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;
    }
posted @ 2021-10-30 16:04  Jonathan1  阅读(37)  评论(0编辑  收藏  举报