Is there any way in Akka to achieve packet frame just like in Erlang with {packet,4}? Packet looks something like this:
4 bytes length in big endian | body...
For example:
00 00 00 05 H E L L O 0 0 0 5 W O R L D
Would be two packets "HELLO" and "WORLD", but they are received as one.
Or
00 00 00 05 H E L L
Now Akka receives these 8 bytes, but one more is still missing and it would be received in next call to "receive"
Problem is that my actor's receive is always called with partial or full request, but I would like to only get "body" part in receive and only when it's fully received.
So all that would be needed is that it first reads those 4 bytes and then waits until it reads other N bytes (N = length in 4 bytes header) and THEN it sends message to my actor. Is it possible somehow?
My server code:
import java.net.InetSocketAddress
import akka.actor.{Props, Actor}
import akka.io.Tcp.Bind
import akka.io.{IO, Tcp}
class Server extends Actor{
import context.system
import Tcp._
IO(Tcp) ! Bind(self, new InetSocketAddress("0.0.0.0", 1234))
def receive ={
case bound @ Bound(localAddr) =>
println("Server is bound to "+localAddr.toString())
case failed @ CommandFailed(_ : Bind) =>
context stop self
case connected @ Connected(remote, local) =>
val handler = context.actorOf(Props[ClientHandler])
val connection = sender()
println(remote.toString + "connected to "+local.toString())
connection ! Register(handler)
}
}
As far as I am aware, there is no library function for this in Akka or Scala. Akka trades in ByteString for reading and writing so I put together a trait which will do exactly what you request. You pass it a ByteString as sent to your actor. It then breaks the stream up according to the packet lengths in the headers. It is stateless so it returns a tuple containing a list of extracted packets and any unused data from the TCP stream as a ByteString. You concatenate new TCP data to the unused portion of the stream returned in this byte string as shown in the example below.
Usage from an actor is as folllows: