markd1
markd1

Reputation: 11

Subsequent Call to Actor Freezes Program

I put together the code below; the intent was to have a non-blocking server accept a connection and then pass off this connection to an actor for further processing. This works the first time through, but on the subsequent request the program freezes at conServ ! servSoc.accept. Any ideas why this is happening?

import java.net._
import java.io._

import java.nio._
import java.nio.channels._

import java.util._

import scala.actors.Actor
import scala.actors.Actor._

def test() = {  
    var channel: ServerSocketChannel = null
    val isa: InetSocketAddress = new InetSocketAddress(23)

    val conServ = actor { 
        react {
            case conn: Socket => {                              
                                try {
                                    var pw: PrintWriter = new PrintWriter(conn.getOutputStream(), true)
                                    pw.println("Current time: " + new Date)
                                    pw.close
                                    conn.close
                                } catch {
                                    case ioe: IOException => println("IOException: " + ioe.getMessage)
                                    case e: Exception => println("Exception: " + e.getMessage)
                                }                               
                            }
        }
    }

    try {
        channel = ServerSocketChannel.open
        channel.configureBlocking(false)
        channel.socket().bind(isa)
        var selector: Selector = Selector.open
        channel.register(selector, SelectionKey.OP_ACCEPT)
        println("** Server ready for requests **")

        while (true) {
            if (selector.select > 0) {
                var selKeys: Set[SelectionKey] = selector.selectedKeys
                var selIt: Iterator[SelectionKey] = selKeys.iterator
                while (selIt.hasNext) {
                    var key: SelectionKey = selIt.next.asInstanceOf[SelectionKey]
                    selIt.remove
                    if (key.isAcceptable) {
                        var ssc: ServerSocketChannel = key.channel.asInstanceOf[ServerSocketChannel]
                        var servSoc: ServerSocket = ssc.socket
                        try {
                            conServ ! servSoc.accept
                        } catch {
                            case ioe: IOException => println(ioe.printStackTrace)
                        }
                    }
                }
            } else {
                continue
            }
        }

    } catch {
        case ioe: IOException => println("Could not listen to port 23. " + ioe.printStackTrace)
        case e: Exception => println("Error: " + e.printStackTrace)
    }
}

test

Upvotes: 1

Views: 128

Answers (2)

huynhjl
huynhjl

Reputation: 41646

Enclose your react in a loop block like this:

val conServ = actor { 
  loop {
    react {
      // ...
    }
  }
}

What happens now, is that your actor is started, processes the first message and is not "reacting" again to process additional message from its queue.

See An actor's act method that uses loop.

Upvotes: 3

thoredge
thoredge

Reputation: 12591

This is what an actor do, treating one message at the time. What you want is a separate thread to handle each request. For this you can try using Futures.

Upvotes: 2

Related Questions