netty源码浅析--服务器bind

本文深入分析了Netty服务器bind操作的源码,从validate()和doBind()方法开始,探讨了初始化、注册、创建channel以及设置非阻塞模式的过程。重点讲解了ChannelPipeline的Handler链结构和事件驱动机制,最后阐述了如何通过unsafe工具类调用Java socket进行绑定。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        上一篇我们提到服务器启动的过程,这篇我们来分析一下服务器bind的过程。

这里写图片描述

        validate()方法只做了一些必要的验证。如果有特殊的验证需求,用户可以重写validate()方法。bind的主要逻辑在doBind中。根据小编阅读源码的经历总结出一点。许多方法里面只做了一些校验,而真正的逻辑全部都在do开头的方法中。

这里写图片描述

        从调用的第一个方法可以看出首先是初始化和注册,那这里到底是初始化和注册什么呢?我们接着看initAndRegister()方法。

这里写图片描述

        从名字中也能看出,会先创建channel。createChannel是一个抽象方法,具体的逻辑在类ServerBootstrap中实现。

这里写图片描述

        next方法选中一个EventLoop初始化channel。

这里写图片描述

        newChannel使用反射来创建channel。使用的是NioServerSocketChannel类。在使用反射创建channel时,会触发NioServerSocketChannel实例化。在调用父类构造函数时传入了SelectionKey.OP_ACCEPT。熟悉Java nio的朋友都知道,在使用Java nio的时候会对selector注册SelectionKey.OP_ACCEPT。难道是在父类中实现的吗?接着来看看NioServerSocketChannel父类方法。

这里写图片描述

        在AbstractNioChannel类中只是对readInterestOp赋值。并没有对channel注册。刚开始看源码的时候,小编也百事不得其解。再查阅了大量的资料后,得知,Channel注册到Selector有两种方式,一种是调用Channel的register方法,第二种是设置SelectionKey的interestOps的值。netty是用了第二种方式,通过设置SelectionKey的interestOps来注册Channel关心的事情,把实际的注册延迟了。然后设置channel为非阻塞模式。channel创建完了,接着看看init又干了些什么。

这里写图片描述

        前面主要是设置一些属性,不再累述。主要在p.addLast()方法的匿名内部类中。

这里写图片描述

在channelInitializer类中会调用channelRegistered方法。initChannel会初始化ServerBootstrapAcceptor类。再实例化的过程中会初始化类DefaultChannelHandlerContext。在Netty的编程模型中,Handler是程序猿主要关心的地方,猿可以在自定义的Handler中实现业务逻辑。在类中有这样两段代码。

这里写图片描述

        是不是有点像双链表。对。Handler其实是带head和tail节点的双链表。由此可以知道,netty的ChannelPipeline包含两条线路,up、down。而这两条链路使用的是同一套handler。在javadoc中有一张图形象的说明了这个过程。

这里写图片描述

        Upstream对应上行,接收到的消息、被动的状态改变,都属于Upstream。Downstream则对应下行,发送的消息、主动的状态改变,都属于Downstream。在没加入任何handler时,是这样的。

这里写图片描述

将ServerBootstrapAcceptor添加到handler链后是这样的。

这里写图片描述

        然后会调用handler的生命周期方法fireChannelRegistered()。这就是事件驱动的具体体现。具体fireChannelRegistered()逻辑不再分析。接着是regist方法。在实现注册之前,netty先创建了channelPromise对象。这里简单说一下,netty所有的方法都是异步,而实现异步的最好方法就是使用基于回调的事件机制。而netty使用的是基于事件监听的方式,这种基于事件监听的方式要比基于回调的事件机制效率更高一点。以后的文章中会分析这种机制。

这里写图片描述
这里写图片描述

        netty会把regist封装成多线程任务,然后将其加入的队列中,由eventloop执行。具体的regist的业务逻辑在AbstractChannel类中。

这里写图片描述
具体的注册逻辑不在分析,不理解的请看java nio的相关知识。

这里写图片描述

        bind前面和regist差不多。也是把具体的逻辑封装成多线程任务。然后将其丢进任务队列中。tail会代理unsafe工具类进行绑定。

这里写图片描述

由bind的调用栈可知,最终会Java socket进行绑定。至此服务器bind过程分析完毕。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值