简体   繁体   English

在JAVA nio选择器中,何时应该注册'写操作'?

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

I am learning Java nio selector. 我正在学习Java nio选择器。 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? 我不知道为什么在这段代码中写入过程可能发生在if (key.isReadable()){...}的块中但不是if (key.isWritable){...}以及为什么写入操作不是注册?

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. 您不需要注册对OP_WRITE兴趣,因为通常该通道已准备好进行写入。 However a WritableChannel , if in non blocking mode, might not succeed in writing all content of the given ByteBuffer . 但是,如果处于非阻塞模式,则WritableChannel可能无法成功写入给定ByteBuffer所有内容。 See here in its java docs: 在这里看到它的java文档:

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 . 在这种情况下,您需要在选择器上注册OP_WRITE的兴趣,以便在频道再次准备好写入时收到通知,这样您就可以完成编写ByteBuffer

See here a related SO question . 在这里看到一个相关的SO问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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