Akka BindException when trying to connect to remote actor: Address already in use

actor, akka, scala

Solution

When running several instances on same machine you need to configure different ports for them. In this example it is only the server that needs a know port (9000). For the clients you can use 0 for a random available port.

Define another configuration file for the clients. `client.conf`:

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

Start the `ActorSystem` in the clients with this configuration:

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

In the clients you will lookup the server with:

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

Problem

I am experimenting with Akka remote actors, trying to establish a simple 2 player game over the network. This answer to an earlier question gave me a really good starting point but now I'm having a hard time understanding how to adapt it to my situation. ISTM that the original is connecting twice from the same client (see commented section below). What I want to do is run it twice from separate clients, but when I do I get a BindException, Address already in use. I guess that's because each time I run the code it attempts to start the server? I need a situation where I can start and stop the master actor independently of clients connecting and disconnecting. The (minimal) Akka config and exception are after the code: ``` 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) } }))*/ } ``` Config: ``` 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.

Original source