【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 842D Vitya and Strange Lesson
题目大意: 定义mex数为数组中第一个没有出现的非负整数.有m个操作,每个操作有一个x,将数组中所有的元素都异或x,然后询问当前的mex Input First line contains two i ...
- Python【第四课】 模块 and 包
本篇内容 模块基础和导入(import,from...import...) 包常识和导入(import,from...import...) 函数式第一类对象 1.模块基础和导入 1.1 模块认识 什么 ...
- day5 liaoxuefeng---实战篇
- 关于 printf scanf getchar
float默认小数6位 右对齐.-m 左对齐 在调用printf函数输出数据时,当数据的实际位宽大于printf函数中的指定位宽时,将按照数据的实际位宽输出数据. .n表精度 输出%符号 注意点 #i ...
- 跨域资源共享CORS与JSONP
同源策略限制: 同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果没有同源策略,攻击者可以通过JavaScript获取你的邮件以及其他敏感信息,比如说 ...
- 原生JS实现圆周运动
<body> <div id="ball" style="width:20px; height:20px; background:red; border ...
- 关于spring定时任务被多次调用的问题
在项目开发中,难免会用到定时任务,如果你的项目中用了spring这个框架,那么恭喜你,你的定时任务的创建将变得无比简单. 代码中只需要一个 @Scheduled标签,然后配置对应的执行频率即可 pas ...
- python学习之路基础篇(第六篇)
一.算法 冒泡排序 两两比较 打的沉下去,小的浮上来 从而把数字从小到大排列出来 选择排序 随机取一个索引作为最大值,然后和列表中的其他索引进行比较,如果l[0]<l[1],则将l[1]修改为 ...
- Dynamics 365 Online 试用账号申请方式
专人整理的申请方式PPT,这里转载给大家,下载地址
- 操作系统内核Hack:(三)引导程序制作
操作系统内核Hack:(三)引导程序制作 关于本文涉及到的完整源码请参考MiniOS的v1_bootloader分支. 1.制作方法 现在我们已经了解了关于BootLoader的一切知识,让我们开始动 ...