netty中 Channel, ChannelPipeline, ChannelHandler, ChannelHandlerContext 的关系

netty中Channel, ChannelPipeline, ChannelHandler, ChannelHandlerContext 的关系

一:channel 和 pipeline 一一对应的

channel 和 pipeline 一一对应的。创建channel时,同时创建pipeline。共生攻灭
pipeline是channel的属性

    // pipeline是channel的属性
    private final DefaultChannelPipeline pipeline;
    protected AbstractChannel(Channel parent) {
        this.parent = parent;
        id = newId();
        unsafe = newUnsafe();
        // 创建channel时,同时创建pipeline
        pipeline = newChannelPipeline();
    }


二:pipeline 串起的其实是ctx

所有文档都说pipeline串起多个handler。pipeline确实是串起多个handler,但,具体到实际代码,pipeline 串起的其实是ctx。

ctx是pipeline的属性(pipeline中双向链表的头元素、中间元素、尾元素);

即:pipeline中有两个属性head和tail,都是ctx,所以pipeline存储了一个双向链表,链表的head, tail都是ctx,链表中的元素当然也是ctx。所以说pipeline串起的是ctx(而不是handler哦。)

不过呢,被串起的ctx中有个属性是handler。所以说:pipeline串起ctx,其实也就是 pipeline串起了handler。

    // ctx是pipeline 的属性(head, tail都是ctx)
    final AbstractChannelHandlerContext head;
    final AbstractChannelHandlerContext tail;
    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;
    }

    // ctx中有个属性是handler。所以
    // pipeline串起ctx,其实也就是串起了handler
    DefaultChannelHandlerContext(
            DefaultChannelPipeline pipeline, EventExecutor executor, String name, ChannelHandler handler) {
        super(pipeline, executor, name, handler.getClass());
        this.handler = handler;
    }

三:同一个handler实例 可以被加进多个pipeline(每次加入得到一个新的ctx实例)

每当将handler实例加进pipeline,就创建了ctx,并且将该ctx加入了pipeline。

这太容易理解了,新创建网络连接即channel(也就创建了pipeline)时,我们总是要给每一个channel(的pipeline)添加handler的,handler是用来处理该网络连接上的数据的。

同一个handler实例可以被加进多个pipeline(so创建了多个ctx),channel毁灭(pipeline也同时毁灭),但handler实例可以继续存在,因为handler实例 还位于别的 pipeline中啊。

    // handler被加入了pipeline
    // 此时,生成了新的ctx,即下面的newCtx
    public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
        final AbstractChannelHandlerContext newCtx;
        synchronized (this) {
            checkMultiplicity(handler);
            // 加handler进入pipeline时,就返回了ctx
            newCtx = newContext(group, filterName(name, handler), handler);

            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.
            if (!registered) {
                newCtx.setAddPending();
                callHandlerCallbackLater(newCtx, true);
                return this;
            }

            EventExecutor executor = newCtx.executor();
            if (!executor.inEventLoop()) {
                callHandlerAddedInEventLoop(newCtx, executor);
                return this;
            }
        }
        callHandlerAdded0(newCtx);
        return this;
    }

四:举个例子

假设

有两个@ChannelHandler.Sharable的 ChannelHandler类,AuthHandler, RemoveSensitiveWordHandler;

要创建两个网络连接即两个channel

public class XXXSocketServerInitializer extends ChannelInitializer<SocketChannel> {

    @Override
    public void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast(new AuthHandler(false));
        pipeline.addLast(new RemoveSensitiveWordHandler());
    }
}

创建完成2个网络连接即两个channel假设channel1, channel2之后,我们得到的实例是这样的:

1. 两个 Channel 的实例,即:channel1, channel2
2. 两个 ChannelPipeline 的实例,即:pipeline1, pipeline2。它们和各自的channel共生攻灭

3. 两个ChannelHandler都是@ChannelHandler.Sharable,它们都永远各自只有一个实例,假设它们是:authHandler1, rmvWordHandler1

4. 几个ctx呢?每次加入pipeline都会新建ctx,因此,4个ctx。具体即:

对于pipeline1

pipeline1.addLast(authHandler1)时,得到了 ctx1_1

pipeline1.addLast(rmvWordHandler1)时,得到了 ctx1_2

于是,pipeline1存储的是:new DefaultChannelPipeline.HeadContext()--> ctx1_1--> ctx1_2--> new DefaultChannelPipeline.TailContext() 

 

对于pipeline2

pipeline2.addLast(authHandler1)时,得到了 ctx2_1

pipeline2.addLast(rmvWordHandler1)时,得到了 ctx2_2

于是,pipeline2存储的是:new DefaultChannelPipeline.HeadContext()--> ctx2_1--> ctx2_2--> new DefaultChannelPipeline.TailContext()

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值