簡體   English   中英

如何使該非阻塞服務器成為多線程?

[英]How do I make this non-blocking server multi-threaded?

我試圖允許到一個小型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);
    }
}

每當我需要編寫套接字服務器時,由於需要處理所有細節問題,我避免使用低級JVM類。

相反,我使用Apache Mina 這是一個Java庫,用於編寫高性能的非阻塞多線程套接字服務器。

使用Mina的另一個好處是,它強制執行了干凈的體系結構 (IoFilter,協議解碼器),這使您的代碼更加模塊化,並且更具可維護性。

除非您真的想編寫一個NIO服務器作為學習練習,否則我建議使用Netty 就像彼得提到的Mina一樣,它也是用於編寫高性能服務器的庫。

最近,我從使用自己的NIO代碼移到了該庫,它使我的代碼更加簡潔。

我的解決方案是創建線程池的Netty和Executor。 您只需添加處理程序來執行Netty的管道,即可將執行程序女巫ChannelBuffer作為參數調用。 超過每個客戶端請求將由單獨的線程處理。

例子

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM