TCP粘包拆包的原因及解决办法

2023-09-19 17:28:34

TCP粘包拆包的原因及解决办法


如果你曾经亲自动手在实际项目中编写过TCP服务器或客户端,特别是涉及到高性能服务器的开发,那么你一定会对TCP的粘包和拆包问题有深刻的理解。这个问题在网络编程中是无法避免的,它源于TCP协议本身的特性和网络环境的复杂性。处理好这个问题,对于保证网络通信的准确性和效率至关重要。因此,对于任何一个网络编程人员来说,理解并解决TCP粘包和拆包问题都是必备的技能。

TCP粘包拆包的原因

TCP粘包和拆包的产生原因主要有以下几点:

  • TCP是基于字节流的:TCP协议数据传输是基于字节流的,它不包含消息、数据包等概念,需要应用层协议自己设计消息的边界,即消息帧(Message Framing)。如果应用层协议没有使用基于长度或者基于终结符息边界等方式进行处理,则会导致多个消息的粘包和拆包。

  • 发送数据大于TCP发送缓冲区剩余空间大小:要发送的数据大于TCP发送缓冲区剩余空间大小,将会发生拆包。

  • MSS/MTU限制:MTU (Maxitum Transmission Unit,最大传输单元)是 链路层 对一次可以发送的最 大数据 的限制。 MSS(Maxitum Segment Size,最大分段大小)是TCP报文中data部分的最大长度,是 传输层 对一次可以发送的最大数据的限制,TCP在传输前将进行拆包。

  • 要发送的数据小于TCP发送缓冲区的大小:要发送的数据小于TCP发送缓冲区的大小,TCP将多次写入缓冲区的数据一次发送出去,将会发生粘包。

  • Nagle算法:如果发送的网络数据包太小,那么他本身会启用Nagle算法对较小的数据包进行合并(基于此,TCP的网络延迟要UDP的高些,因为需要合并延时发送)然后再发送(超时或者包大小足够)。这样的话,服务端在接收到消息(数据流)的时候就无法区分哪些数据包是
    客户端自己分开发送的,这样产生了粘包。

  • socket缓冲区与滑动窗口:每个TCP socket在内核中都有一个发送缓冲区 (SO_SNDBUF )和一个接收缓冲区 (SO_RCVBUF),TCP的全双工的工作模式以及TCP的滑动窗口便是依赖于这两个独立的buffer的填充状态。如果接收数据端的应用层没有及时读取接收缓冲区中的数据,将发生粘包。

如何解决

解决TCP粘包和拆包问题的常见方法有以下几种

  • 固定长度:发送端将每个包都封装成固定的长度,比如100字节大小。如果不足100字节可通过补0或空等进行填充到指定长度。

  • 定界符/分隔符:发送端在每个包的末尾使用固定的分隔符,例如\r\n。如果发生拆包需等待多个包发送过来之后再找到其中的\r\n进行合并。

  • 长度字段:将消息分为头部和消息体,头部中保存整个消息的长度,只有读取到足够长度的消息之后才算是读到了一个完整的消息。

  • 自定义协议:通过自定义协议进行粘包和拆包的处理。

这些方法都需要在应用层进行设计和实现,以便在TCP字节流中正确地识别出消息边界。

一般场景下,定界符和长度字段是比较通用的解决方法。

更多推荐

InsCode Stable Diffusion 美图活动一期——即刻体验!来自 CSDN 的 SD 模型

文章目录🔥关于活动📋前言🎯什么是StableDiffusion🧩StableDiffusion与其他AI艺术生成器有什么区别?🎯开始体验InsCodeStableDiffusion🎯试用SD模型生成优质人物好图🧩第一款(测试)🧩第二款🧩第三款🧩第四款(优化第一款)🎯StableDiffusion常

Redis 事务 - 监控测试

