在理解了服务端接受链接,客户端建立链接的流程后,就来到了最为重要的写入环节,毕竟建立TCP链接不是用来做摆设,是用来实实在在的传输数据使用的。

读取的流程在这里有分析,不再进行过多描述
NioSocketChannel 读取信息

实例

  1. @Override
  2. public void channelRead(ChannelHandlerContext ctx, Object msg) {
  3. //其他业务逻辑
  4. //写入响应数据
  5. ctx.write(msg);
  6. }

对Netty有一点了解的同志对这里都比较熟悉,这里就是处理业务逻辑的地方了,我这里写的比较浅,真实的业务可能需要使用线程池来处理,不阻塞worker线程或者是boss线程。

那么在ctx.write中又发生了什么。

众所周知, Context 是上下文的概念,ChannelHandlerContext则表明是ChannelHandler的上下文,handler的串联则是由pipeline来进行连贯的,因此这里write触发到达的第一站即是 DefaultChannelPipeline 。随后的就是责任链模式的处理,最终抵达头部的write,在头部则是由unsafe来进行处理的

  1. @Override
  2. public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
  3. unsafe.write(msg, promise);
  4. }
  1. @Override
  2. public final void write(Object msg, ChannelPromise promise) {
  3. msg = filterOutboundMessage(msg);
  4. int size = pipeline.estimatorHandle().size(msg);
  5. outboundBuffer.addMessage(msg, size, promise);
  6. }
  1. public void addMessage(Object msg, int size, ChannelPromise promise) {
  2. Entry entry = Entry.newInstance(msg, size, total(msg), promise);
  3. //.. 还有一个比较重要的东西在这里跳过了
  4. // increment pending bytes after adding message to the unflushed arrays.
  5. // See https://github.com/netty/netty/issues/1619
  6. incrementPendingOutboundBytes(entry.pendingSize, false);
  7. }

在理解了pipeline的处理思路后,netty一个整体的写入就没有这么复杂了,但是这里还涉及到一个数据量的问题,放到后边说