TCP中的粘包、拆包问题产生原因及解决方法

目录

一、拆包/粘包 问题产生原因

二、解决 粘包/拆包 问题

三、为什么TCP有粘包?

四、为什么UDP没有粘包?

五、粘包拆包问题,可能会发生在网络的哪些层上?


一、拆包/粘包 问题产生原因

发生TCP拆包或粘包有很多原因,现列出常见的几点:

  • 拆包
    • 待发送的数据大于TCP发送缓冲区剩余空间大小,将会发生拆包。
    • 待发送数据大于MSS(TCP报文长度 - TCP头部长度 > MSS最大报文长度),TCP在传输前将根据MSS大小进行拆包分段发送。
  • 粘包
    • 待发送的数据小于TCP发送缓冲区的大小,TCP将多次写入缓冲区的数据包合并为一次发送,将发生粘包(Nagle算法优化,避免tcp报文头重脚轻的情况发生,以及减少多次网络传输的往返时延)
    • 接收端的应用层没有及时读取接收缓冲区中的数据,将发生粘包。

补充:

MTU 最大传输单元 (链路层):

数据链路层传输的帧大小是有限制的,不能把一个太大的包直接塞给链路层,这个限制被称为「最大传输单元(Maximum Transmission Unit, MTU)」

以太网的帧最大的帧是 1518 字节,除去 14 字节头部和 4 字节 CRC,有效荷载最大为 1500,这个值就是以太网的 MTU。
 

MSS TCP最大段大小 Maximum Segment Size(传输层,可传输tcp数据包大小):

TCP 为了避免IP层分片,会主动把数据分割成小段再交给网络层,最大的分段大小称之为 MSS(Max Segment Size)。

这样一个 MSS 的数据恰好能装进一个 MTU 而不用分片。

一般,在以太网中 TCP 的 MSS = 1500(MTU) - 20(IP 头大小) - 20(TCP 头大小)= 1460

 总结:IP 数据包长度超过链路的 MTU 时,在发送之前需要分片,而 TCP 层为了 IP 层不用分片主动将包切割成 MSS 大小。

二、解决 粘包/拆包 问题

解决问题关键在于如何给每个数据包添加边界信息用于区分不同数据包

  1. 消息分为tcp首部和tcp消息体,TCP的首部字段中,原本是没有表示数据长度的字段,但是可以由IP首部中的 总长度 字段间接计算出来:TCP数据包长度 = IP首部的数据包总长度 - IP首部长度(20字节 )- TCP包首部长度(20字节 )。这样接收端在接收到数据后,通过读取包IP首部的总长度字段,就知道每个数据包的实际长度了。
  2. 发送端在每个包的末尾使用固定的分隔符(如 \r\n),这样接收端通过这个边界就可以将不同的数据包拆分开(如 FTP协议)。
  3. 发送端将每个数据包封装为固定长度(不够的可以通过补0填充),这样接收端每次从接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来。不推荐这种方式,尤其是在高并发大流量的业务场景下,会消耗不必要的资源...

补充:

TCP报文格式图

UDP报文格式图:

IP报文格式图:

三、为什么TCP有粘包?

TCP协议粘包拆包问题是因为TCP协议数据传输是基于 "字节流" 的,它不包含消息、数据包等概念,需要应用层协议自己设计消息边界。日常网络应用开发大都在传输层进行,因此粘包拆包问题大都只发生在TCP协议中。

四、为什么UDP没有粘包?

  1. UDP有消息保护边界,不会发生粘包拆包问题
  2. UDP发送的时候,不经过Nagle算法优化,不会将多个小包合并一次发送出去。
  3. UDP协议的接收端,采用了链式结构来记录每一个到达的UDP包。UDP是基于报文发送的,从UDP的帧结构可以看出,在UDP首部采用了 16位UDP长度 字段来指示UDP数据报文的长度,因此在应用层能很好的将不同的数据报文区分开,从而避免粘包和拆包的问题。

补充:"消息保护边界",就是指传输协议把数据当作一条独立的消息在网络上传输,接收端只能接收独立消息。也就是说存在保护消息边界,接收端一次只能接收发送端发出的一个数据包。而面向字节流是指无消息保护边界的,如果发送端连续发送数据,接收端有可能在一次接收动作中,会接收两个或者更多的数据包。

五、粘包拆包问题,可能会发生在网络的哪些层上?

粘包拆包问题在数据 “链路层、网络层、传输层” 都可能发生。

  • 2
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值