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

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

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

public void bind(ChannelHandlerContext ctx, SocketAddress localAddress,
                ChannelPromise promise) throws Exception {
            ctx.bind(localAddress, promise);
        }

走到这里其实我们发现了其实,还是回到了AbstractChannelHandlerContext#bind(),仍然是先调用了findContextOutbound(),那么其实,整个调用链会一直从pipeline.tail一直往上找到pipeline.head,查看前面章节初始化channel的过程,在实例化NioServerSocketChannel的时候,调用了父类的构造方法,其中AbstractChannel的构造方法实例化了pipeline

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

发现,其实是使用了DefaultChannelPipeline。进入该类构造方法,返现实例化的时候创建了,HeadContext 和 TailContext来作为pipeline的头和尾

    protected DefaultChannelPipeline(Channel channel) {
            this.channel = ObjectUtil.checkNotNull(channel, "channel");
            succeededFuture = new SucceededChannelFuture(channel, null);
            voidPromise =  new VoidChannelPromise(channel, true);
     
            tail = new TailContext(this);
            head = new HeadContext(this);
     
            head.next = tail;
            tail.prev = head;
        }

进入HeadContext#bind()方法,发现其实是调用了unsafe的方法

    @Override
            public void bind(
                    ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise)
                    throws Exception {
                unsafe.bind(localAddress, promise);
            }

经过分析该成员变量是与pipeline一样在AbstractChannel的构造方法中被实例化。其实就是NioServerSocketChannel的实例化过程。其中就进行了成员变量AbstractNioChannel.readInterestOp初始化的,其值就是SelectionKey.OP_ACCEPT事件

    public NioServerSocketChannel(ServerSocketChannel channel) {
            //初始化过程传入了Selecor事件:accept
            super(null, channel, SelectionKey.OP_ACCEPT);
            config = new NioServerSocketChannelConfig(this, javaChannel().socket());
        }
     
    protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
            super(parent);
            this.ch = ch;
            //初始化事件成员变量
            this.readInterestOp = readInterestOp;
            try {
                ch.configureBlocking(false);
            } catch (IOException e) {
                try {
                    ch.close();
                } catch (IOException e2) {
                    if (logger.isWarnEnabled()) {
                        logger.warn(
                                "Failed to close a partially initialized socket.", e2);
                    }
                }
     
                throw new ChannelException("Failed to enter non-blocking mode.", e);
            }
}
返回列表