简体   繁体   中英

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

I'm trying to allow multiple connections to a little Java server type app. It works fine as is, but if one connection opens and then hangs, all subsequent connections will hang. I'm not sure how to go about handling each connection, up to about 20 concurrent ones in their own thread while keeping track of which thread belongs to which client etc. The code I have so far is:

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);
    }
}

Whenever I need to write a socket server I avoid using low-level JVM classes because of the need to handle all the nitty-gritty details.

Instead I use Apache Mina . This ia a Java library for writing high-performance non-blocking multi-threaded socket servers.

An added benefit of using Mina is that it enforces clean architecture (IoFilters, protocol decoders) which makes your code more modular and makes it more maintainable.

Unless you really want to write an NIO server as a learning exercise I would recommend using Netty . Like Mina that Peter mentioned it is also a library for writing high performance servers.

I recently moved from using my own NIO code to this library and it has made my code so much cleaner.

My solution i Netty and Executor which creates ThreadPool. You simply add handler do Netty's pipeline, which call executor witch ChannelBuffer as a parameter. Than every client request will be processed by separate thread.

Look at the examples

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM