参考 https://blog.csdn.net/u010853261/article/details/55803933
TCP以流的方式进行数据传输,上层应用协议为了对消息进行区分,往往采用如下4种方式。
(1)消息长度固定:累计读取到固定长度为LENGTH之后就认为读取到了一个完整的消息。然后将计数器复位,重新开始读下一个数据报文。
(2)回车换行符作为消息结束符:在文本协议中应用比较广泛。
(3)将特殊的分隔符作为消息的结束标志,回车换行符就是一种特殊的结束分隔符。
(4)通过在消息头中定义长度字段来标示消息的总长度。
netty中针对这四种场景均有对应的解码器作为解决方案,比如:
(1)通过FixedLengthFrameDecoder 定长解码器来解决定长消息的黏包问题;
(2)通过LineBasedFrameDecoder和StringDecoder来解决以回车换行符作为消息结束符的TCP黏包的问题;
(3)通过DelimiterBasedFrameDecoder 特殊分隔符解码器来解决以特殊符号作为消息结束符的TCP黏包问题;
(4)最后一种,也是本文的重点,通过LengthFieldBasedFrameDecoder 自定义长度解码器解决TCP黏包问题。
大多数的协议在协议头中都会携带长度字段,用于标识消息体或则整包消息的长度。LengthFieldBasedFrameDecoder通过指定长度来标识整包消息,这样就可以自动的处理黏包和半包消息,只要传入正确的参数,就可以轻松解决“读半包”的问题。
消息的第一个字段是长度字段,且未包含消息头长度,消息解码后,包含长度(0,2,0,0)
其中前2个字节是标识长度的字节,后面12给字节是消息体
lengthFieldOffset = 0;//长度字段的偏差
lengthFieldLength = 2;//长度字段占的字节数
lengthAdjustment = 0;//添加到长度字段的补偿值
initialBytesToStrip = 0。//从解码帧中第一次去除的字节数
消息的第一个字段是长度字段, 且未包含消息头长度 ,消息解码后,不包含长度(0,2,0,2)
消息字段第一个字段是长度字段,包含了消息头的长度,消息解码后,也包含长度查(且未包含消息头长度)
...
消息的第一个字段不是长度字段后面还有消息长度在中间的。lengthFieldOffset
构造参数的定义方式,可以参考
LengthFieldBasedFrameDecoder解决复杂的自定义协议-粘包与半包问题