3

私はAkkaのリモートアクターを実験しており、ネットワーク上で単純な2人用ゲームを確立しようとしています。以前の質問に対するこの答えは私に本当に良い出発点を与えました、しかし今私はそれを私の状況に適応させる方法を理解するのに苦労しています。オリジナルが同じクライアントから2回接続しているISTM(以下のコメントセクションを参照)。私がやりたいのは、別々のクライアントから2回実行することですが、実行すると、BindException、Addressがすでに使用されています。コードを実行するたびにサーバーを起動しようとするためだと思いますか?クライアントの接続と切断に関係なく、マスターアクターを開始および停止できる状況が必要です。(最小限の)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 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。

4

3 に答える 3

12

同じマシンで複数のインスタンスを実行する場合は、それらに異なるポートを構成する必要があります。この例では、既知のポート(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")
于 2013-03-21T13:19:55.903 に答える
4

クライアント構成用のポートを個別に指定するか、サーバー側構成のポートを2552から別のポートに変更する必要があります。2552はakkaアクターシステムのデフォルトポートです。クライアント側でルックアップ用のアクターシステムを作成すると(同じマシン上で)、明示的に指定されていない場合はポート2552にもバインドしようとするため、このエラーが発生します。

于 2013-04-09T07:16:16.367 に答える
0

もう1つの簡単な方法は、誰かがすべてのターミナルウィンドウを閉じて、新しいウィンドウを開くことです。すべてのノードを停止した後でも同じ問題に直面していましたが、新しいノードを開く代わりに同じターミナルで実行されていました

于 2020-08-04T18:14:08.890 に答える