ChannelPipeline类似于一个管道,管道中存放的是一系列对读取数据进行业务操作的ChannelHandler。

1、ChannelPipeline的结构图:

在之前的博客【Netty源码学习】入门示例我们看到了如下的代码:

future.channel().writeAndFlush("Hello Netty Server ,I am a common client");  

其实就是Client向Server发送数据,其具体实现是在AbstractChannel类中

@Override
    public ChannelFuture writeAndFlush(Object msg) {
        return pipeline.writeAndFlush(msg);
    }

上面这段代码出现了我们这篇博客要分析的类DefaultChannelPipeline,其是ChannelPipeline的实现类。DefaultChannelPipeline中writeAndFlush(msg)的实现如下:

@Override
    public final ChannelFuture writeAndFlush(Object msg) {
        return tail.writeAndFlush(msg);
    }

tail对象的定义如下final AbstractChannelHandlerContext tail,接口为ChannelHandlerContext我们会接下来进行分析,其进一步封装了数据读写操作。现在看好像DefaultChannelPipeline的使命已经结束了,发送数据的操作在AbstractChannelHandlerContext中实现。

接下来我们详细介绍一下DefaultChannelPipeline,一开始我们说它是一个管道,是因为他的名称是pipe,其实现在看来他更像一个链表(其实是一个双向循环链表),队列的单位是AbstractChannelHandlerContext,因为其定义了两个变量。

final AbstractChannelHandlerContext head;
    final AbstractChannelHandlerContext tail;

head为链表的头,tail为链表的尾,接下来的很多操作都与head和tail相关的。添加ChannelHandler操作。

@Override
    public final ChannelPipeline addFirst(String name, ChannelHandler handler) {
        return addFirst(null, name, handler);
    }

    @Override
    public final ChannelPipeline addFirst(EventExecutorGroup group, String name, ChannelHandler handler) {
        final AbstractChannelHandlerContext newCtx;
        synchronized (this) {
            checkMultiplicity(handler);
            name = filterName(name, handler);

            newCtx = newContext(group, name, handler);

            addFirst0(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()) {
                newCtx.setAddPending();
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        callHandlerAdded0(newCtx);
                    }
                });
                return this;
            }
        }
        callHandlerAdded0(newCtx);
        return this;
    }

    private void addFirst0(AbstractChannelHandlerContext newCtx) {
        AbstractChannelHandlerContext nextCtx = head.next;
        newCtx.prev = head;
        newCtx.next = nextCtx;
        head.next = newCtx;
        nextCtx.prev = newCtx;
    }

在addFirst0中我们可以清晰的看到,创建双向循环对列,对列的基本单位是AbstractChannelHanndlerContext。ChannelPipeline继承ChannelInboundInvoker和ChannelOutboundInvoker,它既是一个inboundinvoke,又是一个outboundinvoke,同时也是ChannelChandler的管理者,提供了很多对handler进行的操作。

我们介绍一下channelActive操作channelActive函数

@Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            ctx.fireChannelActive();

            readIfIsAutoRead();
        }

其具体实现在我们继承的ChannelHandlerContext类中,比如我们入门教程中的ClientHandler中

@Override
    public void channelActive(ChannelHandlerContext ctx) {
        System.out.println("HelloWorldClientHandler Active");
    }  

由于ChannelHandlerContext是实现数据读写的具体操作类,DefaultChannelPipeline实现了一个ChannelHandlerContext的双向链表,ChannelHandlerContext中封装了我们对消息数据的具体操作比如ClientHandler打印数据,因此DefaultChannelPipeplie的双向链表就是对数据的各种操作,所以在很多地方都会看到pipeline的身影。

