Как создать tcp сервер с аккой? - PullRequest
0 голосов
/ 08 ноября 2019

Я пытаюсь создать простой tcp сервер с помощью akka.

Мой главный

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))


}

Мой серверный актер:

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")
    }

}

Но когда язапустить его, я получаю событие журнала мертвых букв:

таблица [INFO] [11/08/2019 18: 34: 11.558] [default-akka.actor.default-dispatcher-6] [akka:// default / deadLetters] Сообщение [akka.io.Tcp $ Bound] от Actor [akka: // default / system / IO-TCP / selectors / $ a / 0 # -176629096] для Actor [akka: // default /deadLetters] не было доставлено. [1] встреченные мертвые буквы. Если это не ожидаемое поведение, то Actor [akka: // default / deadLetters] мог неожиданно прекратить работу. Это ведение журнала можно отключить или настроить с помощью параметров конфигурации «akka.log-dead-letters» и «akka.log-dead-letters-во время завершения работы».

1 Ответ

1 голос
/ 09 ноября 2019

Сообщение Bind должно быть отправлено актером. Этот субъект в конечном итоге получит сообщение Bound от диспетчера TCP (или CommandFailed). В этом случае Server актер должен отправить Bind сообщение. Например:

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")
    }

}
...