「我正在参与掘金会员专属活动-源码共读第一期,点击参与」
前言
一直大大咧咧, 有点健忘, 万万没想到, 这次写文章也健忘了, 之前我们分析Netty的启动流程讲了初始化和注册, 但是初始化和注册成功之后的doBind0()方法给忘的一干二净...
浅浅回顾一下:
- 在
Netty自定义启动类MyServer中执行了ServerBootstrap.bind(port).sync()方法启动Netty - 在
bind()方法的具体实现doBind()方法中先是执行了initAndRegister()方法, 对channel进行了初始化和注册 - 当初始化和注册完成之后就会执行到
doBind0()方法
如果可以的话, 大家最好是去看一下我之前的几篇文章了解一下整体流程:
- Netty源码分析(一) backlog 参数 - 掘金 (juejin.cn)
- Netty服务端初始化详解 - 掘金 (juejin.cn)
- Netty服务端启动流程分析 - 掘金 (juejin.cn)
- Netty之第一次 TCP 连接时发生了什么 - 掘金 (juejin.cn)
doBind0()方法
在这个方法中, 我们可以看到, 他就是channle.eventLoop()执行了一个Runnable
channle.eventLoop() 方法
channle.eventLoop()方法是一个多态, 执行的是AbstractChannel类下的方法, 在这个方法中可以看到, 他就是对eventLoop进行了赋值并返回, 至于这个this.eventLoop的初始化是在register 的时候
Netty服务端启动流程分析 - 掘金 (juejin.cn)
// 简单代码如下
@Override
public final void register(EventLoop eventLoop, final ChannelPromise promise) {
....
AbstractChannel.this.eventLoop = eventLoop;
...
}
通过我们打断点可以发现eventLoop的类型是NioEventLoop, 继承关系图如下所示
通过断点我们可以看到具体的执行过程就是进入到execute方法. 然后判断task是否为空, 不为空就进入最后的execute方法
在这个方法内部执行流程:
- 判断当前线程是否为
eventLoop线程 - 将任务添加到
taskQueue队列
addTask()方法详情, offerTask()方法的作用就是添加任务, 并返回是否添加成功, 如果添加失败, 就拒绝执行处理器
channel.bind()
接下来我们回到doBind0方法, 继续往下分析
channel是NioServerSocketChannel类, 而bind方法的实现类是在AbstractChannel里面
调用的是pipeline.bind(),pipeline它链接了ChannelHandlerContext,head是outbound,tail是inbound.
继续往下走 ,他会执行tail.bind()方法, 进入到AbstractChannelHandlerContext的bind()方法
如果你看过我上一篇文章, 就会有很熟悉的感觉, findContextOutbound方法, 我们在上一篇文章有说
执行完findContextOutbound()方法之后, 也是我们熟悉的一部分, 已经讲过很多次了
next.invokeBind(localAddress, promise);方法就是执行回调的
端口绑定的发生
再次进入这个方法
pipeline.head就是outbound, 所以在这里的时候会执行DefaultChannelPipeline.bind()方法
再往下走
我们到了AbstractChannel类的bind方法, 直接看doBind(), 打断点跳转
在这里就是执行了 JDK 原生的bind()方法来绑定端口信息, 至此, 我们的Netty启动系列终于算是差不多完结了, 吗?
下一篇文章开始继续攻克任务三, 为什么创建的channel是非阻塞的
本文内容到此结束了
如有收获欢迎点赞👍收藏💖关注✔️,您的鼓励是我最大的动力。
如有错误❌疑问💬欢迎各位大佬指出。
我是 宁轩 , 我们下次再见