Channel.write() 和 ChannelHandlerContext.write() 的區別

看了下netty 源代碼, 終於明白了
Channel.write() 和 ChannelHandlerContext.write() 的區別了
網上說的都不是很清楚 


首先註明我的netty版本
<dependency>
	<groupId>io.netty</groupId>
	<artifactId>netty-all</artifactId>
	<version>4.0.36.Final</version>
</dependency>



ChannelPipeline處理ChannelHandler的順序:


pipeline中的handler 處理的請求分爲兩類: 讀 和 寫
對於讀請求 : 從handler鏈表的 head  到  tail     挨個的處理, 跳過 ChannelOutboundHandler
對於寫請求 : 從handler鏈表的 tail      到  head 挨個的處理, 跳過 ChannelInboundHandler


1 調用 Channel.write(), 會直接調用ChannelPipeline.write()
    @Override
    public ChannelFuture write(Object msg) {
        return pipeline.write(msg);
    }

    @Override
    public ChannelFuture write(Object msg, ChannelPromise promise) {
        return pipeline.write(msg, promise);
    }

    @Override
    public ChannelFuture writeAndFlush(Object msg) {
        return pipeline.writeAndFlush(msg);
    }

    @Override
    public ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) {
        return pipeline.writeAndFlush(msg, promise);
    }

ChannelPipeline.write() 直接調用 tail指向的 最後一個handler的 write
    @Override
    public ChannelFuture write(Object msg) {
        return tail.write(msg);
    }

    @Override
    public ChannelFuture write(Object msg, ChannelPromise promise) {
        return tail.write(msg, promise);
    }
可以看到 調用的是ctx.prev獲取前一個, 所以寫從tail到head


2 調用ChannelHandlerContext.write() 
首先通過findContextOutbound找到當前ChannelHandlerContext的上一個OutboundContext
再調用它執行具體的寫入邏輯
    private void write(Object msg, boolean flush, ChannelPromise promise) {
        AbstractChannelHandlerContext next = findContextOutbound();
        EventExecutor executor = next.executor();
        if (executor.inEventLoop()) {
            next.invokeWrite(msg, promise);
            if (flush) {
                next.invokeFlush();
            }
        } else {
            AbstractWriteTask task;
            if (flush) {
                task = WriteAndFlushTask.newInstance(next, msg, promise);
            }  else {
                task = WriteTask.newInstance(next, msg, promise);
            }
            safeExecute(executor, task, promise, msg);
        }
    }

    private AbstractChannelHandlerContext findContextOutbound() {
        AbstractChannelHandlerContext ctx = this;
        do {
            ctx = ctx.prev;
        } while (!ctx.outbound);
        return ctx;
    }


結論:
Channel.write()  :                        從 tail 到 head 調用每一個outbound 的 ChannelHandlerContext.write
ChannelHandlerContext.write() : 從當前的Context, 找到上一個outbound, 從後向前調用 write


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章