Search code examples
scalaactordisconnect

How do I disconnect a Scala Remote Actor?


In scala it is very easy to make a connection to a remote actor, but the documentation does not tell me anything about disconnecting. Simply throwing away the reference does not work, because remote actors are actors, so these won't be collected until stopped. So how do I disconnect?

This does not Terminate after exit:

import actors.{DaemonActor,remote}
import remote.{RemoteActor,Node}

object SimpleClient{
    val messageHandler = new DaemonActor{
        def act{
            loop{
                react{
                    case message:String =>
                        println("got message: " + message)
                    case _ =>
                }
            }
        }
        start
    }

    def main(args:Array[String]){
        val server = RemoteActor.select(Node("localhost",9999),'server)
        server.send('Connect,messageHandler)

        var exit = false
        while(!exit){
            val message = Console.readLine
            if(message == "exit" || message == "quit") {
                exit = true
                server ! 'Disconnect
            }
            else
                server ! message
        }
    }
}

This is the Server:

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

object Server extends Actor{
    val clients = new collection.mutable.HashSet[OutputChannel[Any]]
    def act{
        loop{
            react{
                case 'Connect =>
                    clients += sender
                case 'Disconnect =>
                    clients -= sender
                case message:String =>
                    for(client <- clients)
                        client ! message
            }
        }
    }

    def main(args:Array[String]){
        start
        RemoteActor.alive(9999)
        RemoteActor.register('server,this)
    }
}

Solution

  • Here's a working version of your source, with pertinent changes commented inline:

    import actors.{DaemonActor,remote}
    import remote.{RemoteActor,Node}
    
    case class Send(message: String)
    case object Disconnect
    
    object SimpleClient{
        val messageHandler = new DaemonActor{
    
           def act{
              // keep the reference to the proxy inside the client-side actor
              val server = RemoteActor.select(Node("localhost",9999),'server)
              server ! 'Connect
              loop{
                 react{
                    case message:String =>
                       println("got message: " + message)
                    case Send(message) => server ! message
                    case Disconnect => { 
                       // disconnect and exit the client-side actor
                       server ! 'Disconnect //'
                       exit
                    }
                    case _ =>
                  }
              }
          }
          start
       }
    
       def main(args:Array[String]){
          var exit = false
          while(!exit){
             val message = Console.readLine
             if(message == "exit" || message == "quit") {
                exit = true
                // tell the client-side actor to exit
                messageHandler ! Disconnect
             } else {
                messageHandler ! Send(message)
             }
          }
       }
    }