Сервер Scala должен управлять множеством клиентов

Нам нужно создать сервер со Scala RemotActors, который может обрабатывать несколько клиентов. Например, чат-сервер, который отвечает на каждое полученное сообщение всем подключенным клиентам. Наша текущая попытка состоит в том, чтобы создать по одному субъекту для каждого клиента, который может прослушивать все полученные сообщения и отвечать на них. Но динамическая регистрация актеров не работает.

import actors.{Actor, OutputChannel}
import actors.remote.{RemoteActor, Node, FreshNameCreator}

object Server extends Actor{

    class ConnectedClient(id:Symbol,out:OutputChannel[Any]) extends Actor{
        start

        def act {
            loop {
                react {
                    case m:ServerMessage =>
                        out ! m
                    case m:ClientMessage =>
                        Server ! m
                }
            }
        }
    }

    RemoteActor.alive(9999)
    RemoteActor.register('server, this ) //'
    println("Server started.")

    var clients = new collection.mutable.HashSet[ConnectedClient]

    def act  {
        loop {
            react {
                case 'connect => //'
                    println("Server: New Client")
                    val id = FreshNameCreator.newName
                    val client = new ConnectedClient(id,sender)
                    clients += client
                    RemoteActor.register(id, client) // This seems not to work
                    reply(id)
                case ClientMessage(m) =>
                    println("Server: received: " + m)
                    for( client <- clients )
                        client ! ServerMessage(m)
                case m =>
                    println("Server: Unknown Message: " + m)
            }
        }
    }
}

case class ServerMessage(m:String)
case class ClientMessage(m:String)

class Client(serverNode:Node) extends Actor{

    println("Client: connecting...")
    val server = RemoteActor.select( serverNode, 'server ) //'

    start

    def act{

        //we want the symbol that is intended to identify our personal Actor at the Server
        val id = (server !? 'connect).asInstanceOf[Symbol] //'
        val personalServer = RemoteActor.select( serverNode, id)

        println("Client["+id+"]: connected")

        loop{
            react{
                case ServerMessage(m) => 
                    println("Client["+id+"]: " + m)
                case m:String =>
                    personalServer ! ClientMessage(m)
                case m =>
                    println("Server: Unknown Message: " + m)
            }
        }
    }
}

object Main{
    def main(args:Array[String]){

        Server.start

        val serverNode = Node("localhost",9999)
        val clientA = new Client(serverNode)
        val clientB = new Client(serverNode)
        val clientC = new Client(serverNode)

        clientA ! "Hello. I am A."
        clientB ! "Hello. I am B."
        clientC ! "Hello. I am C."
    }
}

person Arne    schedule 13.02.2011    source источник


Ответы (1)


Вы должны вызвать alive и register внутри метода act.

person ron    schedule 16.04.2011
comment
да, я уже обнаружил это сам, любая идея, почему я должен это делать? - person Arne; 18.04.2011
comment
Просто дикая догадка, но поскольку каждый поток действует как актор, вызов их из основного потока регистрирует внешнего актора, а не того, который вам нужен. Хотя бы попробовать. - person ron; 18.04.2011