如何在一个非常简单的scala服务器程序中添加多线程/多客户端功能?

时间:2015-08-07 23:25:46

标签: multithreading scala

scala新手在这里,

我故意使用旧版scala 2.7.5

这适用于我需要与此服务器代码一起使用的旧库的兼容性

val server = new ServerSocket(9999)
println("Server initialized:")
val client = server.accept

/* Initalize a big service here -> takes >10 seconds */


while(true){

  val in = new BufferedReader(new InputStreamReader(client.getInputStream)).readLine
  val out = new PrintStream(client.getOutputStream)

  println("Server received:" + in)
  out.println("Message received")
  out.flush
}

基本上,这适用于单个客户端。但它不会从另一个客户端连接,因为它将始终在while循环

内运行

我需要修改代码来处理来自多个客户端的请求

因此,我可以在不编写多线程程序的情况下这样做吗?

如果没有,是否有人可以帮助我使用代码片段为此程序添加基本线程?

1 个答案:

答案 0 :(得分:0)

您希望在非阻塞模式下使用NIO Channels - 这将允许您使用单个线程复用多个输入流。 This is a tutorial in the NIO SocketChannel以及如何将其切换为非阻止模式的说明,以及来自同一作者的this is a tutorial on using SelectorsSocketChannel是您用来读取套接字的内容,Selector是您用来复用频道的内容。

从上面链接的教程:

SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
socketChannel.connect(new InetSocketAddress("http://jenkov.com", 80));
while(! socketChannel.finishConnect() ){
  //wait, or do something else...    
}

在非阻塞read上调用SocketChannel可能会返回零字节,因此请检查返回的字节数。

至于Selector(再次来自教程)

Selector selector = Selector.open();
// OP_READ means that the Selector is interested in read events
SelectionKey key1 = socketChannel1.register(selector, SelectionKey.OP_READ);
SelectionKey key2 = socketChannel2.register(selector, SelectionKey.OP_READ);
Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();
while(keyIterator.hasNext()) {
    SelectionKey key = keyIterator.next();
    if (key.isReadable()) {
        // read from the channel
    }
}