2013-03-21 46 views
2

我正在試驗Akka遠程演員,嘗試通過網絡建立一個簡單的2人遊戲。 This answer以前的問題給了我一個很好的起點,但現在我很難理解如何適應我的情況。 ISTM表示原始連接兩次來自同一客戶端(請參閱下面的註釋部分)。我想要做的是從不同的客戶端運行兩次,但是當我這樣做時,我得到一個BindException,地址已經在使用中。我想這是因爲每次運行代碼時都會嘗試啓動服務器?我需要一種能夠獨立於客戶端連接和斷開連接來啓動和停止主演員的情況。的(最小的)阿卡配置和異常是代碼之後:Akka BindException當試圖連接到遠程actor:地址已在使用

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。

回答

10

在同一臺機器上運行多個實例時,需要爲它們配置不同的端口。 在這個例子中,只有服務器需要知道端口(9000)。 對於客戶端,您可以使用0作爲隨機可用端口。

爲客戶端定義另一個配置文件。 client.conf

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

在客戶端,您將查找與服務器:

val server = system.actorFor("akka://[email protected]:9000/user/server") 
+0

謝謝帕特里克。 'system'的聲明給了我一個錯誤,雖然:必需的類型com.typesafe.config.Config。我使用Akka 2.0.5和Scala 2.9。 – jaybee 2013-03-21 13:29:08

+0

太好了,現在正在爲我工​​作:-)如果有人試圖做同樣的事情,我從https://github.com/akka/akka/tree/v2.0.5/akka-samples/akka-sample複製 - 遠程獲取服務器啓動和工作。 – jaybee 2013-03-21 15:27:51

+1

似乎現在港口需要通過'akka.remote.netty.tcp.port'而不是'akka.remote.netty.port'進行設置。 – phdoerfler 2015-12-11 20:24:15

3

您也需要到指定端口

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

與此配置開始在客戶ActorSystem分別進行客戶端配置或將服務器端配置的端口從2552更改爲其他內容。 2552是akka參與者系統的默認端口,當您在客戶端創建參與者(在同一臺計算機上)時,它還會嘗試綁定到端口2552(如果未明確指定),因此會出現此錯誤。

相關問題