Netty Bootstrap(图解)|秒懂 (3)

SO_REUSEADDR
  Socket参数,地址复用,默认值False。有四种情况可以使用:
(1).当有一个有相同本地地址和端口的socket1处于TIME_WAIT状态时,而你希望启动的程序的socket2要占用该地址和端口,比如重启服务且保持先前端口。
(2).有多块网卡或用IP Alias技术的机器在同一端口启动多个进程,但每个进程绑定的本地IP地址不能相同。
(3).单个进程绑定相同的端口到多个socket上,但每个socket绑定的ip地址不同。(4).完全相同的地址和端口的重复绑定。但这只用于UDP的多播,不用于TCP。

SO_LINGER
  Socket参数,关闭Socket的延迟时间,默认值为-1,表示禁用该功能。-1表示socket.close()方法立即返回,但OS底层会将发送缓冲区全部发送到对端。0表示socket.close()方法立即返回,OS放弃发送缓冲区的数据直接向对端发送RST包,对端收到复位错误。非0整数值表示调用socket.close()方法的线程被阻塞直到延迟时间到或发送缓冲区中的数据发送完毕,若超时,则对端会收到复位错误。

SO_BACKLOG
  Socket参数,服务端接受连接的队列长度,如果队列已满,客户端连接将被拒绝。默认值,Windows为200,其他为128。

b.option(ChannelOption.SO_BACKLOG, 1024)

表示系统用于临时存放已完成三次握手的请求的队列的最大长度,如果连接建立频繁,服务器处理创建新连接较慢,可以适当调大这个参数.

SO_BROADCAST
  Socket参数,设置广播模式。

5: 装配流水线

​ ChannelPipeline 这是Netty处理请求的责任链,这是一个ChannelHandler的链表,而ChannelHandler就是用来处理网络请求的内容的。

​ 每一个channel ,都有一个处理器流水线。

​ 装配 child channel 流水线,调用 childHandler()方法,传递一个ChannelInitializer 的实例。

​ 在 child channel 创建成功,开始通道初始化的时候,在bootstrap启动器中配置的 ChannelInitializer 实例就会被调用。

​ 这个时候,才真正的执行去执行 initChannel 初始化方法,开始通道流水线装配。

​ 流水线装配,主要是在流水线pipeline 的后面,增加负责数据读写、处理业务逻辑的handler。

b.childHandler(new ChannelInitializer<SocketChannel>() { //有连接到达时会创建一个channel protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new ProtobufDecoder()); ch.pipeline().addLast(new ProtobufEncoder()); // pipeline管理channel中的Handler // 在channel队列中添加一个handler来处理业务 ch.pipeline().addLast("serverHandler", serverHandler); } });

说明一下,ChannelInitializer这个类中,有一个泛型参数 SocketChannel,这里的类型,需要和前面的Channel类型对应上。

顺便说一下处理器。

处理器 ChannelHandler 用来处理网络请求内容,有ChannelInboundHandler和ChannelOutboundHandler两种,ChannlPipeline会从头到尾顺序调用ChannelInboundHandler处理网络请求内容,从尾到头调用ChannelOutboundHandler 处理网络请求内容。

pipeline 流水线的图,大致如下:

img

如何装配parent 通道呢?

使用serverBootstrap.handler() 方法 。 handler()方法,可以和前面分析的childHandler()方法对应起来。childHandler()用于指定处理新连接数据的读写处理逻辑。 handler()方法装配parent 通道。

比方说:

serverBootstrap.handler(new ChannelInitializer() { protected void initChannel(NioServerSocketChannel ch) { System.out.println("服务端启动中"); } } )

handler()用于指定在服务端启动过程中的一些逻辑,通常情况下呢,我们用不着这个方法。

6: 开始绑定server

// 通过调用sync同步方法阻塞直到绑定成功 ChannelFuture channelFuture = b.bind().sync(); LOGGER.info(ChatServer.class.getName() + " started and listen on " + channelFuture.channel().localAddress());

这个也很简单。

7: ChannelFuture

ChannelFuture 在Netty中的所有的I/O操作都是异步执行的,这就意味着任何一个I/O操作会立刻返回,不保证在调用结束的时候操作会执行完成。因此,会返回一个ChannelFuture的实例,通过这个实例可以获取当前I/O操作的状态。

// 7 监听通道关闭事件 // 应用程序会一直等待,直到channel关闭 ChannelFuture closeFuture= channelFuture.channel().closeFuture(); closeFuture.sync();

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wppxzg.html