简体   繁体   中英

In JAVA nio selector, when should I register the 'write operation'?

I am learning Java nio selector. In my understanding, I thought the steps using selector is to firstly I register the my interest operations and then I can check the ready set and finally I can do the operations corresponding my interest operations. I don't know why in this code the writing process can happen in the block of if (key.isReadable()){...} but not if (key.isWritable){...} and why writing operation is not registered?

Iterator keys = sel.selectedKeys().iterator();
while (keys.hasNext()) {
    SelectionKey key = (SelectionKey)keys.next();

    if (!key.isValid()) 
        continue;

    if (key.isAcceptable()) {
        // increase the counter
        connection++;

        // remove accept request
        keys.remove();

        // ACCEPT: get the server channel
        ServerSocketChannel ssc = 
                (ServerSocketChannel) key.channel();

        // init a socket for a client
        SocketChannel nsc = ssc.accept();
        nsc.configureBlocking(false);

        // register the socket for READ
        nsc.register(sel, SelectionKey.OP_READ);
    } 
}


while (count < COUNT_MAX + NUM_CHILD - 1) {
    sel.select();

    // Get all pending events and iterate
    Iterator keys = sel.selectedKeys().iterator();
    while ( keys.hasNext() ) {
        SelectionKey key = (SelectionKey)keys.next();
        keys.remove();

        if (!key.isValid()) 
            continue;

        if (key.isReadable()) {
            // READ: get the channel
            SocketChannel nsc = (SocketChannel) key.channel();

            // clear buffer for reading
            readBuffer.clear();
            int nBytes = nsc.read(readBuffer);
            if (nBytes == -1) {// Check if the client closed the socket
                key.channel().close();
                key.cancel();
                continue;
            }

            // Read a message 
            DataInputStream ist = new DataInputStream (
                    new ByteArrayInputStream(readBuffer.array()));
            String msg = ist.readUTF();
            System.out.print(msg + "\n");

            // Clear the write buffer 
            writeBuffer.clear();

            // Write the counter value on the buffer
            count++;
            if (count < COUNT_MAX)
                writeBuffer.putInt(count);
            else
                writeBuffer.putInt(-1);
            // flip the buffer and write on the channel
            writeBuffer.flip();
            // Reply to a client
            nsc.write(writeBuffer);
        } 
    } // while (key)

You don't need to register interest in OP_WRITE because usually the channel is ready for writing. However a WritableChannel , if in non blocking mode, might not succeed in writing all content of the given ByteBuffer . See here in its java docs:

Some types of channels, depending upon their state, may write only some of the bytes or possibly none at all. A socket channel in non-blocking mode, for example, cannot write any more bytes than are free in the socket's output buffer.

In this case you need to register the interest for OP_WRITE on the selector to be notified when the channel is once again ready for writing, so you can finish writing your ByteBuffer .

See here a related SO question .

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