首先需要明确的一点是:
TCP是面向字节流的协议,就是没有界限的一串数据,本没有“包”的概念,“粘包”和“拆包”一说是为了有助于形象地理解这两种现象。
什么是TCP粘包?
TCP粘包指的是在数据传输过程中,发送方发送的若干个逻辑上独立的数据包在接收方接收时可能被合并为一个数据包,或者当连续发送的数据包到达接收端时,TCP栈可能会将它们合并为单个缓冲区中的数据,从而导致接收方难以区分原始的独立数据包。
1:TCP协议的流式特性
TCP本身对于发送的数据包就是当做一串无结构的字节流。
2:Nagle算法
该算法会等待收集一定量的小数据包,合并成一个大的数据包再发送,以减少网络中的小包数量,这可能导致原数据包边界消失。
3:接收缓冲区处理
接收方可能由于处理速度不及接收速度,导致多个数据包累积在缓冲区中,当从缓冲区读取数据时,可能会一次性读到多个数据包的内容。
什么是TCP拆包?
与粘包相对,TCP拆包是指一个完整的逻辑数据包在传输过程中被TCP协议拆分成多个数据包发送给接收方。
TCP为什么要拆包?
TCP拆包的原因主要包括以下几点:
1. MTU(最大传输单元)限制:
每个网络链路都有其最大传输单元(MTU)的限制,这决定了可通过该链路传输的单个数据包的最大尺寸。当TCP需要通过具有较小MTU的网络传输数据时,如果数据包的大小超过了该MTU,TCP就必须将数据拆分成多个符合MTU要求的较小包。
2. MSS(最大段大小)协商:
在TCP三次握手建立连接的过程中,双方会协商MSS值,这是不包括TCP头部在内的数据部分的最大长度。如果应用程序发送的数据超过双方协商的MSS,TCP层会自动将其拆分成多个TCP段。
3. 提高网络效率:
在网络传输中,较小的数据包可能更有利于网络的高效利用,尤其是在存在拥塞控制的情况下。TCP可能会选择拆分较大的数据以减少单个数据包的重传概率,或者为了更好地利用并行路径。
4. 流量控制:
TCP通过滑动窗口机制进行流量控制,以防止发送方过快地发送数据导致接收方无法处理。当接收方的缓冲区即将满时,它会减少通告窗口大小,发送方则需要减慢发送速率或拆分数据包以适应窗口大小。
5. 拥塞控制:
为了应对网络拥塞,TCP实施拥塞控制策略,如慢启动、拥塞避免和快速重传等。在检测到网络拥塞时,TCP可能会减少单个数据段的大小,以减少网络中的数据负载,这也可能导致数据被拆包。
用一张图说明粘包拆包
解决方案
为了解决TCP粘包和拆包问题,通常需要在应用层设计相应的协议来定义数据包的边界,这里就又涉及到 自定义消息协议的设计 这个知识点了,这里不展开讲,单说下常见的做法包括:
定长消息:
每个消息的大小固定,接收方按照预定长度读取消息。
消息头:
在每个消息前添加包含消息长度的信息,接收方先读取消息头获取长度,再根据长度读取消息体。
分隔符:
在消息之间使用特定的分隔符,接收方通过识别分隔符来拆分消息。
更高级的协议封装:
使用已经内置了数据包边界处理的高层协议,如HTTP、WebSocket等。
原创文章,作者:速盾高防cdn,如若转载,请注明出处:https://www.sudun.com/ask/78437.html