简体   繁体   中英

One thread one ByteBuffer NIO

I am wondering about the best way to implement a multiuser NIO server with one thread and one buffer. Currently I use a selector to achieve this but I have only figured out how to do reading on all the clients. I am having trouble implementing write using the one buffer. Do I need a second buffer for writes? Or do I have to (unfortunately) have a write buffer per client? I wrote this example to easily show how I'm doing stuff, just so you know all processing happens within the scheduler's thread, I am not interacting with any state through another thread!

ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();

ServerSocketChannel server = ServerSocketChannel.open();
Selector selector = Selector.open();
ByteBuffer buffer = ByteBuffer.allocateDirect(8192);
Map<SelectionKey, SocketChannel> clients = new HashMap<>();

server.configureBlocking(false);
server.register(selector, SelectionKey.OP_ACCEPT);
server.bind(new InetSocketAddress(43594));

scheduler.scheduleAtFixedRate(() -> {
    try {
        selector.selectNow();
        Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
        while (keys.hasNext()) {
            SelectionKey key = keys.next();
            keys.remove();
            if (key.isAcceptable()) {
                for (int i = 0; i < 16; i++) {
                    SocketChannel client = server.accept();
                    if (client == null)
                        break;
                    client.configureBlocking(false);
                    SelectionKey clientKey = client.register(selector, SelectionKey.OP_READ);
                    clients.put(clientKey, client);
                }
            }
            if (key.isReadable()) {
                SocketChannel client = clients.get(key);
                if (client != null) {
                    buffer.clear();
                    client.read(buffer);
                    buffer.flip();
                    // do stuff with buffer
                }
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}, 600, 600, TimeUnit.MILLISECONDS);

You can't. For anything less trivial than an echo server, you need at least one buffer per channel, possibly two (read and write). Otherwise you can't possibly deal with partially read requests, or partially written responses.

You can associate the buffers with the channel via the SelectionKey attachment.

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