- 最近在阅读 Netty 的源码,但是有个地方一直没搞懂,
- 服务端启动类
ServerBootstrap.java
中有个嵌套类ServerBootstrapAcceptor
,它的channelRead(ctx, msg)
方法可以直接将Object msg
强转为Channel
对象。 - 在调用
channelRead(ctx, msg)
方法之前,Netty 是在什么地方将客户端的连接转换为 Channel 的呢?有点头疼! - 下图是
ServerBootstrapAcceptor
源代码截图,使用的Netty版本是netty-all:4.1.15.Final
2019年3月24日18:58:36
ServerBootstrap.ServerBootstrapAcceptor#channelRead(ctx, msg)
还是很晕,遂发帖提问。自己也在思索,寻找答案!就在发布问答之后的几个小时之后,我想到一种解题思路,现列举如下(仔细编写提问,有时也能帮助找到答案):IntelliJ IDEA
的Find Usages
找到调用关系的。(很惭愧,阅读源码不多,所以之前一直没使用Find Usages
这个功能来辅助摸清调用关系)processSelectedKey(k, ch)
方法了,这个方法的命名也能够说明问题,它是用来处理SelectionKey
的,NioEventLoop
的processSelectedKey(SelectionKey k, AbstractNioChannel ch)
方法中有对 java.nio 的SelectionKey
的OP_CONNECT
,OP_WRITE
,OP_READ
,OP_ACCEPT
的判断OP_ACCEPT
的处理,就找到了对客户端连接的处理了,SocketChannel
就在随后的代码中创建出来的(一个SocketChannel
就对应一个与客户端的连接!)。NioEventLoop#processSelectedKey(k, ch)
方法中调用了unsafe#read()
,这里的unsafe
对应的是AbstractNioMessageChannel
的内部类NioMessageUnsafe
,在NioMessageUnsafe#read()
方法内部又调用了NioServerSocketChannel
的doReadMessages(buf:List)
方法,就是在这里SocketChannel
被创建。