netty源码分析一
一个channel对应一个pipeline,pipeline是channel的成员变量,初始化channel的时候就初始化了pipeline,一个pipeline里面包含多个handler,其中在初始化handler的时候,会同时初始化head/tail两个handlerContext;一个DefaultChannelHandlerContext
里面包含一个handler,换句话说handler是以handlerContext
的形式存在。
public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractChannel.class);
private final Channel parent; // 代表父类channel
private final ChannelId id; // 采用默认方式生成的全局唯一id
//实现具体的连接与读/写数据,如网络的读/写、链路关闭、发起连接等
private final Unsafe unsafe; // Unsafe实例
//一个Handler的容器,也可以将其理解为一个Handler链。Handler主要处理数据的编/解码和业务逻辑。
private final DefaultChannelPipeline pipeline; // 当前channel对应的DefaultChannelPipeline
private final VoidChannelPromise unsafeVoidPromise = new VoidChannelPromise(this, false);
private final CloseFuture closeFuture = new CloseFuture(this);
private volatile SocketAddress localAddress;
private volatile SocketAddress remoteAddress;
private volatile EventLoop eventLoop; // 当前channel注册的EventLoop 每个Channel对应一条EventLoop线程。
private volatile boolean registered;
private boolean closeInitiated;
private Throwable initialCloseCause;
/**
* Cache for the string representation of this channel
*/
private boolean strValActive;
private String strVal;
/**
* Creates a new instance.
*
* @param parent the parent of this channel. {@code null} if there's no parent.
*/
protected AbstractChannel(Channel parent) {
this.parent = parent;
id = newId();
unsafe = newUnsafe();
pipeline = newChannelPipeline(); // 创建pipeline
}
}
下面是pipeline的具体实现类,可以看到在初始化pipeline的时候,也初始化了head/tail两个变量, 同时改变了指向
public class DefaultChannelPipeline implements ChannelPipeline {
// pipeline里面
final AbstractChannelHandlerContext head;
final AbstractChannelHandlerContext tail;
private final Channel channel;
private final ChannelFuture succeededFuture;
private final VoidChannelPromise voidPromise;
private final boolean touch = ResourceLeakDetector.isEnabled();
private boolean registered;
protected DefaultChannelPipeline(Channel channel) {
this.channel = ObjectUtil.checkNotNull(channel, "channel");// 这个方法值得借鉴
succeededFuture = new SucceededChannelFuture(channel, null);
voidPromise = new VoidChannelPromise(channel, true);
// 创建两个节点
tail = new TailContext(this); //AbstractChannelHandlerContext
head = new HeadContext(this); //AbstractChannelHandlerContext的子类
head.next = tail;
tail.prev = head;
}
}
pipeline里面保存着链表的头结点和尾节点,因为很容易向链表中添加元素,具体方法如下:
// 这个方法向链表里面添加节点
private void addLast0(AbstractChannelHandlerContext newCtx) {
AbstractChannelHandlerContext prev = tail.prev;
newCtx.prev = prev;
newCtx.next = tail;
prev.next = newCtx;
tail.prev = newCtx;
}
在执行handler的过程中需要一个一个的遍历链表,具体方法如下:
private AbstractChannelHandlerContext findContextInbound(int mask) {// 这个是从链表里面获取一个元素 那么是怎么添加进去的呢?这个方法见上面
logger.info("findContextInbound-_-");
AbstractChannelHandlerContext ctx = this;
do {
ctx = ctx.next;
} while ((ctx.executionMask & mask) == 0);
return ctx;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)