Skip to content

Commit 5e92a01

Browse files
authored
Merge pull request #2358 from ScalaWilliam/handle-errors-client-socket
Add a note to handle client socket stream errors.
2 parents 24370ab + 99b75be commit 5e92a01

File tree

2 files changed

+6
-0
lines changed

2 files changed

+6
-0
lines changed

io/src/main/scala/fs2/io/net/SocketGroup.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ trait SocketGroup[F[_]] {
5959
* client sockets -- one per client that connects to the bound address/port.
6060
*
6161
* When the stream terminates, all open connections will terminate as well.
62+
* Because of this, make sure to handle errors in the client socket Streams.
6263
*
6364
* @param address address to accept connections from; none for all interfaces
6465
* @param port port to bind
@@ -71,6 +72,8 @@ trait SocketGroup[F[_]] {
7172
): Stream[F, Socket[F]]
7273

7374
/** Like [[server]] but provides the `SocketAddress` of the bound server socket before providing accepted sockets.
75+
*
76+
* Make sure to handle errors in the client socket Streams.
7477
*/
7578
def serverResource(
7679
address: Option[Host] = None,

site/io.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ def echoServer[F[_]: Concurrent: Network]: F[Unit] =
142142
.interleave(Stream.constant("\n"))
143143
.through(text.utf8Encode)
144144
.through(client.writes)
145+
.handleErrorWith(_ => Stream.empty) // handle errors of client sockets
145146
}.parJoin(100).compile.drain
146147
```
147148

@@ -152,6 +153,8 @@ we read from the client socket, UTF-8 decode the received bytes, extract individ
152153

153154
Since we mapped over the infinite client stream, we end up with a `Stream[F, Stream[F, Unit]]`. We flatten this to a single `Stream[F, Unit]` via `parJoin(100)`, which runs up to 100 of the inner streams concurrently. As inner streams finish, new inner streams are pulled from the source. Hence, `parJoin` is controlling the maximum number of concurrent client requests our server processes.
154155

156+
In joining all these streams together, be prudent to handle errors in the client streams.
157+
155158
The pattern of `Network[F].server(address).map(handleClient).parJoin(maxConcurrentClients)` is very common when working with server sockets.
156159

157160
A simpler echo server could be implemented with this core logic:

0 commit comments

Comments
 (0)