Richard Searle

home

Read-only TCP client in Akka Streams

24 Nov 2016

This stackoverflow question concerns how to implement a read-only TCP client using Akka Streams.

The key issue was the requirement that a Flow has both a Sink (to process the incoming bytes) and a Source. For this use case the Source does not generate any bytes, but must still be specified.

Source.empty would appear to satisfy the requirement, but it immediately completes the Flow. The above stackoverflow suggests using Source(List(ByteString.empty)), but that also completes the Flow.

We need an incomplete Source, which is most easily achieved using Source.maybe, which never completes and explicitly specifies that no data will write to the Flow.

The core code is then

  val clientFlow: Flow[ByteString, ByteString, Future[OutgoingConnection]] =
     Tcp().outgoingConnection(new InetSocketAddress("127.0.0.1", 2558))
  val result: (Promise[Option[Nothing]], Future[Done]) =
     clientFlow.runWith(Source.maybe, Sink.foreach(bs => println(bs.utf8String)))

The Promise[Option[Nothing]] provides a hook to cleanly terminate the Flow, using
result._1.complete(Try(None)).

The Future[Done] provides a hook to determine the Flow has terminated, e.g. Await.ready(result._2, 100 seconds).