Netty笔记-Channel的Register

1.SelectableChannel的register

在nio编程中,通过ServerSocketChannel的register方法,将事件监听注册到Selector当中去,所以理论上在Netty中,肯定也有这么一个环节

    public MultiplexerTimeServer(int port) {
        try {
            selector = Selector.open();
            servChannel = ServerSocketChannel.open();
            servChannel.configureBlocking(false);
            servChannel.socket().bind(new InetSocketAddress(port), 1024);
            servChannel.register(selector, SelectionKey.OP_ACCEPT);
            System.out.println("The time server is start in port : " + port);
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

2.AbstractChannel

我们分析的时候将断点下在SelectableChannel的register方法这里,发现调用方为AbstractNioChannel的doRegister方法

调用堆栈如下

Netty笔记-Channel的Register_第1张图片

doRegister方法

    @Override
    protected void doRegister() throws Exception {
        boolean selected = false;
        for (;;) {
            try {
                selectionKey = javaChannel().register(eventLoop().selector, 0, this);
                return;
            } catch (CancelledKeyException e) {
                if (!selected) {
                    // Force the Selector to select now as the "canceled" SelectionKey may still be
                    // cached and not removed because no Select.select(..) operation was called yet.
                    eventLoop().selectNow();
                    selected = true;
                } else {
                    // We forced a select operation on the selector before but the SelectionKey is still cached
                    // for whatever reason. JDK bug ?
                    throw e;
                }
            }
        }
    }

2. register方法参数

register方法的第2个参数0,表示不接受任何事件,第三个参数表示attach参数
那么总有一个地方需要初始化来接收SelectionKey.OP_ACCEPT事件

3.Channel注册到Selector的两种方式

  • 一种是调用Channel的register方法,
  • 第二种是设置SelectionKey的interestOps的值。Netty是用了第二种方式,通过设置SelectionKey的interestOps来注册Channel关心的事件,把实际的注册延迟了。

在AbstractNioChannel的doBeginRead方法中调用SelectionKey的interestOps方法来注册事件

Netty笔记-Channel的Register_第2张图片
 @Override
    protected void doBeginRead() throws Exception {
        if (inputShutdown) {
            return;
        }

        final SelectionKey selectionKey = this.selectionKey;
        if (!selectionKey.isValid()) {
            return;
        }

        final int interestOps = selectionKey.interestOps();
        if ((interestOps & readInterestOp) == 0) {
            selectionKey.interestOps(interestOps | readInterestOp);
        }
    }

参考:
https://segmentfault.com/a/1190000013015303
https://blog.csdn.net/iter_zc/article/details/39396169

你可能感兴趣的