/** * ChannelHandlerContext 实现了ChannelInboundInvoker和ChannelOutboundInvoker * * ChannelPipeline 也实现了ChannelInboundInvoker和*ChannelOutboundInvoker, * * ChannelPipeline 持有ChannelHandlerContext链表, * 对于ChannelInboundInvoker和ChannelOutboundInvoker事件 * ChannelPipeline 只是委派给ChannelHandlerContext链表中每一个 * ChannelHandlerContext处理,ChannelHandlerContext再调用 * 相应的ChannelInboundHandler 或ChannelOutboundHandler方法 * * ChannelPipeline 实现ChannelInboundInvoker和ChannelOutboundInvoker * 目的:只是平滑地将事件委派出去。 **/
/** * Enables a {@link ChannelHandler} to interact with its {@link ChannelPipeline} * and other handlers. Among other things a handler can notify the next {@link ChannelHandler} in the * {@link ChannelPipeline} as well as modify the {@link ChannelPipeline} it belongs to dynamically. * * ChannelHandlerContext 是ChannelPipeline与ChannelHandler之间的粘合剂,负责事件透传至ChannelHandler及调用上或下一个ChannelHandler * DefaultChannelPipeline 持有N个ChannelHandlerContext(链表结构),每一个ChannelHandlerContext对应一个ChannelHandler, * ChannelHandlerContext创建于:channel.pipeline().addLast(ChannelHandler)方法。 * 事件源于ChannelPipeline-》链表Head(或Tail)-》ChannelHandlerContext-》ChannelHandler * 链表下一个(或上一个)->ChannelHandlerContext-》ChannelHandler * 链表下一个(或上一个)->ChannelHandlerContext-》ChannelHandler * 调用过程:ChannelPipeline--》ChannelHandlerContext--》ChannelHandler * <h3>Notify</h3> * 你能够在ChannelHander中调用ChannelHandlerContext的各种方法来触发相邻的ChannelHanndler事件。 * 一般情况下: 你在ChannelHander.channelActive(ChannelHandlerContext ctx) 方法中调用ChannelHandlerContext.fireChannelActive * 会触发下一个 ChannelHander.channelActive,如果没有调用,则下一个(之后的)ChannelHander不会被执行。 * * * <h3>Modifying a pipeline</h3> * 你能够通过ChannelHandlerContext.pipeline()方法获取ChannelPipeline,从而在运行时动态添加修改ChannelHandlers * * * <h3>Retrieving for later use</h3> * 你能够保存ChannelHandlerContext对象,以使之后使用。 * 例如在另外一个线程(非netty内部IO线程)触发事件 * * public class MyHandler extends ChannelDuplexHandler { * * private ChannelHandlerContext ctx; * * public void beforeAdd(ChannelHandlerContext ctx) { * this.ctx = ctx; * } * * public void login(String username, password) { * ctx.write(new LoginMessage(username, password)); * } * ... * } * </pre> * * <h3>Storing stateful information</h3> * 保存状态信息(线程安全的) * 你可以使用 attr(AttributeKey<T> key);方法存储状态信息,以便之后需要时取出。 * 请参考ChannelHandler了解状态信息管理 * * <h3>A handler can have more than one context</h3> * 请注意一个ChannelHandler 实例能够添加到多个ChannelPipeline中或同一个ChannelPipeline添加多次, * 每一次添加,都创建一个新的ChannelHandlerContext与其对应,即同一个ChannelHandler 实例可能对应 * 多个ChannelHandlerContext,在通过ChannelHandlerContext.attr保存或获取变量时,是保存在ChannelHandlerContext * 中,因而虽然只有一个ChannelHandler 实例,但添加的变量不是共享的。 * 该变量的范围:同一个Channel.pipeline().链表中同一个ChannelHandlerContext 范围。 * */ public interface ChannelHandlerContext extends AttributeMap, ChannelInboundInvoker, ChannelOutboundInvoker { /** * 返回绑定到ChannelHandlerContext的Channel */ Channel channel(); /** * 返回io线程对象(EventExecutor),用于执行内部IO任务 */ EventExecutor executor(); /** * * ChannelPipeline.add("name",ChannelHandler)--这个NAME */ String name(); /** * 返回ChannelHandlerContext对应的ChannelHandler(每一个ChannelHandlerContext对应一个ChannelHandler) */ ChannelHandler handler(); /** * 如果对应的ChannelHandler从ChannelPipeline被迁移,则返回true */ boolean isRemoved(); /** * 以下方法调用 ChannelHander相应方法:如fireChannelRegistered,则调用channelRegistered * DefaultChannelHandlerContext 中还实现了下一个或上一个ChannelHandler的事件触发。 **/ ChannelHandlerContext fireChannelRegistered(); ChannelHandlerContext fireChannelUnregistered(); ChannelHandlerContext fireChannelActive(); ChannelHandlerContext fireChannelInactive(); ChannelHandlerContext fireExceptionCaught(Throwable cause); ChannelHandlerContext fireUserEventTriggered(Object evt); ChannelHandlerContext fireChannelRead(Object msg); ChannelHandlerContext fireChannelReadComplete(); ChannelHandlerContext fireChannelWritabilityChanged(); ChannelHandlerContext read(); ChannelHandlerContext flush(); /** * 返回ChannelPipeline */ ChannelPipeline pipeline(); /** * Return the assigned {@link ByteBufAllocator} which will be used to allocate {@link ByteBuf}s. */ ByteBufAllocator alloc(); /** * @deprecated Use {@link Channel#attr(AttributeKey)} */ @Deprecated @Override <T> Attribute<T> attr(AttributeKey<T> key); /** * @deprecated Use {@link Channel#hasAttr(AttributeKey)} */ @Deprecated @Override <T> boolean hasAttr(AttributeKey<T> key); } abstract class AbstractChannelHandlerContext extends DefaultAttributeMap implements ChannelHandlerContext, ResourceLeakHint { //对应的ChannelHandler 是inbound?则处理ChannelInboundHandler 事件 private final boolean inbound //对应的ChannelHandler 是outbound?则处理ChannelOutboundHandler 事件 private final boolean outbound; //持有pipeline,ChannelHandlerContext与pipeline 是多对一关系 private final DefaultChannelPipeline pipeline; //ChannelHander 对应的名字 private final String name; //ChannelHandlerContext链,指向下一个ChannelHandlerContext, //DefaultChannelPipeline.addLast(ChannelHandler)建立的ChannelHandlerContext链 volatile AbstractChannelHandlerContext next; //ChannelHandlerContext链,指向上一个ChannelHandlerContext //DefaultChannelPipeline持有链头指向head //DefaultChannelPipeline.addLast(ChannelHandler)建立的ChannelHandlerContext链 //DefaultChannelPipeline持有链尾指向tail volatile AbstractChannelHandlerContext prev; /** * 构建器 * **/ AbstractChannelHandlerContext(DefaultChannelPipeline pipeline, EventExecutor executor, String name, boolean inbound, boolean outbound) { this.name = ObjectUtil.checkNotNull(name, "name"); this.pipeline = pipeline; this.executor = executor; this.inbound = inbound; this.outbound = outbound; } /* * firexxxx方法: * 以fireChannelActive为例 ,channelActive属于Inbound事件 * 从当前ChannelHandlerContext向下查找每一个inbound==true的ChannelHandlerContext,找到后 * 调用其对应handler.channelActive(ctx),channelActive内部处理完逻辑后,如果需要调用下一个 * ChannelHander.channelActive(ctx),则在channelActive内部写:ctx.fireChannelActive() * 由此继续循环调用下一个ChannelHandler.channelActive * */ @Override public ChannelHandlerContext fireChannelActive() { final AbstractChannelHandlerContext next = findContextInbound(); invokeChannelActive(next); return this; } private AbstractChannelHandlerContext findContextInbound() { AbstractChannelHandlerContext ctx = this; do { ctx = ctx.next; } while (!ctx.inbound); return ctx; } static void invokeChannelActive(final AbstractChannelHandlerContext next) { EventExecutor executor = next.executor(); if (executor.inEventLoop()) { next.invokeChannelActive(); } else { executor.execute(new Runnable() { @Override public void run() { next.invokeChannelActive(); } }); } } private void invokeChannelActive() { if (invokeHandler()) { try { ((ChannelInboundHandler) handler()).channelActive(this); } catch (Throwable t) { notifyHandlerException(t); } } else { fireChannelActive(); } } /** * wirte属于outbound事件,当通过ctx.write()方法被调用时,查找当前ChannelHandlerContext的上一个 * ChannelHandlerContext,调用其write方法,-》nextChannelHander.write -->next ....-->链表头 * DefaultPipeLine.HeadContext 实例.write :最终调用channel.unsafe.write 真正的向网络流中写出 **/ private void write(Object msg, boolean flush, ChannelPromise promise) { AbstractChannelHandlerContext next = findContextOutbound(); final Object m = pipeline.touch(msg, next); EventExecutor executor = next.executor(); if (executor.inEventLoop()) { if (flush) { next.invokeWriteAndFlush(m, promise); } else { next.invokeWrite(m, promise); } } else { //如果不是NioEventLoop内部io线程则创建任务添加到内部io线程执行队列中等待执行 AbstractWriteTask task; if (flush) { task = WriteAndFlushTask.newInstance(next, m, promise); } else { task = WriteTask.newInstance(next, m, promise); } safeExecute(executor, task, promise, m); } } private void invokeWrite(Object msg, ChannelPromise promise) { try { ((ChannelOutboundHandler) handler()).write(this, msg, promise); } catch (Throwable t) { notifyOutboundHandlerException(t, promise); } } private AbstractChannelHandlerContext findContextOutbound() { AbstractChannelHandlerContext ctx = this; do { ctx = ctx.prev; } while (!ctx.outbound); return ctx; } } /** *DefaultChannelHandlerContext 在AbstractChannelHandlerContext基础上,添加了判断是ChannelHandler是 * ChannelInboundHandler 还是ChannelOutboundHandler的方法 * */ final class DefaultChannelHandlerContext extends AbstractChannelHandlerContext { private final ChannelHandler handler; DefaultChannelHandlerContext( DefaultChannelPipeline pipeline, EventExecutor executor, String name, ChannelHandler handler) { super(pipeline, executor, name, isInbound(handler), isOutbound(handler)); if (handler == null) { throw new NullPointerException("handler"); } this.handler = handler; } @Override public ChannelHandler handler() { return handler; } private static boolean isInbound(ChannelHandler handler) { return handler instanceof ChannelInboundHandler; } private static boolean isOutbound(ChannelHandler handler) { return handler instanceof ChannelOutboundHandler; } }
相关推荐
Netty4.1的源码,欢迎大家下载。.............................................................................................................................................................................
这个“netty4.1源码”压缩包包含的是Netty框架4.1版本的源代码,对于深入理解Netty的工作原理、性能优化以及自定义功能扩展非常有帮助。 Netty的核心特性包括: 1. **异步非阻塞I/O**:Netty基于Java NIO(非阻塞I...
这个"Netty-4.1 源码包"包含了Netty框架的源代码,允许开发者深入理解其内部工作原理,优化自定义实现,或者排查问题。 在Netty 4.1 版本中,主要包含以下关键知识点: 1. **NIO (Non-blocking I/O)**: Netty 使用...
在本文中,我们将深入探讨 Netty 4.1 的中文API帮助文档和用户指南,以及如何利用这些资源来提升你的网络编程技能。 首先,Netty 4.1 中文API帮助文档是理解 Netty 内部机制的关键工具。它包含了详细的类、接口、...
这个“netty 4.1 中文.CHM”文件是一个压缩包,包含的是Netty 4.1版本的中文版帮助文档,对于开发者来说是一个非常宝贵的资源,特别是对于那些中文为母语的开发者,它提供了方便的理解和学习Netty的途径。...
Netty-4.1.97.Final源码提供了对Netty内部机制的深度洞察,对于Java程序员尤其是希望提升网络编程能力或进行定制化开发的人来说,是一份极其宝贵的资料。 首先,让我们从整体上了解Netty的架构设计。Netty采用了...
赠送jar包:netty-common-4.1.65.Final.jar; 赠送原API文档:netty-common-4.1.65.Final-javadoc.jar; 赠送源代码:netty-common-4.1.65.Final-sources.jar; 赠送Maven依赖信息文件:netty-common-4.1.65.Final....
netty案例,netty4.1中级拓展篇八《Netty心跳服务与断线重连》源码 https://mp.weixin.qq.com/s?__biz=MzIxMDAwMDAxMw==&mid=2650724845&idx=1&sn=8631c590ff4876ba0b7af64df16fc54b&scene=19#wechat_redirect
这个压缩包包含的是Netty 4.1的英文API帮助文档和用户指南,对于理解和使用Netty框架非常有帮助。 首先,我们来看`netty 4.1.CHM`文件,这是一个CHM(Compiled Help Manual)格式的帮助文档,通常包含了详细的API...
赠送jar包:netty-all-4.1.68.Final.jar; 赠送原API文档:netty-all-4.1.68.Final-javadoc.jar; 赠送源代码:netty-all-4.1.68.Final-sources.jar; 赠送Maven依赖信息文件:netty-all-4.1.68.Final.pom; 包含...
赠送jar包:netty-all-4.1.68.Final.jar; 赠送原API文档:netty-all-4.1.68.Final-javadoc.jar; 赠送源代码:netty-all-4.1.68.Final-sources.jar; 赠送Maven依赖信息文件:netty-all-4.1.68.Final.pom; 包含...
在本文中,我们将深入分析 Netty 4.1 源码中的 EchoServer 示例,以理解其核心组件和工作原理。 首先,我们关注 EchoServer 服务端的初始化,这涉及到两个关键组件:`bossGroup` 和 `workerGroup`。它们都是 `...
标题 "netty-netty-4.1.32.final-remark.zip" 提到了 Netty 的版本号 4.1.32.Final,这表明这是一个关于 Netty 4.1.32.Final 版本的资料包。"final" 表示这是该版本的最终发布,通常意味着经过了充分测试和稳定。...
这个“netty-netty-4.1.79.Final.tar.gz”文件是一个包含Netty 4.1.79.Final版本的压缩包,通常用于Java开发环境。解压后,我们可以得到Netty的源代码、库文件和其他相关资源。 Netty的核心特性包括: 1. **异步...
netty案例,netty4.1中级拓展篇十三《Netty基于SSL实现信息传输过程中双向加密验证》源码 ...
netty案例,netty4.1中级拓展篇一《Netty与SpringBoot整合》源码 https://mp.weixin.qq.com/s?__biz=MzIxMDAwMDAxMw==&mid=2650724796&idx=1&sn=ce5dc3c913d464b0e2e4e429a17bb01e&scene=19#wechat_redirect
netty-buffer-4.1.32.Final-sources.jar netty-buffer-4.1.32.Final.jar netty-build-22-sources.jar netty-build-22.jar netty-codec-4.1.32.Final-sources.jar netty-codec-4.1.32.Final.jar netty-codec-...
这个“netty-netty-4.1.69.Final.tar.gz”文件是Netty的最新稳定版本,版本号为4.1.69.Final,它是一个压缩包文件,通常包含源码、编译后的类库、文档和其他相关资源。 Netty的核心特点包括: 1. **异步事件驱动**...
netty案例,netty4.1基础入门篇十一《netty udp通信方式案例Demo》源码 https://mp.weixin.qq.com/s?__biz=MzIxMDAwMDAxMw==&mid=2650724927&idx=1&sn=a16bc8e98d6a27816da0896adcc83778&scene=19#wechat_redirect