I’m trying to build a simple TCP-Server which can accept connections and data from multiple devices. On the other hand the server should be able to send data to a specified device. Building this based on actors seems pretty straightforward:
private val devices: mutable.Map[String, ActorRef] = mutable.Map.empty
def receive: Receive = {
case Tcp.Received(message) => {
var data = parse(message)
devices.update(data.deviceId, sender())
...
}
case outgoingMessage: OutgoingTcpMessage =>
devices.get(outgoingMessage.deviceId).foreach(_ ! Tcp.Write(outgoingMessage.message))
Not actually sure if it would work exactly like this, but seems like this could go in the right direction.
Now all this should work encrypted over TLS. From what I could find it seems easier to use akka streams to wrap everything in TLS. So now I’m trying to reimplement my server with akka streams.
From the documentation a simple TCP-server:
val connections: Source[IncomingConnection, Future[ServerBinding]] =
Tcp(system).bind(host, port)
connections.runForeach { connection =>
println(s"New connection from: ${connection.remoteAddress}")
val echo = Flow[ByteString]
.via(Framing.delimiter(ByteString("\n"), maximumFrameLength = 256, allowTruncation = true))
.map(_.utf8String)
.map(_ + "!!!\n")
.map(ByteString(_))
connection.handleWith(echo)
}
Seems like it would be easy to implement the receiving part but I dont see how I can send the outgoing messages. From the documentation sending a message to all devices would be simply:
val welcome = Source.single(welcomeMsg)
and then calling merge(welcome) on the echo-flow.
But I can’t figure out how work in the Map which maps deviceId to the correct connection so I can send messages to the correct device.
Is there a way to implement this following the above scheme or am I heading in a wrong direction?
Quite new to akka so feel free to question my whole approach as well. Not set on doing it exactly this way, just what I came up with reading the docs and SO.