在理解了服务端接受链接,客户端建立链接的流程后,就来到了最为重要的写入环节,毕竟建立TCP链接不是用来做摆设,是用来实实在在的传输数据使用的。
读取的流程在这里有分析,不再进行过多描述
NioSocketChannel 读取信息
实例
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
//其他业务逻辑
//写入响应数据
ctx.write(msg);
}
对Netty有一点了解的同志对这里都比较熟悉,这里就是处理业务逻辑的地方了,我这里写的比较浅,真实的业务可能需要使用线程池来处理,不阻塞worker线程或者是boss线程。
那么在ctx.write中又发生了什么。
众所周知, Context 是上下文的概念,ChannelHandlerContext则表明是ChannelHandler的上下文,handler的串联则是由pipeline来进行连贯的,因此这里write触发到达的第一站即是 DefaultChannelPipeline
。随后的就是责任链模式的处理,最终抵达头部的write,在头部则是由unsafe来进行处理的
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
unsafe.write(msg, promise);
}
@Override
public final void write(Object msg, ChannelPromise promise) {
msg = filterOutboundMessage(msg);
int size = pipeline.estimatorHandle().size(msg);
outboundBuffer.addMessage(msg, size, promise);
}
public void addMessage(Object msg, int size, ChannelPromise promise) {
Entry entry = Entry.newInstance(msg, size, total(msg), promise);
//.. 还有一个比较重要的东西在这里跳过了
// increment pending bytes after adding message to the unflushed arrays.
// See https://github.com/netty/netty/issues/1619
incrementPendingOutboundBytes(entry.pendingSize, false);
}
在理解了pipeline的处理思路后,netty一个整体的写入就没有这么复杂了,但是这里还涉及到一个数据量的问题,放到后边说