Netty-操作篇

发布时间 2023-11-20 21:54:33作者: 轻寒

服务端创建步骤

步骤一:创建ServerBootstrap实例。

步骤二:设置并绑定Reactor线程池。

步骤三:设置并绑定服务端Channel。

步骤四:链路建立的时候创建并初始化ChannelPipeline(非必须)。

用于处理网络事件:

1.链路注册、激活、断开、发生异常

2.接收到请求消息

3.请求消息接收并处理完毕

4.发送应答消息

5.发生用户自定义事件

步骤五:初始化ChannelPipeline完成之后,添加并设置ChannelHandler。

比较实用的ChannelHandler:

1.系统编码框架:ByteToMessageCodec

2.通用基于长度的半包解码器:LengthFieldBaseFrameDecoder

3.码流日志打印Handler:LoggingHandler

4.SSL安全认真Handler:SslHandler

5.链路空闲检测Handler:IdleStateHandler

6.流量整型Handler:ChannelTrafficShapingHandler

7.Base64编解码:Base64Decoder和Base64Encoder

步骤六:绑定并启动监听端口

步骤七:Selector轮询

步骤八:当轮询到准备就绪的Channel之后,就由Reactor线程NioEventLoop执行ChannelPipeline的相应方法,最终调度并执行ChannelHandler

步骤九:执行Netty系统ChannelHandler和用户添加定制的ChannelHandler。

常见问题

异步操作-ChannelFuture

1.Netty强烈建议通过添加监听器的方式获取I/O操作结果

2.可以同时添加一个或多个GenericFutureListener,也可以用remove方法删除

3.注意不要在ChannelHandler中调用ChannelFuture的await()方法,这会导致死锁。原因是发起I/O操作之后,由I/O线程负责异步通知发起I/O才注意的用户线程,如果I/O线程和用户线程是同一个线程,就会导致I/O线程等待自己通知自己操作完成,这就导致了死锁

粘包问题

解决策略:

1.消息定长,例如每个报文的大小固定为200字节,如果不够,空位补空格。

2.在包尾增加回车换行符进行分割,例如FTP协议。

3.将消息分为消息头和消息体,消息头包含消息总长度(或者消息体长度)的字段,通常设计思路为第一个字段使用int32来表示消息的总长度。

4.更复杂的应用层协议。

内置的编码解码器

1.LineBasedFrameDecoder:工作原理是它依次遍历ByteBuf中的可读字节,判断看是否有“\n”或者“\r\n”,如果有,就以此位置为结束位置,从可读索引到结束位置区间的字节就组成了一行。它是以换行符为结束标志的解码器,支持携带结束符或者不携带结束符两种解码方式,同时支持配置单行的最大长度。如果连续读取到最大长度后仍然没有发现换行符,就会抛出异常,同时忽略掉之前读取到的异常码流。

2.StringDecoder:将接收到的对象转换成字符串,然后继续调用后面的Handler。

3.LineBasedFrameDecoder+StringDecoder组合就是按行切换的文本解码器,它被设计用来支持TCP的粘包和拆包。