blob: 37342788a7f4af859069678cd1462df510d31628 [file] [log] [blame] [view]
# Handling multiple clients
## Prerequisites
This tutorial builds on the [HLCPP getting started tutorials][overview].
## Overview
This tutorial updates the [Echo client][client-tut] from the getting started
tutorials to make multiple connections to the server, and update the
[Echo server][server-tut] to handle multiple client connections. For running
multiple instances of a server (or multiple FIDL protocols), see the
tutorial on [services][services-tut].
The full example code for this tutorial is located at
[`//examples/fidl/hlcpp/multiple_clients`][src].
## Implement the server
In the [previous implementation][server-tut-impl], the `main()` function initialized
a single `fidl::Binding`, and bound any incoming requests to it:
```cpp
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/hlcpp/server/main.cc" region_tag="main" highlight="5,7,8,9,10,12" %}
```
This means that if a second client tries to connect to the server at the same
time, the second call to `binding.Bind` will overwrite the channel from the
first client. To support multiple clients, keep track of multiple
`fidl::Binding`s (one for each client) using a `fidl::BindingSet`:
```cpp
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/hlcpp/multiple_clients/server/main.cc" region_tag="main" highlight="5,7" %}
```
A binding set also simplifies the code since it no longer
needs to create a custom handler. The binding set has a `GetHandler` method,
which returns a handler that creates a new `Binding` and stores it in a vector.
To use `fidl::BindingSet`, include `lib/fidl/cpp/binding_set.h`.
## Implement the client
In order to manage multiple clients connected to a protocol, the FIDL HLCPP
runtime library provides an anolog to `fidl::BindingSet`: the
`fidl::InterfacePtrSet`. Use the class to write code that makes multiple
connections to the same protocol:
```cpp
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/hlcpp/multiple_clients/client/main.cc" region_tag="main" %}
```
The code for setting up a proxy and making requests is the same as in the
[client tutorial][client-main] except it uses
an interface pointer set to simplify the process of broadcasting a message
to a set of clients. An added benefit of using `fidl::InterfacePtrSet` and
`fidl::BindingSet` is that any binding or interface pointer that experiences an
error on its channel is automatically removed from the set.
To use `fidl::InterfacePtrSet`, include `lib/fidl/cpp/interface_ptr_set.h`.
## Run the example
In order for the client and server to communicate using the `Echo` protocol,
component framework must route the `fuchsia.examples.Echo` capability from the
server to the client. For this tutorial, a [realm][glossary.realm] component is
provided to declare the appropriate capabilities and routes.
Note: You can explore the full source for the realm component at
[`//examples/fidl/echo-realm`](/examples/fidl/echo-realm)
1. Configure your build to include the provided package that includes the
echo realm, server, and client:
```posix-terminal
fx set core.x64 --with //examples/fidl/hlcpp:echo-hlcpp-multi-client
```
1. Build the Fuchsia image:
```posix-terminal
fx build
```
1. Run the `echo_realm` component. This creates the client and server component
instances and routes the capabilities:
```posix-terminal
ffx component run /core/ffx-laboratory:echo_realm fuchsia-pkg://fuchsia.com/echo-hlcpp-multi-client#meta/echo_realm.cm
```
1. Start the `echo_client` instance:
```posix-terminal
ffx component start /core/ffx-laboratory:echo_realm/echo_client
```
The server component starts when the client attempts to connect to the `Echo`
protocol. You should see output similar to the following in the device logs
(`ffx log`):
```none {:.devsite-disable-click-to-copy}
[echo_server][][I] Running echo server
[echo_client][][I] Got response Hello echoer 0
```
Terminate the realm component to stop execution and clean up the component
instances:
```posix-terminal
ffx component destroy /core/ffx-laboratory:echo_realm
```
<!-- xrefs -->
[glossary.realm]: /docs/glossary/README.md#realm
[client-tut]: /docs/development/languages/fidl/tutorials/hlcpp/basics/client.md
[client-main]: /docs/development/languages/fidl/tutorials/hlcpp/basics/client.md#main
[server-tut]: /docs/development/languages/fidl/tutorials/hlcpp/basics/server.md
[server-tut-impl]: /docs/development/languages/fidl/tutorials/hlcpp/basics/server.md#impl
[services-tut]: /docs/development/languages/fidl/tutorials/hlcpp/topics/services.md
[src]: /examples/fidl/hlcpp/multiple_clients
[overview]: /docs/development/languages/fidl/tutorials/hlcpp/README.md