Using Scala with Akka IO is there a way to have an Actor strictly for listening and then when a connection is established create a new actor that will then be responsible for that Socket (Reading, Writing, etc)?
So far I have this. The problem is that the Server actor is receiving the data. I would like to transfer ownership of the socket to the new created Client actor so that it receives any messages related to the socket. Anyone know how to do that?
Edit: added solution. I just needed to pass the ActorRef into the curried parameter of accept
import akka.actor._
import akka.actor.IO.SocketHandle
import java.net.InetSocketAddress
/**
* Purpose:
* User: chuck
* Date: 17/01/13
* Time: 5:37 PM
*/
object Main {
class Server extends Actor {
override def preStart() {
IOManager(context.system) listen new InetSocketAddress(3333)
}
def receive = {
case IO.NewClient(server) =>
val client = context.actorOf(Props(new Client()))
server.accept()(client)
println("Client accepted")
case IO.Read(socket, bytes) =>
println("Server " + bytes)
}
}
class Client() extends Actor {
def receive = {
case IO.Read(socket, bytes) =>
println("Client " + bytes)
case IO.Closed(socket, reason) =>
println("Socket closed " + reason)
}
}
def main(args: Array[String]) {
val system = ActorSystem()
system.actorOf(Props(new Server))
}
}
Thanks!
To make the answer a little more visible :
From the Akka documentation for ServerHandle
:
def accept ()(implicit socketOwner: ActorRef): SocketHandle
socketOwner ActorRef that should receive events associated with the SocketChannel. The ActorRef for the current Actor will be used implicitly.
If nothing is passed to the curried parameter (only calling server.accept()
), the current Actor (Server) will receive events from the SocketChannel. However as the method signature suggests, you can pass an ActorRef to the curried parameter so that events occurring on the SocketChannel will be handled by this new Actor.
Leaving us to the solution added by the owner of the question :
def receive = {
case IO.NewClient(server) =>
val client = context.actorOf(Props(new Client()))
server.accept()(client) // Transferring ownership of the socket to a new Actor
println("Client accepted")
case IO.Read(socket, bytes) =>
println("Server " + bytes)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With