Netty源码剖析-接受数据

参考文献:极客时间傅健老师的《Netty源码剖析与实战》Talk is cheap.show me the code!

----主线:worker thread

  ①多路复用器(Selector)接受到OP_READ事件

  ②处理OP_READ事件:NioSocketChannel.NioSocketChannelUnsafe.read();

    -1分配一个初始1024字节的byte buffer来接受数据

    -2从Channel接受数据到byte buffer

    -3记录实际接受数据大小,调整下次分配byte buffer大小

    -4触发pipeline.fireChannelRead(byteBuf)把读取到的数据传播出去

    -5判断接受byte buffer是否满载而归,是:尝试继续读取直到没有数据或满16次,否:结束本轮读取,等待下次OP_READ事件

----源码解释:

 

    在NioEventLoop中的processSelectedKey()的unsafe.read()加个断点

Netty源码剖析-接受数据

 

 

 然后启动服务端和客户端...第一次启动的时候如下图:

Netty源码剖析-接受数据

 

 

 这里的channel=NioServerSocketChannel.处理的是OP_ACCEPT,我们直接放行,断点还停留在原地看看效果:

Netty源码剖析-接受数据

 

 

 可以清楚的看到这时候的channel=NioSocketChannel;这个时候我们跟进去看看:

Netty源码剖析-接受数据

 

 

 进入read()方法后可以看到这行代码,byteBuf = allocHandle.allocate(allocator);表示尽可能分配合适的大小:“guess”;下面一行“allocHandle.lastBytesRead(doReadBytes(byteBuf));”则表示读并且记录读了多少,如果读满了下次继续的话直接扩容;先跟进看看allocate();

Netty源码剖析-接受数据

 

 

 然后在进去guess();

Netty源码剖析-接受数据

 

 

 进来可以发现返回的是“1024”,接着往下走:

Netty源码剖析-接受数据

进入doReadBytes();

Netty源码剖析-接受数据

可以发现这里有一个“byteBuf.writeBytes()”;接着跟进去看看:

Netty源码剖析-接受数据

再跟进"setBytes()"

Netty源码剖析-接受数据

 

 

 这里就能看出来是“SocketChannel.read()”;然后再接着往下执行返回:

Netty源码剖析-接受数据

 

 

 不难看出读取了一次:

Netty源码剖析-接受数据

 

 下面的pipeline.fireChannelRead(byteBuf);则是处理业务逻辑的地方,pipeline上执行,继续往下走:

Netty源码剖析-接受数据

 

 allocHandle.readComplete();记录这次读事件共读了多少数据,计算下次分配的大小

pipeline.fireChannelReadComplete();相当于完成本次读事件的处理

 

----总结:

  读取数据的本质:sun.nio.ch.SocketChannelImpl#read(java.nio.ByteBuffer)

  NioSocketChannel read()是读数据,NioServerSocketChannel read()是创建连接

  pipeline.fireChannelReadComplete();表示一次事件处理完成

    pipeline.fireChannelRead(byreBuf);一次读取数据完成,一次读事件处理可能会包含多次读数据操作

  为什么最多只尝试读取16次?“雨露均沾”

  AdaptiveRecvByteBufAllocator对bytebuf的猜测:放大果断,缩小谨慎(需要连续两次判断)

我只想做的更好,仅此而已。

 

上一篇:base64编码处理大文件


下一篇:netty pooled vs unpooled ByteBuf