【Netty源码学习】ChannelPipeline(一)的更多相关文章

  1. 【Netty源码学习】DefaultChannelPipeline(三)

    上一篇博客中[Netty源码学习]ChannelPipeline(二)我们介绍了接口ChannelPipeline的提供的方法,接下来我们分析一下其实现类DefaultChannelPipeline具 ...

  2. Netty 源码学习——EventLoop

    Netty 源码学习--EventLoop 在前面 Netty 源码学习--客户端流程分析中我们已经知道了一个 EventLoop 大概的流程,这一章我们来详细的看一看. NioEventLoopGr ...

  3. Netty 源码学习——客户端流程分析

    Netty 源码学习--客户端流程分析 友情提醒: 需要观看者具备一些 NIO 的知识,否则看起来有的地方可能会不明白. 使用版本依赖 <dependency> <groupId&g ...

  4. Netty源码学习系列之4-ServerBootstrap的bind方法

    前言 今天研究ServerBootstrap的bind方法,该方法可以说是netty的重中之重.核心中的核心.前两节的NioEventLoopGroup和ServerBootstrap的初始化就是为b ...

  5. 【Netty源码学习】ServerBootStrap

    上一篇博客[Netty源码学习]BootStrap中我们介绍了客户端使用的启动服务,接下来我们介绍一下服务端使用的启动服务. 总体来说ServerBootStrap有两个主要功能: (1)调用父类Ab ...

  6. Netty 源码分析——ChannelPipeline

    Netty 源码分析--ChannelPipeline 通过前面的两章我们分析了客户端和服务端的流程代码,其中在初始化 Channel 的时候一定会看到一个 ChannelPipeline.所以在 N ...

  7. Netty源码解析 -- ChannelPipeline机制与读写过程

    本文继续阅读Netty源码,解析ChannelPipeline事件传播原理,以及Netty读写过程. 源码分析基于Netty 4.1 ChannelPipeline Netty中的ChannelPip ...

  8. 【Netty源码学习】EventLoopGroup

    在上一篇博客[Netty源码解析]入门示例中我们介绍了一个Netty入门的示例代码,接下来的博客我们会分析一下整个demo工程运行过程的运行机制. 无论在Netty应用的客户端还是服务端都首先会初始化 ...

  9. Netty源码学习(六)ChannelPipeline

    0. ChannelPipeline简介 ChannelPipeline = Channel + Pipeline,也就是说首先它与Channel绑定,然后它是起到类似于管道的作用:字节流在Chann ...

随机推荐

  1. 51 nod 1766 树上的最远点对(线段树+lca)

    1766 树上的最远点对 基准时间限制:3 秒 空间限制:524288 KB 分值: 80 难度:5级算法题   n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个 ...

  2. 51 nod 1405 树的距离之和

    1405 树的距离之和 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题   给定一棵无根树,假设它有n个节点,节点编号从1到n, 求任意两点之间的距离(最短路径)之 ...

  3. 【USACO12JAN】视频游戏的连击Video Game Combos

    题目描述 Bessie is playing a video game! In the game, the three letters 'A', 'B', and 'C' are the only v ...

  4. 【Codeforces Round #431 (Div. 1) D.Shake It!】

    ·最小割和组合数放在了一起,产生了这道题目. 英文题,述大意:     一张初始化为仅有一个起点0,一个终点1和一条边的图.输入n,m表示n次操作(1<=n,m<=50),每次操作是任选一 ...

  5. poj1741Tree 点分治

    上午学习了点分治,写了1个半小时终于写出一个代码--poj1741,可以说是个模板题. 分治:对于每个儿子找出重心,分别处理 注意:1.每次处理一个重心后,ans减去对它儿子的处理 原因:因为统计方法 ...

  6. IDEA 整合 SSM 框架学习

    认识 Spring 框架 更多详情请点击这里:这里 Spring 框架是 Java 应用最广的框架,它的成功来源于理念,而不是技术本身,它的理念包括 IoC (Inversion of Control ...

  7. Windows2003无法连接远程桌面问题 解决方法!

    按照以下步骤来一一排除问题吧!  步骤1.遇到这样的情况,通常情况下我们都是先检查远程有没有开启,就是右击我的电脑查看属性里的远程前面的框框有没有勾上,勾上后即可远程,metsc 127.0.0.1 ...

  8. Linux学习之CentOS(五)--CentOS下VMware-Tools安装

    已经进入到了Linux学习之CentOS的第六篇随笔了,所以这里就介绍一下VMware-Tools的安装. VMware-Tools的安装 VMware-Tools 主要的功能就是让用户在虚拟机和真实 ...

  9. css文本强制一行 字间距

    white-space:nowrap 在一行 .slideLastlyNews img{margin-left:9px;margin-right:5px;margin-top:6px;width:5p ...

  10. MySQL使用判断

    1.case语法 在第一个方案的返回结果中, value=compare-value.而第二个方案的返回结果是第一种情况的真实结果.如果没有匹配的结果值,则返回结果为ELSE后的结果,如果没有ELSE ...