首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

绑定端口并向Selector注册accept事件 5

绑定端口并向Selector注册accept事件 5

通过分析readIfIsAutoRead()我们发现,调用了通道的read方法,一样的操作,最终回到了头部HeadContext#read()

    private void readIfIsAutoRead() {
                //该配置项默认值是1,默认条件成立
                if (channel.config().isAutoRead()) {
                    channel.read();
                }
            }
     
    @Override
        public Channel read() {
            //调用pipeline的read()
            pipeline.read();
            return this;
       }
     
    @Override
        public final ChannelPipeline read() {
            //从尾部开始
            tail.read();
            return this;
        }
     
    @Override
        public ChannelHandlerContext read() {
            //查找最近的一个ContextOutbound
            final AbstractChannelHandlerContext next = findContextOutbound();
            EventExecutor executor = next.executor();
            if (executor.inEventLoop()) {
                next.invokeRead();
            } else {
                Runnable task = next.invokeReadTask;
                if (task == null) {
                    next.invokeReadTask = task = new Runnable() {
                        @Override
                        public void run() {
                            next.invokeRead();
                        }
                    };
                }
                executor.execute(task);
            }
     
            return this;
        }
     
    private void invokeRead() {
            if (invokeHandler()) {
                try {
                    //调用实际上是调用 ChannelHandlerContext.read方法,回到上一个方法,知道找到头部HeadContext
                    ((ChannelOutboundHandler) handler()).read(this);
                } catch (Throwable t) {
                    notifyHandlerException(t);
                }
            } else {
                read();
            }
        }
     

    @Override
            public void read(ChannelHandlerContext ctx) {
                unsafe.beginRead();
            }

结合之前对unsafe实例的分析,最终进入AbstractNioChannel#doBeginRead()方法,

        @Override
        protected void doBeginRead() throws Exception {
            //获取selectionKey
            final SelectionKey selectionKey = this.selectionKey;
            if (!selectionKey.isValid()) {
                return;
            }
     
            readPending = true;
            //改变Selector事件为OP_ACCEPT
            final int interestOps = selectionKey.interestOps();
            if ((interestOps & readInterestOp) == 0) {
                selectionKey.interestOps(interestOps | readInterestOp);
            }
        }

分析一下,还记得selectionKey是什么时候初始化的吗,是在Selector注册的时候,可以翻看之前的文章。AbstractNioChannel#doRegister()中有以下代码,这个0则是SelectionKeyImpl的成员变量interestOps

selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);

而成员变量readInterestOp前面已经分析过了,构造方法初始化通道的时候,给入了OP_ACCEPT值。也就是accept事件。
返回列表