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)
}
}
[Disclaimer: I'm PO of Akka]
May I suggest taking a look at Akka, which was built with Remote Actors in mind from day 1? www.akka.io
Your question is not really clear enough about what problem you think you are experiencing. Actors do not "connect" to each other (like a socket). You send an actor a message because you have a reference to it (or a proxy, in the case of remote actors).
Having such a reference does not prevent the actor (either actor) from shutting down. If there are no longer any references to an actor and it is not running, there is nothing to stop it being garbage-collected
The Reactor
trait defines protected[actors] def exit(): Nothing
which the actor can call itself upon reception of a message telling it to do so.
sealed trait Msg
case object Apoptosis extends Msg
// ... more messages
class RRActor extends Reactor[Msg] {
def act = loop {
react {
// ... Whatever messages the actor handles
case Apoptosis => this.exit
}
}
}
Edit: I have not tested this ever with remote actors.
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)
}
}
}
}
精彩评论