前言:之前的分析中我们知道了服务端对于客户端accept 以及read 事件的处理,那么客户端/服务端 进行数据写入时 数据流又是怎么传递的,本文继续对 write 探究;
1 Netty 服务端 数据如何写出:
通常我们使用SocketChannel 的channel 或者 ChannelHandlerContext 进行数据的写出,示例如下:
示例比较简单将要写的内容,按照一定编码格式转换为字节后,最终交由channel管道或者ChannelHandlerContext 进行写出;
**2 数据的写出流程:**数据流的写出是按照handler 一定规则,进行数据传递的一个过程;
2.1 ch.writeAndFlush 方法:
2.1.1 可以看到数据的写出是从tail 尾巴开始搜索handler 进行处理的:
2.1.2 最终进入到AbstractChannelHandlerContext 的write 方法:
private void write(Object msg, boolean flush, ChannelPromise promise) {
ObjectUtil.checkNotNull(msg, "msg");
try {
if (this.isNotValidPromise(promise, true)) {
ReferenceCountUtil.release(msg);
return;
}
} catch (RuntimeException var8) {
ReferenceCountUtil.release(msg);
throw var8;
}
AbstractChannelHandlerContext next = this.findContextOutbound(flush ? 98304 : '耀');
Object m = this.pipeline.touch(msg, next);
EventExecutor executor = next.executor();
if (executor.inEventLoop()) {
if (flush) {
next.invokeWriteAndFlush(m, promise);
} else {
next.invokeWrite(m, promise);
}
} else {
WriteTask task = AbstractChannelHandlerContext.WriteTask.newInstance(next, m, promise, flush);
if (!safeExecute(executor, task, promise, m, !flush)) {
task.cancel();
}
}
}
代码比较简单这里只对关键点进行简单解释:
- 从tail 向前依次找到outbound的handler 处理器并调用write 方法执行业务逻辑 :
2.2 ChannelHandlerContext .writeAndFlush 的数据写入,与channel.writeAndFlush 不同点:
ChannelHandlerContext 并没有从tail 向前找outbound 而是从当前的handler 向前寻找;
outbound 的handler 调用write :
3 简单总结:
在调用writeAndFlush 进行数据的写出时,netty 会依次寻找outboard的handler 处理器,依次调用write 方法进行业务逻辑的处理;