2011-01-26 86 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