views:

125

answers:

3

Hi.

I'm playing with Remote Actors but I'm facing some difficulties.

Consider this server:

object Server {
    def main(args: Array[String]) {
        val server = new Server
        server.start
    }
}

class Server extends Actor {
    RemoteActor.alive(12345)
    RemoteActor.register('server, this)

    def act() {
        while(true) {
            receive { case x => println(x) }
        }
    }
}

I have written a simple client:

object Client {
    def main(args: Array[String]) {
        val server = RemoteActor.select(Node("localhost", 12345), 'server)
        server ! "Hey!"
    }
}

As expected, the server prints "Hey!".

However, unexpectedly, the client application never terminates!

It looks like many thread have been started on the client application, but they keep running after my main function finishes!

What can I do to terminate the client application? And more: what if I want my client to be able to start and stop connections? How can I achieve this?

Some additional info (based on replies): I'm using scala 2.8.0.final, and what I'm talking about here is a standalone server and a standalone client. They should be launched like $ scala Server and $ scala Client. What I want to happen is that the application "Client" should finish, but it never happens.

Thanks!

A: 

The following code works for me:

import scala.actors.Actor
import scala.actors.remote.RemoteActor
import scala.actors.remote.RemoteActor._
import scala.actors.remote.Node

object Client {
    def main(args: Array[String]) {
        val server = RemoteActor.select(Node("localhost", 12345), 'server)
        server ! "Hey!"
        exit
    }
}
Jus12
Yeah, that would work, but it does not smell good. If this is the only solution, then to end the threads created by the client we would need to kill the whole application...
Bruno Reis
+1  A: 

In the client code, wrap the select and related statements in an Actor.actor block, then call exit() at the end of the block. It doesn't seem like you should need to do this, but this was the only way I found that terminates all the threads that the select call starts.

Kevin
Hmm, good idea! Thanks!
Bruno Reis
+2  A: 

Do not send messages to other actors from outside an actor. While Scala will happily accept it, it has consequences such as you are seeing. Here's an equivalent code that works:

import scala.actors.remote._

object Act extends scala.actors.Actor {
  def act = {
        val server = RemoteActor.select(Node("localhost", 12345), 'server)
        server ! "Hey!"
  }
}

object Client {
    def main(args: Array[String]) {
      Act.start()
    }
}

Or, more simply,

import scala.actors.Actor.actor
import scala.actors.remote._

object Client {
    def main(args: Array[String]) {
      actor {
        val server = RemoteActor.select(Node("localhost", 12345), 'server)
        server ! "Hey!"
      }        
    }
}
Daniel
Excellent! Thanks for the information.
Bruno Reis