OP_ACCEP、OP_READ和OP_WRITE的注册

OP_ACCEP注册

  首先,ServerSocketChannel创建时就指定感兴趣事件OP_ACCEPT;然后,在注册阶段,直接向Selector注册OP_ACCEPT;

    public NioServerSocketChannel(ServerSocketChannel channel) {
        super(null, channel, SelectionKey.OP_ACCEPT);
        config = new NioServerSocketChannelConfig(this, javaChannel().socket());
    }

OP_READ注册

 首先,SocketChannel创建时就指定感兴趣事件OP_READ;然后,在注册阶段,直接向Selector注册OP_READ;

    protected AbstractNioByteChannel(Channel parent, SelectableChannel ch) {
        super(parent, ch, SelectionKey.OP_READ);
    }

OP_WRITE注册

  Flush时,如果ChannelOutboundBuffer的数据没有全部写入Channel的发送缓冲区,则注册OP_WRITE,如NioSocketChannel的doWrite()方法所示。当Channel的发送缓冲区可写之后,产生OP_WRITE事件,处理逻辑是:再次调用flush方法,继续将ChannelOutboundBuffer的数据写入Channel。

 for (int i = writeSpinCount - 1; i >= 0; i --) {
                    int localFlushedAmount = doWriteBytes(buf);
                    if (localFlushedAmount == 0) {
                        setOpWrite = true;
                        break;
                    }

                    flushedAmount += localFlushedAmount;
                    if (!buf.isReadable()) {
                        done = true;
                        break;
                    }
                }
 protected final void incompleteWrite(boolean setOpWrite) {
        // Did not write completely.
        if (setOpWrite) {
            setOpWrite();
        } else {
            // Schedule flush again later so other tasks can be picked up in the meantime
            Runnable flushTask = this.flushTask;
            if (flushTask == null) {
                flushTask = this.flushTask = new Runnable() {
                    @Override
                    public void run() {
                        flush();
                    }
                };
            }
            eventLoop().execute(flushTask);
        }
    }
// Process OP_WRITE first as we may be able to write some queued buffers and so free memory.
            if ((readyOps & SelectionKey.OP_WRITE) != 0) {
                // Call forceFlush which will also take care of clear the OP_WRITE once there is nothing left to write
                ch.unsafe().forceFlush();
            }

OP_WRITE注销

  Flush时,如果ChannelOutboundBuffer的数据全部写入Channel的发送缓冲区,则取消OP_WRITE的注册,如NioSocketChannel的doWrite()方法所示:
这里写图片描述

OP_WRITE特殊性说明

  OP_WRITE表示Channel的发送缓冲区可写,如果OP_WRITE一直被注册,大部分情况下Channel是空闲的,产生大量的OP_WRITE事件;只有在Flush时,ChannelOutboundBuffer中的数据没有全部写入Channel的发送缓冲区,才会关心Channel的发送缓冲区何时变为可写。

参考:

  1. https://blog.csdn.net/fjslovejhl/article/details/9246225
  2. https://blog.csdn.net/iter_zc/article/details/39396169

猜你喜欢

转载自blog.csdn.net/yangguosb/article/details/80180786
OP