技巧提示:基于Future异步编程,在主线程中通过调用future.isDone方法判断异步方法是否已完成,如果未完成,通过在该凭证上添加监听器(事件回调),操作完成后执行回调逻辑。
从上面的方法来看服务端的绑定流程包含初始化与绑定两个子流程,接下来将分别深入探讨。
2.1 通道初始化
基于NIO编程,需要先创建通道,然后将其注册到事件选择器,这个过程由 AbstractBootstrap 的 initAndRegister 方法实现。
实现的关键点如下:
代码@1:创建NIO服务端通道实现类NioServerSocketChannel的实例。
代码@2:调用 init 方法初始化通道。
代码@3:将通道注册到事件轮询器EventLoopGroup
代码@4::如果通道已注册,但发生了错误则调用通道close方法回收相关资源,如果未注册成功,则强制清除通道占用的资源,特别是文件占用符。
关于通道的注册逻辑已经在手把手教你如何编写一个NIO客户端 中已详细介绍,故接下来重点关注一下服务端通道的注册流程。
2.1.1 服务端通道初始化流程
AbstractBootstrap 的 init 方法是一个抽象方法,具体有其子类实现:
服务端通道的初始化代码由ServerBootstrap的init方法。
Step1:首先将通过ServerBootstrap设置的选项与附加选项初始化到通道中。
Step2:init 方法的关键点:将 handler 方法设置的事件链,同时新增 ServerBootstrapAcceptor 事件处理方法加入到 NioServerSocketChannel 的事件链,但并没有把 childHandler 中添加的事件链添加到NioServerSocketChannel。
读者朋友们,请停下来思考一下,为什么会这样?从现在可以肯定的是 handler 方法定义的事件处理方法将在与 NioServerSocketChannel 相关的事件发生时其作用。
要解开这个谜题,我们有必要来看看 ServerBootstrapAcceptor 是如何工作的。
2.1.2 ServerBootstrapAcceptor 详解
ServerBootstrapAcceptor 类图如下所示:
ServerBootstrapAcceptor方法只实现了inbound事件的channelRead事件。在详细探究它之前先看看属性:
- EventLoopGroup childGroup
事件执行器组,ServerBootstrap设置的从Reactor线程组,即Work线程组。
- ChannelHandler childHandler
ServerBootstrap#childHandler 设置的事件处理器,也就是用户定义的事件处理器。
接下来探究其 channelRead 方法的实现逻辑:
Step1:channelRead竟然传入的是一个Channel,那这个Channel对象是NioSocketChannel吗?
是的,原来当 OP_ACCEPT 事件触发后,Server端会通过调用ServerSocketChannel 的 accept()方法,将返回一个 NioSocketChannel,读写操作的载体,在NIO中负责数据的读写。
Step2:将通过 childHandler 定义的事件处理器绑定到 NioSocketChannel。
最终完成 NioServerSocketChannel 与 NioSocketChannel 的初始化与事件绑定。
关于 NioSocketChannel 详细的初始化流程蕴含在 ChannelInitializer,其机制已经在 手把手教你如何编写一个NIO客户端 中详细介绍。
2.2 NIO绑定机制
在通道完成初始化与注册后,服务端需要进行端口绑定,由 AbstractBootstrap 的 doBind0 方法实现。
bind 的核心实现最终是调用 Channel 的 bind 方法,最终由 AbstractChannel 类实现:
bind事件将传播,根据Netty事件传播机制,bind 属于 ChannelOutbound事件,最终将调用 HeadContext的bind方法,最终将调用Unsafe的bind方法,更加具体是调用 AbstractChannel的内部类AbstractUnsafe的bind方法,其代码如下所示:
doBind 方法是一个抽象方法,NIO服务端的实现:NioServerSocketChannel。
即最终通过调用NIO底层NioServerSocketChannel 的 bind 方法完成服务端通道的绑定操作,即实现服务端在特定端口监听客户客户端的连接请求。
行文至此开头部门提出的问题大家都能解答了不,为了倒逼读者朋友门真正能理解开头部分的问题,建议读者进行总结,真正做到带着问题阅读源码,当然可以加笔者私信:dingwpmz,共同交流探讨。
欢迎加笔者微信号(dingwpmz),拉您如技术交流加群探讨,关注『中间件兴趣圈』回复**【PDF】**可获取海量学习资料。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
最后
无论是哪家公司,都很重视基础,大厂更加重视技术的深度和广度,面试是一个双向选择的过程,不要抱着畏惧的心态去面试,不利于自己的发挥。同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,是不是能真的得到锻炼。
针对以上面试技术点,我在这里也做一些分享,希望能更好的帮助到大家。
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
g-E3L51L9A-1712803363480)]
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-ILxj333X-1712803363481)]