【转】http://blog.csdn.net/zxhoo/article/details/17264263
Netty4
Netty是一个和MINA类似的Java NIO框架,目前的最新版本是4.0.13,这两个框架的主要作者好像都是同一个韩国人。
Channel
Channel是Netty最核心的接口,一个Channel就是一个联络Socket的通道,通过Channel,你可以对Socket进行各种操作。
ChannelHandler
用Netty编写网络程序的时候,你很少直接操纵Channel,而是通过ChannelHandler来间接操纵Channel。
ChannelPipeline
ChannelPipeline实际上应该叫做ChannelHandlerPipeline,可以把ChannelPipeline看成是一个ChandlerHandler的链表,当需要对Channel进行某种处理的时候,Pipeline负责依次调用每一个Handler进行处理。每个Channel都有一个属于自己的Pipeline,调用Channel#pipeline()方法可以获得Channel的Pipeline,调用Pipeline#channel()方法可以获得Pipeline的Channel。
ChannelPipeline的方法有很多,其中一部分是用来管理ChannelHandler的,如下面这些:
- ChannelPipeline addFirst(String name, ChannelHandler handler);
- ChannelPipeline addLast(String name, ChannelHandler handler);
- ChannelPipeline addBefore(String baseName, String name, ChannelHandler handler);
- ChannelPipeline addAfter(String baseName, String name, ChannelHandler handler);
- ChannelPipeline remove(ChannelHandler handler);
- ChannelHandler remove(String name);
- ChannelHandler removeFirst();
- ChannelHandler removeLast();
- ChannelPipeline replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler);
- ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler);
- ChannelHandler first();
- ChannelHandler last();
- ChannelHandler get(String name);
根据上面的方法,能够大概想象的到Pipeline按照什么样的方式组织Handler。
ChannelHandlerContext
ChannelPipeline并不是直接管理ChannelHandler,而是通过ChannelHandlerContext来间接管理,这一点通过ChannelPipeline的默认实现DefaultChannelPipeline可以看出来。
调用ChannelHandlerContext#channel()方法可以得到和Context绑定的Channel,调用ChannelHandlerContext#handler()方法可以得到和Context绑定的Handler。
ChannelPipeline和ChannelHandlerContext默认实现
DefaultChannelHandlerContext和DefaultChannelPipeline是ChannelHandlerContext和ChannelPipeline的默认实现,下面是它们的部分代码:
- final class DefaultChannelHandlerContext extends DefaultAttributeMap implements ChannelHandlerContext {
- volatile DefaultChannelHandlerContext next;
- volatile DefaultChannelHandlerContext prev;
- private final boolean inbound;
- private final boolean outbound;
- private final AbstractChannel channel;
- private final DefaultChannelPipeline pipeline;
- private final String name;
- private final ChannelHandler handler;
- private boolean removed;
- // ...
- }
- final class DefaultChannelPipeline implements ChannelPipeline {
- // ...
- final DefaultChannelHandlerContext head;
- final DefaultChannelHandlerContext tail;
- // ...
- }
从上面的代码可以看出,在DefaultPipeline内部,DefaultChannelHandlerContext组成了一个双向链表:
再来看看DefaultChannelPipeline的构造函数:
- public DefaultChannelPipeline(AbstractChannel channel) {
- if (channel == null) {
- throw new NullPointerException("channel");
- }
- this.channel = channel;
- TailHandler tailHandler = new TailHandler();
- tail = new DefaultChannelHandlerContext(this, null, generateName(tailHandler), tailHandler);
- HeadHandler headHandler = new HeadHandler(channel.unsafe());
- head = new DefaultChannelHandlerContext(this, null, generateName(headHandler), headHandler);
- head.next = tail;
- tail.prev = head;
- }
可以看到,DefaultChinnelPipeline内部使用了两个特殊的Handler来表示Handler链的头和尾:
ChannelHandler的种类
从上面DefaultChannelHandlerContext代码可以知道,Handler实际上分为两种,Inbound和Outbound,这一点也可以从ChannelHandler接口的子接口得到证明:
- public interface ChannelInboundHandler extends ChannelHandler {
- // ...
- }
- public interface ChannelOutboundHandler extends ChannelHandler {
- // ...
- }
事件的传播
为了搞清楚事件如何在Pipeline里传播,让我们从Channel的抽象子类AbstractChannel开始,下面是AbstractChannel#write()方法的实现:
- public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
- // ...
- @Override
- public Channel write(Object msg) {
- return pipeline.write(msg);
- }
- // ...
- }
AbstractChannel直接调用了Pipeline的write()方法:
再看DefaultChannelPipeline的write()方法实现:
- final class DefaultChannelPipeline implements ChannelPipeline {
- // ...
- @Override
- public ChannelFuture write(Object msg) {
- return tail.write(msg);
- }
- // ...
- }
因为write是个outbound事件,所以DefaultChannelPipeline直接找到tail部分的context,调用其write()方法:
接着看DefaultChannelHandlerContext的write()方法:
- final class DefaultChannelHandlerContext extends DefaultAttributeMap implements ChannelHandlerContext {
- // ...
- @Override
- public ChannelFuture write(Object msg) {
- return write(msg, newPromise());
- }
- @Override
- public ChannelFuture write(final Object msg, final ChannelPromise promise) {
- if (msg == null) {
- throw new NullPointerException("msg");
- }
- validatePromise(promise, true);
- write(msg, false, promise);
- return promise;
- }
- private void write(Object msg, boolean flush, ChannelPromise promise) {
- DefaultChannelHandlerContext next = findContextOutbound();
- next.invokeWrite(msg, promise);
- if (flush) {
- next.invokeFlush();
- }
- }
- private DefaultChannelHandlerContext findContextOutbound() {
- DefaultChannelHandlerContext ctx = this;
- do {
- ctx = ctx.prev;
- } while (!ctx.outbound);
- return ctx;
- }
- private void invokeWrite(Object msg, ChannelPromise promise) {
- try {
- ((ChannelOutboundHandler) handler).write(this, msg, promise);
- } catch (Throwable t) {
- notifyOutboundHandlerException(t, promise);
- }
- }
- // ...
- }
context的write()方法沿着context链往前找,直至找到一个outbound类型的context为止,然后调用其invokeWrite()方法:
invokeWrite()接着调用handler的write()方法:
最后看看ChannelOutboundHandlerAdapter的write()方法实现:
- public class ChannelOutboundHandlerAdapter extends ChannelHandlerAdapter implements ChannelOutboundHandler {
- // ...
- @Override
- public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
- ctx.write(msg, promise);
- }
- // ...
- }
默认的实现调用了context的write()方法而不做任何处理,这样write事件就沿着outbound链继续传播:
可见,Pipeline的事件传播,是靠Pipeline,Context和Handler共同协作完成的。
相关推荐
public final ChannelPipeline remove(ChannelHandler handler) { remove(getContextOrDie(handler)); return this; } getContextOrDie(ChannelHandler handler)方法获得相应AbstractChannelHandlerContext节点:...
Netty的心跳检测和Keepalive机制都是为了确保客户端和服务器之间的连接仍然有效,防止连接断开。但它们在实现方式和原理上...在初始化ChannelPipeline时,我们可以添加IdleStateHandler实例,并设置读、写超时时间。
第6章 ChannelHandler和ChannelPipeline 第7章 EventLoop和线程模型 第8章 引导 第9章 单元测试 第二部分 编解码器 第10章 编解码器框架 第11章 预置的ChannelHandler和编解码器 第三部分 网络协议 第12章 ...
第17章 ChannelPipeline 和ChannelHandler 第18章 EvenLoop 和EventLoopGroup 第19章 Future 和Promise 第20章 Netty 架构解析 第21章j ava多线程编程在netty中的应用 第22章 高性能之道 第23章 可靠性 第24章 安全...
后篇章的技术持续高能,Kafka、Zookeeper、手写Tomcat+心跳机制、手写RPC框架、Dubbo框架、Netty源码解析、Eureka、ChannelPipeline源码解析、ElasticSearch、RocketMQ、K8S全实战、大型互联网高可用设计、ELK日志...
[ChannelPipeline构建逻辑](netty / netty逻辑流程/ 2。ChannelPipeline构造过程.md) ChannelPipeline执行流程 [事件初始/ IO处理流程](/ home / chen / github / _note / netty / netty逻辑流程/ 3。...
净值 jdk bio,nio,aio各种使用案例,深入理解netty,结合源码... ChannelHandlerContext和ChannelPipeLine以及Channel的关系 使用netty自带的编码解码器编写一个聊天室 在9的基础上加入私聊功能 在10的基础上加入pr
第17 章 ChannelPipeline 和ChannelHandler...... 388 第18 章 EventLoop 和EventLoopGroup...... 419 第19 章 Future 和Promise ...... 438 第20 章 Netty 架构剖析...... 452 第21 章...
io.netty.channel.ChannelPipeline; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io....
65_ChannelPipeline创建时机与高级拦截过滤器模式的运用 66_Netty常量池实现及ChannelOption与Attribute作用分析 67_Channel与ChannelHandler及ChannelHandlerContext之间的关系分析 68_Netty核心四大组件关系与构建...
63_Reactor模式与Netty组件对比及Acceptor组件的作用分析 64_Channel与ChannelPipeline关联关系及模式运用 65_ChannelPipeline创建时机与高级拦截过滤器模式的运用 66_Netty常量池实现及ChannelOption与Attribute...
源码篇 :bird: MyBatis :leaf_fluttering_in_wind: 春天 :bullet_train: 达博Dubbo原始解析-服务导出 :hammer_and_wrench: 净额 Netty原始解析正式篇-承诺Netty原始解析正式篇——ChannelPipeline和ChannelHandler ...
第65讲:ChannelPipeline创建时机与高级拦截过滤器模式的运用 第66讲:Netty常量池实现及ChannelOption与Attribute作用分析 第67讲:Channel与ChannelHandler及ChannelHandlerContext之间的关系分析 第68讲:...