Alexander Kondaurov
Alexander Kondaurov

Reputation: 4123

How to create tcp server with akka?

I'm trying to create simple tcp server with help of akka.

My main

import java.net.InetSocketAddress

import akka.actor._
import akka.io._
import Tcp._


object Main extends App {

    implicit val actorSystem: ActorSystem = ActorSystem()

    val serverRef = actorSystem.actorOf(server.Server.props)

    val tcpManager = IO(Tcp)

    tcpManager ! Bind(serverRef, new InetSocketAddress("localhost", 8099))


}

My server actor:

package server

import akka.actor._
import akka.io.Tcp
import Tcp._


object Server {

def props = Props(new Server())

class SimplisticHandler extends Actor {
    def receive = {
        case Received(data) => sender() ! Write(data)
        case PeerClosed     => context.stop(self)
    }
}

}

class Server extends Actor {

    override def receive: Receive = {

        case b @ Bound(localAddress) =>
            println(s"connected to ${localAddress.toString}")
            context.parent ! b

        case CommandFailed(_: Bind) => context.stop(self)

        case c @ Connected(remote, local) =>
            val handler = context.actorOf(Server.props)
            val connection = sender()
            connection ! Register(handler)

            case msg =>
                println("Unknown message")
    }

}

But when i run it i get dead letter log event:

table [INFO] [11/08/2019 18:34:11.558] [default-akka.actor.default-dispatcher-6] [akka://default/deadLetters] Message [akka.io.Tcp$Bound] from Actor[akka://default/system/IO-TCP/selectors/$a/0#-176629096] to Actor[akka://default/deadLetters] was not delivered. [1] dead letters encountered. If this is not an expected behavior then Actor[akka://default/deadLetters] may have terminated unexpectedly. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.

Upvotes: 0

Views: 727

Answers (1)

Daniel
Daniel

Reputation: 783

The Bind message should be sent from an actor. That actor will eventually receive Bound message from TCP manager (or CommandFailed). In this case, Server actor should send Bind message. For instance:

class Server extends Actor {

    IO(Tcp) ! Bind(self, new InetSocketAddress("localhost", 8099)) //<--------

    override def receive: Receive = {

        case b @ Bound(localAddress) =>
            println(s"connected to ${localAddress.toString}")
            context.parent ! b

        case CommandFailed(_: Bind) => context.stop(self)

        case c @ Connected(remote, local) =>
            val handler = context.actorOf(Server.props)
            val connection = sender()
            connection ! Register(handler)

            case msg =>
                println("Unknown message")
    }

}

Upvotes: 1

Related Questions