Netty-操作篇
服务端创建步骤
步骤一:创建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的粘包和拆包。