1

I am using akka-io to create a Tcp Client Actor that communicates with a non-jvm tcp (non-akka) server over a socket. Because akka-io sends ByteString and the program expects a regular String outputted to it, the ByteString message is never processed. A very crude java based approach to this actually works:

override def receive: Receive = {
    case ClientTcpActor.Start =>
      val socket = new Socket(socketAddress.getHostName, socketAddress.getPort)
      val out = new PrintWriter(socket.getOutputStream, true)
      out.println("Hello World!")
      import java.io.BufferedReader
      import java.io.InputStreamReader
      val is = socket.getInputStream
      val isr = new InputStreamReader(is)
      val br = new BufferedReader(isr)
      val message = br.readLine
      println(s"Message received from the server : $message")
}

I am able to send a message to the tcp port and receive a response back.

However, this akka-io approach doesnt work. Specifically, I never receive data back from the socket because the external application cant process the ByteString sent by the Write object

def receive: PartialFunction[Any, Unit] = {
    case CommandFailed(_: Connect) =>
      log.info("Connection failed.")
      context stop self

    case c@Connected(_, _) =>
      log.info("Connect succeeded.")
      val connection = sender()
      connection ! Register(self)
      val message = ByteString("hello world")
      log.info(s"Sending request message ${message}")
      connection ! Write(message)

    case Received(data) =>
      log.info(data.toString())


    case _: ConnectionClosed =>
      log.info("Connected is closed!")
    case _ =>
      log.info("Something else is up.")
  }

I also created my own akka-IO server application that processes data on the same port and verified that I was actually sending the message to the port, but the akka server actor was needed to process the decoding of the ByteString

Im hoping this is some easy-fix I'm overlooking.

Zee
  • 1,321
  • 2
  • 18
  • 41

1 Answers1

0

Over the network there is no such thing as String or ByteString, there are only bytes. ByteString is essentially just a wrapper around byte arrays to ensure they are not mutated (as that would then require synchronisation for it to be safe to share between threads/actors). When you create a ByteString from a String it will use an encoding (UTF8 in this case) to encode the string into bytes.

Can't say what is wrong from the pieces of your code that you included, but there is a complete example client in the docs that may be helpful to compare your code to: http://doc.akka.io/docs/akka/current/scala/io-tcp.html#Connecting

johanandren
  • 11,249
  • 1
  • 25
  • 30
  • yeah I based my code on that example and despite doing so it did not work as expected. I ended up using a variation on the java-esque tcp client code I wrote above which did solve my problem – Zee May 12 '17 at 14:09
  • It does look different form the docs though. Note that if you use the old Java sockets API you are blocking the thread on network input, so you should make sure you run the actor on a dispatcher dedicated to handling blocking (for more info read Konrads excellent answer here: http://stackoverflow.com/questions/34641861/akka-http-blocking-in-a-future-blocks-the-server/34645097#34645097). – johanandren May 12 '17 at 14:15