Netty解析二十:Netty中的拆包沾包处理
产生粘包和拆包问题的主要原因是,操作系统在发送TCP数据的时候,底层会有一个缓冲区,例如1024个字节大小,如果一次请求发送的数据量比较小,没达到缓冲区大小,TCP则会将多个请求合并为同一个请求进行发送,这就形成了粘包问题;如果一次请求发送的数据量比较大,超过了缓冲区大小,TCP就会将其拆分为多次发送,这就是拆包,也就是将一个大的包拆分为多个小包进行发送。
常用解决方案
由于底层的TCP无法理解上层的业务数据,所以在底层是无法保证数据包不被拆分和重组的,这个问题只能通过上层的应用协议栈设计来解决。业界的主流协议的解决方案,可以归纳如下:
- 消息定长,报文大小固定长度,例如每个报文的长度固定为200字节,如果不够空位补空格;
- 包尾添加特殊分隔符,例如每条报文结束都添加回车换行符(\r\n例如FTP协议)或者指定特殊字符作为报文分隔符,接收方通过特殊分隔符切分报文区分;
- 将消息分为消息头和消息体,消息头中包含表示信息的总长度(或者消息体长度)的字段;
- 更复杂的自定义应用层协议。
Netty中实现拆包沾包处理
- FixedLengthFrameDecoder:固定报文长度;
- LineBasedFrameDecoder与DelimiterBasedFrameDecoder:分隔符处理拆包沾包,LineBasedFrameDecoder:换行符,DelimiterBasedFrameDecoder用户指定符号;
- LengthFieldBasedFrameDecoder与LengthFieldPrepender:添加报文头来描述报文偏移量以及长度;
- 实现MessageToByteEncoder和ByteToMessageDecoder自定义处理。