述
上文中通过一个简单的例子,对netty有了一个大致的了解,本文来详细看一下Netty服务端的启动.
NettyServer解析
代码如下:
1 | public class NettyServer { |
和上篇文章中的NettyServer基本是一样的,详细看一下这段代码
首先创建了两个NioEventLoopGroup
对象,这两个对象可以看做是传统IO编程模型的两大线程组,bossGroup
表示监听端口,accept新连接的线程组,workerGroup
表示处理每一条连接的数据读写的线程组,不理解的同学可以看一下上一小节.
用生活中的例子来讲就是,一个工厂要运作,必然要有一个老板负责从外面接活,然后有很多员工,负责具体干活,老板就是bossGroup
,员工们就是workerGroup
,bossGroup
接收完连接,扔给workerGroup
去处理.
接下来,我们创建了一个引导类ServerBootstrap
,这个类将引导我们进行服务端的启动工作,直接new出来开搞
我们通过.group(bossGroup, workerGroup)
给引导类配置两大线程组,这个引导类的线程模型也就定型了
然后,我们指定我们服务端的IO模型为NIO,我们通过.channel(NioServerSocketChannel.class)
来指定 IO 模型,当然,这里也有其他的选择,如果你想指定 IO 模型为BIO,那么这里配置上OioServerSocketChannel.class
类型即可,当然通常我们也不会这么做,因为Netty的优势就在于NIO.
接着,我们调用childHandler()
方法,给这个引导类创建一个ChannelInitializer
,这里主要就是定义后续每条连接的数据读写,业务处理逻辑,不理解没关系,在后面我们会详细分析.ChannelInitializer
这个类中,我们注意到有一个泛型参数NioSocketChannel
,这个类呢,就是 Netty 对 NIO 类型的连接的抽象,而我们前面NioServerSocketChannel
也是对 NIO 类型的连接的抽象,NioServerSocketChannel
和NioSocketChannel
的概念可以和 BIO 编程模型中的ServerSocket
以及Socket
两个概念对应上
总结
启动一个Netty服务端,必须要指定三类属性,分别是线程模型、IO 模型、连接读写处理逻辑,有了这三者,之后在调用bind(8000)
,我们就可以在本地绑定一个 8000 端口启动起来
图片来源,侵删
自动绑定递增端口
首先看下代码,如下:
1 | public static void bind(final ServerBootstrap serverBootstrap, final int port) { |
就是把上面绑定端口的代码抽出来,单独的一个方法,上面的代码中serverBootstrap.bind(8000);
是一个异步方法,调用之后立即返回一个ChannelFuture
,然后我们给这个ChannelFuture
加了一个监听器GenericFutureListener
,然后里面重写了operationComplete()
方法,里面判断端口是否绑定成功,绑定失败的话,就又调用自身,把端口加1再去尝试绑定
比如说我传的port参数是1000,然后端口1000绑定失败的话,就又去绑定1001,1002…直到绑定成功
服务端启动时的一些其他功能
NettyServer代码如下:
1 | /** |
额外的一些方法及其功能都在代码的注释里了.从方法名上来看比如说上面的attr()
,childAttr()
,option()
,childOption()
…等等这些,可以看出一类是去设置服务端的,还有一类是针对连接的设置
附
上面的代码中还用到了一个类CommonConfig
,用来放一些常量,如下:
1 | public class CommonConfig { |