在上一节介绍了服务端ACCEPT客户端的信息后,对 对端 的socket 进行了一次初始化和注册的过程,在这个过程中呢, NioSocketChannel 被绑定到了一个 NioEventLoop 上.

由于服务端的select操作也是发生在 NioeventLoop#run 中,所以基本上客户端对于信息的触发也是在这里.

服务端accept即将到来的请求.
只不过这里的 unsafe 由NioServerSocketChannel中的NioMessageUnsafe 变成了NioSocketChannel中的NioSocketChannelUnsafe

同理,还是关注他们的 read 方法. 但是这次的 read 和server的就不一样了,server是建立TCP链接后续的一些初始化,而这里的 read 是为了处理业务逻辑,所以必然是要涉及读取socket的信息的.
方法在NioByteUnsafe#read中,这里就不贴了.

关于分配Buffer这块留到下一个小节讲,稍微有一些区别的点就在于 doReadBytes(byteBuf)

NioSocketChannel#doReadBytes

  1. @Override
  2. protected int doReadBytes(ByteBuf byteBuf) throws Exception {
  3. final RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();
  4. //byteBuf.writableBytes() 还剩下多少空间能写入
  5. //尝试读取这么多,byteBuf.writableBytes()
  6. allocHandle.attemptedBytesRead(byteBuf.writableBytes());
  7. //这里描述起来就比较简单,从socket中读取数据,写入到buffer中去.
  8. return byteBuf.writeBytes(javaChannel(), allocHandle.attemptedBytesRead());
  9. }

这一块主要是读取数据.

从代理中可以看得到,他是分了好几次取的,每取一次就触发一次read事件,交付给后述的业务逻辑进行处理.
那么什么情况下,这里会是循环多次呢?

当需要读取的有1000时,但是socket一次仅读取了500,那么触发完读的时候,业务确认数据不够,再来一次,发现够了处理. 最后触发读取完成事件.