前言
一直大大咧咧, 有点健忘, 万万没想到, 这次写文章也健忘了, 之前我们分析Netty的启动流程讲了初始化和注册, 但是初始化和注册成功之后的doBind0()方法给忘的一干二净...
浅浅回顾一下:
- 在
Netty自定义启动类MyServer中执行了ServerBootstrap.bind(port).sync()方法启动Netty - 在
bind()方法的具体实现doBind()方法中先是执行了initAndRegister()方法, 对channel进行了初始化和注册 - 当初始化和注册完成之后就会执行到
doBind0()方法
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是非阻塞的