最通用TCP黏包解决方案

参考 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解决复杂的自定义协议-粘包与半包问题

https://blog.csdn.net/u014801432/article/details/81909902

你可能感兴趣的:(最通用TCP黏包解决方案)