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

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

 目录

粘包/拆包 问题产生原因:

解决 粘包/拆包 问题:

为什么TCP有粘包?

为什么UDP没有粘包?

发生在网络的哪些层上?


粘包/拆包 问题产生原因:

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

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

    补充:

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

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

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

     

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

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

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

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

    image.gif编辑

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

    解决 粘包/拆包 问题:

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

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

      补充:TCP报文格式图

      image.gif编辑

      为什么TCP有粘包?

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

      为什么UDP没有粘包?

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

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

        发生在网络的哪些层上?

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

        目录
        相关文章
        |
        5月前
        |
        缓存 网络协议 算法
        c++理论篇(一) ——浅谈tcp缓存与tcp的分包与粘包
        c++理论篇(一) ——浅谈tcp缓存与tcp的分包与粘包
        145 0
        c++理论篇(一) ——浅谈tcp缓存与tcp的分包与粘包
        |
        6月前
        |
        网络协议
        解决TCP粘包问题
        解决TCP粘包问题
        |
        6月前
        |
        XML 缓存 网络协议
        面试题:TCP的粘包和拆包
        面试题:TCP的粘包和拆包
        54 1
        |
        缓存 网络协议 算法
        TCP粘包、拆包原因与解决方案
        TCP粘包、拆包原因与解决方案
        202 0
        |
        存储 消息中间件 缓存
        计网 - TCP 的封包格式:TCP 为什么要粘包和拆包?
        计网 - TCP 的封包格式:TCP 为什么要粘包和拆包?
        123 0
        |
        网络协议 算法
        第 9 章 TCP 粘包和拆包及解决方案
        第 9 章 TCP 粘包和拆包及解决方案
        217 0
        |
        存储 网络协议
        TCP拆包和粘包的作用是什么
        首先我们思考一个问题,应用层的传输一个10M的文件是一次性传输完成,而对于传输层的协议来说,为什么不是一次性传输完成呢。 这个有很多原因,比如稳定性,一次发送的数据越多,出错的概率越大。再比如说为了效率,网络中有时候存在并行的路径,拆分数据包就就能更好的利用这些并行的路径。再有,比如发送和接收数据的时候,都存在缓冲区,缓冲区是在内存中开辟的一块空间,目的是缓冲大量的应用频繁的通过网卡收发数据,这个时候,网卡只能一个一个处理应用的请求。当网卡忙不过来的时候,数据就需要排队了。也就是将数据放入缓冲区。如果每个应用都随意发送很大的数据,可能导致其他应用的实时性遭到破坏。
        71 0
        |
        存储 缓存 网络协议
        Linux网络编程TCP粘包问题解析及解决方法
        Linux网络编程TCP粘包问题解析及解决方法
        141 0
        |
        移动开发 网络协议 Java
        TCP 粘包/拆包问题
        《基础系列》
        158 0
        TCP 粘包/拆包问题
        |
        移动开发 网络协议
        TCP的粘包拆包问题+解决方案
        TCP的粘包拆包问题+解决方案
        157 0
        TCP的粘包拆包问题+解决方案