scala - 尝试连接到远程参与者时出现 Akka BindException : Address already in use

标签 scala akka actor

我正在尝试使用 Akka 远程 Actor,尝试通过网络建立一个简单的 2 人游戏。 This answer之前的问题给了我一个非常好的起点,但现在我很难理解如何使其适应我的情况。 ISTM 认为原始版本是从同一客户端连接两次(请参阅下面的评论部分)。我想做的是从不同的客户端运行它两次,但是当我这样做时,我得到一个 BindException,地址已在使用中。我想这是因为每次我运行代码时它都会尝试启动服务器?我需要一种可以独立于客户端连接和断开来启动和停止主参与者的情况。 (最小)Akka 配置和异常位于代码之后:

import akka.actor._
//example from answer to https://stackoverflow.com/questions/15527193/keeping-references-to-two-actors
// by Patrick Nordwall
case object JoinMsg
case class Msg(s: String)

class Server extends Actor {

  def receive = {
    case JoinMsg =>
      println("got player 1")
      sender ! Msg("Waiting for player 2")
      context.become(waitingForPlayer2(sender))
  }

  def waitingForPlayer2(client1: ActorRef): Actor.Receive = {
    case JoinMsg =>
      println("got player 2")
      sender ! Msg("hi")
      client1 ! Msg("hi")
      context.become(ready(client1, sender))
  }

  def ready(client1: ActorRef, client2: ActorRef): Actor.Receive = {
    case m: Msg if sender == client1 => client2 ! m
    case m: Msg if sender == client2 => client1 ! m
  }
}

/* I want to run this once for each "player" */
object Demo extends App {
  val system = ActorSystem("Game")
  val server = system.actorOf(Props[Server], "server")

  system.actorOf(Props(new Actor {
    server ! JoinMsg
    def receive = {
      case Msg(s) => println(s)
    }
  }))

  /* Rather than connecting twice from the same node, I want to run this
     program twice from different nodes 
    system.actorOf(Props(new Actor {
    server ! JoinMsg
    def receive = {
      case Msg(s) => println(s)
    }
  }))*/
}

配置:

akka {
  actor {
    provider = "akka.remote.RemoteActorRefProvider"
  }
  remote {
    transport = "akka.remote.netty.NettyRemoteTransport"
    netty {
      hostname = "localhost"
      port = 9000
    }
 }
}

异常(exception):

Exception in thread "main" java.lang.ExceptionInInitializerError
    at akkademo.main(akkademo.scala)
Caused by: org.jboss.netty.channel.ChannelException: Failed to bind to: localhost/127.0.0.1:9000
    at org.jboss.netty.bootstrap.ServerBootstrap.bind(ServerBootstrap.java:298)
    at akka.remote.netty.NettyRemoteServer.start(Server.scala:54)
    at akka.remote.netty.NettyRemoteTransport.start(NettyRemoteSupport.scala:90)
    at akka.remote.RemoteActorRefProvider.init(RemoteActorRefProvider.scala:94)
    at akka.actor.ActorSystemImpl._start(ActorSystem.scala:588)
    at akka.actor.ActorSystemImpl.start(ActorSystem.scala:595)
    at akka.actor.ActorSystem$.apply(ActorSystem.scala:111)
    at akka.actor.ActorSystem$.apply(ActorSystem.scala:93)
    at akkademo$.<init>(akkademo.scala:4)
    at akkademo$.<clinit>(akkademo.scala)
    ... 1 more
Caused by: java.net.BindException: Address already in use

TIA。

最佳答案

在同一台计算机上运行多个实例时,您需要为它们配置不同的端口。 在此示例中,只有服务器需要已知端口 (9000)。 对于客户端,您可以使用 0 作为随机可用端口。

为客户端定义另一个配置文件。 client.conf:

akka {
  actor {
    provider = "akka.remote.RemoteActorRefProvider"
  }
  remote {
    transport = "akka.remote.netty.NettyRemoteTransport"
    netty {
      hostname = "localhost"
      port = 0
    }
 }
}

使用以下配置在客户端中启动 ActorSystem:

import com.typesafe.config.ConfigFactory
val system = ActorSystem("Game", ConfigFactory.load("client"))

在客户端中,您将使用以下方式查找服务器:

val server = system.actorFor("akka://Game@localhost:9000/user/server")

关于scala - 尝试连接到远程参与者时出现 Akka BindException : Address already in use,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15547090/

相关文章:

scala - SQLException : unknown database with SQLite and Scala

sql - 使用新的外键 ID 复制数据的方法

akka - 使用 ActorSelection 通配符选择子树中的所有 akka Actor

scala - 重新开始的我的 Actor 所产生的 future 会发生什么

json - 自定义 akka 持久化(播放!)JSON(反)序列化器

Azure Service Fabric 与 Project Orleans 中的参与者粒度

database - AKKA Actor 是优化我的设置的好解决方案吗?

scala - 如果类型是 HList 的成员,我如何检查无形?

java - Scala类继承和方法参数

scala - 使用 TestActorRef 测试 actor 崩溃