2011-01-26 67 views
3

我想允许多个连接到一个小型的Java服务器类型的应用程序。它可以正常工作,但如果一个连接打开然后挂起,则所有后续连接都将挂起。我不知道如何去在自己的线程处理每个连接,高达约20个并发的人,同时跟踪哪个线程属于哪个客户端等我到目前为止的代码是:如何使这个非阻塞服务器成为多线程?

private void init() { 
    try { 
     // Create the server socket channel 
     ServerSocketChannel server = ServerSocketChannel.open(); 
     // nonblocking I/O 
     server.configureBlocking(false); 
     // host-port 
     server.socket().bind(new InetSocketAddress(host, port)); 
     System.out.println("Server connected on " + host + ":" + port); 
     // Create the selector 
     Selector selector = Selector.open(); 
     // Recording server to selector (type OP_ACCEPT) 
     server.register(selector, SelectionKey.OP_ACCEPT); 
     // Infinite server loop 
     for (;;) { 
      // Waiting for events 
      selector.select(); 
      // Get keys 
      Set keys = selector.selectedKeys(); 
      Iterator i = keys.iterator(); 
      // For each keys... 
      while (i.hasNext()) { 
       SelectionKey key = (SelectionKey) i.next(); 
       // Remove the current key 
       i.remove(); 
       // if isAccetable = true 
       // then a client required a connection 
       if (key.isAcceptable()) { 
        // get client socket channel 
        SocketChannel client = server.accept(); 
        // Non Blocking I/O 
        client.configureBlocking(false); 
        // recording to the selector (reading) 
        client.register(selector, SelectionKey.OP_READ); 
        continue; 
       } 
       // then the server is ready to read 
       if (key.isReadable()) { 
        SocketChannel client = (SocketChannel) key.channel(); 
        // Read byte coming from the client 
        int BUFFER_SIZE = 32; 
        ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE); 
        try { 
         client.read(buffer); 
        } catch (Exception e) { 
         // client is no longer active 
         e.printStackTrace(); 
         continue; 
        } 
        buffer.flip(); 
        Charset charset = Charset.forName("ISO-8859-1"); 
        CharsetDecoder decoder = charset.newDecoder(); 
        CharBuffer charBuffer = decoder.decode(buffer); 
        Handler dataHandler = new Handler(); 
        client.write(ByteBuffer.wrap(dataHandler.processInput(charBuffer.toString()).getBytes())); 
        client.socket().close(); 
        continue; 
       } 
      } 
     } 
    } catch (IOException ex) { 
     Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex); 
    } 
} 
+0

我只想用阻塞NIO,并且每个客户端一个线程,它会更简单,可扩展到10K的连接。它也可以更高效。 – 2011-01-26 09:18:17

回答

1

我的解决方案我创建ThreadPool的Netty和Executor。 您只需添加处理程序do Netty的管道,该管道将执行程序WitchCharingBuffer作为参数调用。 比每个客户端请求都会由单独的线程处理。

看那examples

+0

现在看看netty感谢: ) – zcourts 2011-01-26 12:40:09

3

无论何时我需要编写套接字服务器,我都会避免使用低级别的JVM类,因为需要处理所有基本的细节。我想用Apache Mina。这是一个用于编写高性能无阻塞多线程套接字服务器的Java库。

使用Mina的一个附加好处是它强制执行clean architecture(IoFilters,协议解码器),它使您的代码更加模块化并且使其更易于维护。

+0

听起来很有希望...我会看看并回来。 我真的需要熟悉更多的Apache项目...... – zcourts 2011-01-26 09:27:29

2

除非你真的想写一个NIO服务器作为学习练习,否则我会推荐使用Netty。和Mina一样,Peter也提到它也是编写高性能服务器的库。

我最近从使用我自己的NIO代码移动到这个库,它使我的代码变得更干净。

+0

我所有的东西都会让生活变得更简单,没有太多的开销,所以我也会结帐netty – zcourts 2011-01-26 12:41:07