netty4源码阅读与分析---netty4如何处理tcp的粘包,拆包

TCP是一个基于“流”的数据传输协议,所谓流,就是没有边界的一长串二进制数据。TCP作为传输层协议并不不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行数据包的划分或者组合,所以在业务上认为是一个完整的包,可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题。

1,为什么会出现粘包和拆包

a,如果应用程序写入的数据大小超过了tcp缓冲区的大小,那必须将数据进行拆分

b,如果发送的数据超过了MSS(最大报文长度),将会发生拆包

c,如果要发送的数据小于TCP发送缓冲区的大小,TCP将多次写入缓冲区的数据一次发送出去,这种情况下将会发生粘包

d,如果接收端的业务层没有及时处理完缓冲区的数据,也可能发生粘包

e,其他

2,如何解决粘包拆包问题,保证数据准确?

通过上面的分析,我们知道了原因,解决问题的关键是需要能够区分出边界,那么我们在传输的时候需要加上边界信息,如何做呢?主要有以下几种方式:

a,将消息分为消息头和消息尾,消息头包含了消息内容的总长度

b,消息定长,不足补0

c,在包的尾部添加特殊字符作为标识边界

d,使用其他协议或自定义协议

3,netty是如何解决tcp粘包拆包问题?

Netty提供了多个解码器,可以进行分包的操作,分别是:LineBasedFrameDecoder 、DelimiterBasedFrameDecoder、FixedLengthFrameDecoder、LengthFieldBasedFrameDecoder,接下来我们挨个看下。

a,LineBasedFrameDecoder,我们主要看下decode方法,发现其中有一行:

final int delimLength = buffer.getByte(eol) == '\r'? 2 : 1;

原来它是以回车换行符来作为边界区分标志的,不过有个缺点,如果消息内容中就有回车换行符时会存在误判。

b,DelimiterBasedFrameDecoder是分隔符解码器,用户可以指定自己的分隔符,DelimiterBasedFrameDecoder可以自动完成以分隔符作为结束标识的消息的解码。回车换行解码器实际上是一种特殊的DelimiterBasedFrameDecoder解码器,与LineBasedFrameDecoder类似,消息内容中如果也存在指定的分割符会导致误判

c,FixedLengthFrameDecoder,这个就是消息定长的解码器,编解码比较简单,实用性强

d,LengthFieldBasedFrameDecoder,协议头中会携带长度字段,用于标识消息体或者整包消息的长度

实际使用中,我们大多选择LengthFieldBasedFrameDecoder这种基于消息长度的解码器,有比较强的通用性。





猜你喜欢

转载自blog.csdn.net/chengzhang1989/article/details/80425282