美文网首页
6_netty_ChannelPipeline

6_netty_ChannelPipeline

作者: loading_17 | 来源:发表于2018-06-21 21:31 被阅读0次

    在上一篇实例化NioServerSocketChannel中,

        protected DefaultChannelPipeline newChannelPipeline() {
            return new DefaultChannelPipeline(this);
        }
    

    看看DefaultChannelPipeline的继续结构,并不复杂。


        protected DefaultChannelPipeline(Channel 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;
        }
    

    TailContext和HeadContext都是DefaultChannelPipline的内部类。



     HeadContext(DefaultChannelPipeline pipeline) {
              //设置属性
                super(pipeline, null, HEAD_NAME, false, true);
                unsafe = pipeline.channel().unsafe();
                setAddComplete();
            }
    

    第四个参数表示inbound,第五个表示outbound,这里的HeadContext是outbound的,那么表示处理出站的handler。相反的TailContext是处理入站的handler。
    示例代码中都是addLast,我们就先看看addLast方法。

        public final ChannelPipeline addLast(ChannelHandler... handlers) {
            return addLast(null, handlers);
        }
        public final ChannelPipeline addLast(EventExecutorGroup executor, ChannelHandler... handlers) {
            if (handlers == null) {
                throw new NullPointerException("handlers");
            }
    
            for (ChannelHandler h: handlers) {
                if (h == null) {
                    break;
                }
                addLast(executor, null, h);
            }
    
            return this;
        }
    
        public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
            final AbstractChannelHandlerContext newCtx;
            synchronized (this) {
                //检查是否添加过这个handler,通过added属性判断
                checkMultiplicity(handler);
              //新建DefaultChannelHandlerContext类
                newCtx = newContext(group, filterName(name, handler), handler);
              //将包装后的DefaultChannelHandlerContext类加入双向链表
              //将会被放在headcontext和tailcontext之间
                addLast0(newCtx);
    
                // If the registered is false it means that the channel was not registered on an eventloop yet.
                // In this case we add the context to the pipeline and add a task that will call
                // ChannelHandler.handlerAdded(...) once the channel is registered.
                //判断channel是否注册过eventloop,如果没有需要添加任务,并在
                //channel注册的时候调用ChannelHnadler.handlerAdded()方法
                if (!registered) {
                    newCtx.setAddPending();
                    callHandlerCallbackLater(newCtx, true);
                    return this;
                }
    
                EventExecutor executor = newCtx.executor();
                if (!executor.inEventLoop()) {
                    newCtx.setAddPending();
                    executor.execute(new Runnable() {
                        @Override
                        public void run() {
                            callHandlerAdded0(newCtx);
                        }
                    });
                    return this;
                }
            }
            callHandlerAdded0(newCtx);
            return this;
        }
    

    上述将添加任务后,会在bind的后续代码中register0方法内执行pipeline.invokeHandlerAddedIfNeeded(),最后一步就会执行对应的ChannelInitializer的initChannel方法。

    总结下:

    1. 在创建channnel的时候,会同时创建pipeline对象进行绑定
    2. pipeline是一个双端队列,初始化的时候头会新建好head和tail,前者是outbound,后者是inbound。

    相关文章

      网友评论

          本文标题:6_netty_ChannelPipeline

          本文链接:https://www.haomeiwen.com/subject/aeaqyftx.html