在上一节介绍了服务端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
@Override
protected int doReadBytes(ByteBuf byteBuf) throws Exception {
final RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();
//byteBuf.writableBytes() 还剩下多少空间能写入
//尝试读取这么多,byteBuf.writableBytes()
allocHandle.attemptedBytesRead(byteBuf.writableBytes());
//这里描述起来就比较简单,从socket中读取数据,写入到buffer中去.
return byteBuf.writeBytes(javaChannel(), allocHandle.attemptedBytesRead());
}
这一块主要是读取数据.
从代理中可以看得到,他是分了好几次取的,每取一次就触发一次read事件,交付给后述的业务逻辑进行处理.
那么什么情况下,这里会是循环多次呢?
当需要读取的有1000时,但是socket一次仅读取了500,那么触发完读的时候,业务确认数据不够,再来一次,发现够了处理. 最后触发读取完成事件.