版权声明:本文为博主原创文章,未经博主允许不得转载。
看了下netty 源代码, 终于明白了
Channel.write() 和 ChannelHandlerContext.write() 的区别了
网上说的都不是很清楚
首先注明我的netty版本
```
- <span style="font-size:14px;"><dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty-all</artifactId>
- <version>4.0.36.Final</version>
- </dependency></span>
- ```
ChannelPipeline处理ChannelHandler的顺序:
pipeline中的handler 处理的请求分为两类: 读 和 写
对于读请求 : 从handler链表的 head 到 tail 挨个的处理, 跳过 ChannelOutboundHandler
对于写请求 : 从handler链表的 tail 到 head 挨个的处理, 跳过 ChannelInboundHandler
1 调用 Channel.write(), 会直接调用ChannelPipeline.write()
[java] view plain copy
- @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[java] view plain copy
- @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
再调用它执行具体的写入逻辑
[java] view plain copy
- 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);
- }
- }
[java] view plain copy
- 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