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

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

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

回过神来我们接着找unsalf的初始化实例。继续往上查看的构造方法,调用了抽象方法newUnsafe,NioServerSocketChannel继承了NioSocketChannle,最终发现unsafe其实是NioSocketChannelUnsafe

    protected AbstractChannel(Channel parent) {
            this.parent = parent;
            id = newId();
            unsafe = newUnsafe();
            pipeline = newChannelPipeline();
        }

11623065-b89e6b0fd4b76053.png

    @Override
        protected AbstractNioUnsafe newUnsafe() {
            return new NioSocketChannelUnsafe();
        }

进入查看其bind(),该方法在其父类AbstractChannel.AbstractUnsafe#bind()中

            @Override
            public final void bind(final SocketAddress localAddress, final ChannelPromise promise) {
               
                //省略代码
               
                //未绑定之前:未激活状态
                boolean wasActive = isActive();
                try {
                    //进行绑定,成功后激活状态
                    doBind(localAddress);
                } catch (Throwable t) {
                    safeSetFailure(promise, t);
                    closeIfClosed();
                    return;
                }
               
                //判断是哦付激活来进行 Event传播:ChannelActive
                if (!wasActive && isActive()) {
                    invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            pipeline.fireChannelActive();
                        }
                    });
                }
     
                safeSetSuccess(promise);
            }

这里有两个地方指的继续深入查看其源码,一个是doBind()绑定端口,另一个是fireChannelActive()传播事件,我们当前的节点是在pipleline头部 HeadContext里面。

    doBind()最终进入NioServerSocketChannel#doBind()调用了jdk底层的端口绑定方法。完成了绑定。

    @Override
        protected void doBind(SocketAddress localAddress) throws Exception {
            if (PlatformDependent.javaVersion() >= 7) {
                javaChannel().bind(localAddress, config.getBacklog());
            } else {
                javaChannel().socket().bind(localAddress, config.getBacklog());
            }
        }

    进入DefaultChannelPipeline.HeadContext#channelActive()发现调用了readIfIsAutoRead()

    @Override
            public void channelActive(ChannelHandlerContext ctx) throws Exception {
                ctx.fireChannelActive();
     
                readIfIsAutoRead();
            }
返回列表