NioEventLoop中已经知道,当服务端绑启动之后,服务端的channel已经注册到boos reactor线程中,reactor不断检测有新的事件,直到检测出有accept事件发生。当程序进入processSelectedKey方法中时,判断条件SelectionKey.OP_READ 表示boos reactor线程已经轮询到 SelectionKey.OP_ACCEPT 事件,说明有新的连接进入,此时将调用channel的 unsafe来进行实际的操作。如下图:
channel底层都会有一个与unsafe绑定,每种类型的channel实际的操作都由unsafe来实现
服务端对应的channel的unsafe是 NioMessageUnsafe
入到它的read方法,进入新连接处理的第二步
注册到reactor线程:
NioMessageUnsafe.java
assert eventLoop().inEventLoop();
断言确定该read方法必须是reactor线程调用,
final ChannelPipeline pipeline = pipeline();
然后拿到channel对应的pipeline
int localRead = doReadMessages(readBuf);
调用 doReadMessages 方法不断地读取消息,用 readBuf 作为容器
然后调用 pipeline.fireChannelRead(),将每条新连接经过一层服务端channel的洗礼
之后清理容器,触发 pipeline.fireChannelReadComplete()
1. doReadMessages()
NioServerSocketChannel继承AbstractNioMessageChannel,实现了AbstractNioMessageChannel中的doReadMessages()方法:
netty调用jdk底层nio的边界 javaChannel().accept();,由于netty中reactor线程第一步就扫描到有accept事件发生,因此,这里的accept方法是立即返回的,返回jdk底层nio创建的一条channel;
buf.add(new NioSocketChannel(this, ch));
netty将jdk的 SocketChannel 封装成自定义的 NioSocketChannel,加入到list里面,这样外层就可以遍历该list,做后续处理
2.pipeline.fireChannelRead(NioSocketChannel)
简单介绍一下pipeline这个组件:
在netty的各种类型的channel中,都会包含一个pipeline,字面意思是管道,我们可以理解为一条流水线工艺,流水线工艺有起点,有结束,中间还有各种各样的流水线关卡,一件物品,在流水线起点开始处理,经过各个流水线关卡的加工,最终到流水线结束
对应到netty里面,流水线的开始就是HeadContxt,流水线的结束就是TailConext,HeadContxt中调用Unsafe做具体的操作,TailConext中用于向用户抛出pipeline中未处理异常以及对未处理消息的警告
pipeline.fireChannelRead(NioSocketChannel); 最终通过head->unsafe->ServerBootstrapAcceptor的调用链,调用到这里的 ServerBootstrapAcceptor 的channelRead方法:
网友评论