TCP协议中的粘包和半包问题
前言
TCP(Transmission Control Protocol)是一种面向连接的可靠传输协议,广泛应用于网络通信领域。在TCP协议中,数据被分割成一个一个的报文段进行传输。然而,由于网络传输的不可靠性,TCP协议会面临一些数据传输问题,如粘包和半包问题。在网络通信中,当发送方连续发送多个小数据包时,接收方可能会将它们合并成一个大的数据包,这就是粘包问题;而当发送方发送的数据包长度大于接收方的缓冲区长度时,接收方无法完整接收数据包,导致数据的接收不完整,这就是半包问题。本文将深入探讨TCP协议中的粘包和半包问题,分析他们出现的根本原因,并提供一些解决方案,以便更好地应对这些问题。
一、粘包半包问题以及产生的原因分析
粘包就是多个数据混淆在一起了,而且多个数据包之间没有明确的分隔,导致无法对这些数据包进行正确的读取。
半包就是一个大的数据包被拆分成了多个数据包发送,读取的时候没有把多个包合成一个原本的大包,导致读取的数据不完整。
这种问题产生的原因可能有多种因素,从应用层到链路层中都有可能引起这个问题。
我们先要搞懂几个概念:
- TCP协议中的滑动窗口机制
- TCP协议中的Nagle算法
- 传输层中的MSS限制和链路层的MTU机制
- 应用层的发送方缓冲区和接收方缓冲区
下面我们先逐个介绍这些概念,然后再分析这些机制在什么情况下会引起粘包或半包问题。
1.TCP协议中的滑动窗口
TCP协议是一种可靠性传输协议,所以在传输数据的时候必须要等到对方的应答之后才能发送下一条数据,这种显然效率不高。
TCP协议为了解决这个传输效率的问题,引入了滑动窗口。滑动窗口就是在发送方和接收方都有一个缓冲区,这个缓冲区就是"窗口",假设发送方的窗口大小是 0~100KB,那么发送数据的时候前100KB的数据不需要等到对方ACK应答即可全部发送。
如果发送的过程中收到了对方返回某个数据包的ACK,那么这个窗口会对应的向后滑动。比如刚开始的窗口大小是
0~100KB,收到前20KB数据包的ACK之后,这个窗口就会滑动到20~120KB的位置,以此类推。这里还有一个小问题,如果发送方一直未接收到前20KB的ACK消息,那么在发送完0~100KB的数据之后,窗口就会卡在那里,这就是经典的队头阻塞问题,后续会讲解,本文重点不是这个,先有个印象。
接收方那里也有这么一个窗口,只会读取窗口内的数据并返回ACK,返回ACK后,接收窗口往后滑动。
对于TCP的滑动窗口,发送方的窗口起到了优化传输效率的作用,接收方的窗口起到了流量控制的作用。
2.传输层的MSS与链路层的MTU
MSS是传输层的最大报文长度限制,而MTU则是链路层的最大数据包大小限制,一般MTU会限制MSS,比如MTU=1500,那么MSS每次传输的数据包大小只能是MTU-40=1460(TCP报文头大小为40)。
有这个限制的原因是为了避免出现网络堵塞。因为网卡会有带宽限制,如果一次发送一个1GB大小的数据包,如果没有限制直接发送,就会导致网络堵塞,并且超出网络硬件设备单次传输数据的最大限制。
每次传输的数据包大小超过MSS大小时,就会自动切割这个数据包,将大的数据包拆分成多个小包。
3.TCP协议中的Nagle算法
有这么一种情况,每次发送的数据包都非常小,比如只有1个字节,但是TCP的报文头默认有40个字节,数据+报文头一共是41字节。如果这种较小的数据包经常出现,会造成过多的网络资源浪费。比如有1W个这样的数据包,那么总数据量中有400MB都是报文头,只有10MB是真正的数据。
所以TCP中引入了一种叫做Nagle的算法,如若连续几次发送的数据都很小,TCP会根据这个算法把多个数据合并成一个包发出,从而优化传输效率,避免网络资源浪费。
4.应用层的接收缓冲区和发送缓冲区
对于操作系统的IO函数而言,网络数据不管是发送或者接收,都不会去逐个读取,而是会先把接收/发送的数据放入到一个缓冲区中,然后批量进行操作。当然,发送和接收各自会对应有一个缓冲区。
假设现在要发送我叫王大锤,我在总结粘包和半包问题这组数据,操作系统的IO函数会挨个将他们写入到发送缓冲区。接收方也是这样,会将他们挨个从接收缓冲区中读取出来。
5.产生原因分析
搞清楚上面几个概念之后,我们再来分析一下为什么会产生粘包或者半包的问题
粘包:发送ABCD、EFGHIJK两个数据包,被接收成ABCDEFGHIJK一个数据包,多个包粘在一起。
- 应用层:接收方的接收缓冲区太大,导致读取多个数据包一起输出。
- TCP滑动窗口:接收方窗口较大,导致发送方发出的多个数据包处理不及时造成粘包
- Nagle算法:由于发送方的单个数据包体积太小,导致多个包合并成一个包发送
半包:发送ABCDEFG一个数据包,被接收成ABC、DEFG两个
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
