【Netty源码学习】ChannelPipeline(一)
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(一)的更多相关文章
- 【Netty源码学习】DefaultChannelPipeline(三)
上一篇博客中[Netty源码学习]ChannelPipeline(二)我们介绍了接口ChannelPipeline的提供的方法,接下来我们分析一下其实现类DefaultChannelPipeline具 ...
- Netty 源码学习——EventLoop
Netty 源码学习--EventLoop 在前面 Netty 源码学习--客户端流程分析中我们已经知道了一个 EventLoop 大概的流程,这一章我们来详细的看一看. NioEventLoopGr ...
- Netty 源码学习——客户端流程分析
Netty 源码学习--客户端流程分析 友情提醒: 需要观看者具备一些 NIO 的知识,否则看起来有的地方可能会不明白. 使用版本依赖 <dependency> <groupId&g ...
- Netty源码学习系列之4-ServerBootstrap的bind方法
前言 今天研究ServerBootstrap的bind方法,该方法可以说是netty的重中之重.核心中的核心.前两节的NioEventLoopGroup和ServerBootstrap的初始化就是为b ...
- 【Netty源码学习】ServerBootStrap
上一篇博客[Netty源码学习]BootStrap中我们介绍了客户端使用的启动服务,接下来我们介绍一下服务端使用的启动服务. 总体来说ServerBootStrap有两个主要功能: (1)调用父类Ab ...
- Netty 源码分析——ChannelPipeline
Netty 源码分析--ChannelPipeline 通过前面的两章我们分析了客户端和服务端的流程代码,其中在初始化 Channel 的时候一定会看到一个 ChannelPipeline.所以在 N ...
- Netty源码解析 -- ChannelPipeline机制与读写过程
本文继续阅读Netty源码,解析ChannelPipeline事件传播原理,以及Netty读写过程. 源码分析基于Netty 4.1 ChannelPipeline Netty中的ChannelPip ...
- 【Netty源码学习】EventLoopGroup
在上一篇博客[Netty源码解析]入门示例中我们介绍了一个Netty入门的示例代码,接下来的博客我们会分析一下整个demo工程运行过程的运行机制. 无论在Netty应用的客户端还是服务端都首先会初始化 ...
- Netty源码学习(六)ChannelPipeline
0. ChannelPipeline简介 ChannelPipeline = Channel + Pipeline,也就是说首先它与Channel绑定,然后它是起到类似于管道的作用:字节流在Chann ...
随机推荐
- Codeforces Round #460 D. Karen and Cards
Description Karen just got home from the supermarket, and is getting ready to go to sleep. After tak ...
- ●POJ 1195 Mobile phones
题链: http://poj.org/problem?id=1195 题解: 二维树状数组 #include<cstdio> #include<cstring> #includ ...
- codeforces round #419 C. Karen and Game
C. Karen and Game time limit per test 2 seconds memory limit per test 512 megabytes input standard i ...
- bzoj 1835: [ZJOI2010]基站选址
Description 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci.如果在距离第i个村庄 ...
- hdu 5600 BestCoder Round #67 (div.2)
N bulbs Accepts: 275 Submissions: 1237 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 655 ...
- bzoj2339[HNOI2011]卡农 dp+容斥
2339: [HNOI2011]卡农 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 842 Solved: 510[Submit][Status][ ...
- python安装pip以及导入第三方包
python有着强大的第三方库,数量很多且功能强大. 最原始的办法是在官网上下载压缩包,解压,然后运行setup.py来进行安装. 显然这种方法很繁琐,不方便.因此有了包管理工具. pip是一个包管理 ...
- RabbitMQ日志无法禁用问题
最近使用spring+rabbitmq发现其Debug日志非常多,几天就把服务器磁盘弄爆了. 原来rabbitmq依赖logback.xml输出日志. 在和log4j.properties同目录下加一 ...
- 561. Array Partition I
Given an array of 2n integers, your task is to group these integers into n pairs of integer, say \(( ...
- 2-学习GPRS_Air202(Air202开发板介绍和下载第一个程序)
http://www.cnblogs.com/yangfengwu/p/8887933.html 资料链接 链接:https://pan.baidu.com/s/1968t2QITuxoyXlE_Nz ...