Redis基本事务操作Redis事务本质:一组命令的集合!一个事务中的所有命令都会被序列化,在事务执行过程的中,会按照顺序执行!Redis事务是一组Redis命令的有序集合,这些命令在事务中按照顺序执行,但在事务执行过程中不会立即执行,而是将它们放入一个队列中,等待显式提交(EXEC命令)后才会执行。例如:(按顺序执行

Altera&Xilinx公司FPGA简介

Intel/Altera公司Intel/Altera系列FPGA简介-知乎(zhihu.com)AlteraFPGA提供了多种可配置嵌入式SRAM、高速收发器、高速I/O、逻辑模块以及布线。其内置知识产权(IP)结合优秀的软件工具,缩短了FPGA开发时间,降低了功耗和成本。AlteraFPGA非常适合从大批量应用到目前

Windows驱动开发(一)第一个驱动程序

首先我们需要了解,在操作系统中,是分两种权限的,一种是内核态,我们也称为0环,一种是用户态,称之为3环。而在我们的电脑中,驱动程序是运行在内核态的,这意味着和操作系统内核是在同一权限的,而普通的应用程序的权限是最低的。高权限谁不想拥有呢,因此驱动程序是很有必要了解与学习的。比如我们熟知的防病毒软件,游戏保护等,现在都在

线性代数的本质(九)——二次型与合同

文章目录二次型与合同二次型与标准型二次型的分类度量矩阵与合同二次型与合同二次型与标准型Grant:二次型研究的是二次曲面在不同基下的坐标变换由解析几何的知识,我们了解到二次函数的一次项和常数项只是对函数图像进行平移,并不会改变图形的形状和大小。以一元二次函数为例而二次函数的二次项控制函数图像的大小和形状。以二元二次函数

性能测试之使用Jemeter对HTTP接口压测

我们不应该仅仅局限于某一种工具,性能测试能使用的工具非常多,选择适合的就是最好的。笔者已经使用Loadrunner进行多年的项目性能测试实战经验,也算略有小成,任何性能测试(如压力测试、负载测试、疲劳强度测试等)都可以使用该工具。但我并不鼓励这样做,我们应该根据当前所处的情况,基于被测对象、时间及成本考虑,采用最合适的

卓越领先!安全狗入选2023年福建省互联网综合实力50强

近日,福建省互联网协会在2023年东南科技论坛——智能算力助力数字经济产业融合发展论坛上正式发布2023年福建省互联网综合实力前50家企业最终评定结果。作为国内云原生安全领导厂商,安全狗凭借突出的竞争力和市场表现入选综合实力50强。厦门服云信息科技有限公司(品牌名:安全狗)成立于2013年,致力于提供云安全、(云)数据

第一章:最新版零基础学习 PYTHON 教程(第六节 - Python 中的命名空间和作用域)

什么是命名空间:命名空间是一个为Python中的每个对象都有唯一名称的系统。对象可能是变量或方法。Python本身以Python字典的形式维护一个命名空间。让我们看一个例子,计算机中的目录文件系统结构。不用说,可以有多个目录,每个目录中都有一个同名的文件。但是,只要指定文件的绝对路径,就可以根据需要定向到该文件。实时的

利用免费的敏捷研发管理工具管理端到端敏捷研发流程

Leangoo领歌是Scrum中文网(scrum.cn)旗下的一款永久免费的敏捷研发管理工具。Leangoo领歌覆盖了敏捷研发全流程,它提供端到端敏捷研发管理解决方案,包括小型团队敏捷开发,规模化敏捷SAFe,ScrumofScrums大规模敏捷,涵盖敏捷需求管理、任务协同、进展跟踪、缺陷管理、统计度量等。提供了不同视

【Rust 基础篇】Rust 声明宏:代码生成的魔法

导言Rust是一门以安全性和性能著称的系统级编程语言,它提供了强大的宏系统,使得开发者可以在编译期间生成代码,实现元编程(Metaprogramming)。宏是Rust中的一种特殊函数,它可以接受代码片段作为输入,并根据需要生成代码片段作为输出。本篇博客将深入探讨Rust中的声明宏,包括声明宏的定义、声明宏的特点、声明

【Rust 基础篇】Rust高级函数:函数作为参数与返回值

导言Rust是一门以安全性、并发性和性能著称的系统级编程语言。在Rust中,函数是一等公民,这意味着函数可以像其他数据类型一样被传递、作为参数传递给其他函数,也可以作为返回值返回。这使得Rust具有强大的高级函数(Higher-OrderFunctions)特性,可以写出更加简洁、灵活和功能强大的代码。本篇博客将深入探

热文推荐