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;
}