说一下 Tcp 粘包是怎么产生的?
TCP 粘包是什么?
TCP 粘包(TCP Packet Merging) 是指多个小的数据包在 TCP 传输过程中被合并在一起,接收方读取时无法正确分辨数据边界,导致数据解析错误。
TCP 是流式协议,没有数据包的概念,它只是保证数据按照字节流的顺序传输,不保证接收方能按照原始发送时的数据边界来接收数据。因此,TCP 可能会把多个数据包合并(粘包)或者拆分(拆包)。
1. TCP 粘包的两种情况
(1)发送端导致的粘包
当发送方的数据量较小,TCP 不会立即发送,而是等缓冲区满了再一起发送,这样可以减少网络开销。导致多个小数据包合并成一个大的数据包,产生粘包。
示例
假设我们在 TCP 连接中连续发送三条消息:
send(socket, "Hello", 5, 0);
send(socket, "World", 5, 0);
send(socket, "!!!", 3, 0);
如果 TCP 将这三次 send 的数据合并在一起,接收方可能会收到:
HelloWorld!!!
这样就无法判断消息边界,导致解析困难。
原因
- TCP 有 Nagle 算法(默认开启):
- 小数据会被合并,等待缓冲区满了才一起发送,减少小包,提高传输效率。
- 适用于高并发场景,但会导致粘包问题。
- 可以通过
setsockopt关闭:int flag = 1; setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(int));
(2)接收端导致的粘包
接收方 读取数据不及时或者一次性读取了多个数据包,导致多个包的数据合并读取,形成粘包。
示例
如果发送方连续发送:
send(socket, "Hello", 5, 0);
send(socket, "World", 5, 0);
send(socket, "!!!", 3, 0);
接收方可能这样读取:
char buffer[20];
recv(socket, buffer, 20, 0);
如果 recv() 读取到了所有数据,buffer 里存的是:
HelloWorld!!!
但接收方可能预期每条消息是独立的,所以会出现粘包问题。
原因
- TCP 是 流式传输,没有边界概念,
recv()读取数据时,可能一次读取多个包的内容。 - 如果接收方缓冲区没满,但程序没有及时读取,新的数据到来后会追加到原有数据里,造成粘包。
2. TCP 拆包(包被拆分)
除了粘包,拆包(packet fragmentation) 也是常见问题。
如果单次发送的数据超过了 TCP 最大传输单元(MTU),TCP 会自动拆分数据包。
示例
假设 send() 发送 5000 字节,而 TCP 的 MTU 设为 1500 字节,则会拆分成:
Packet 1: 1500 bytes
Packet 2: 1500 bytes
Packet 3: 1500 bytes
Packet 4: 500 bytes
这样接收方 recv() 时可能会一次只收到部分数据,需要多次 recv() 才能完整还原。
3. 如何解决 TCP 粘包/拆包问题?
由于 TCP 没有消息边界,需要在应用层手动处理数据边界:
(1)固定长度协议
如果每条消息长度固定,可以按照固定字节数读取:
recv(socket, buffer, 10, 0); // 一次读取 10 字节
但这种方法仅适用于所有消息长度一致的情况。
(2)特殊分隔符
在消息结尾添加特殊字符,接收方按照这个字符分割数据:
send(socket, "Hello|", 6, 0);
send(socket, "World|", 6, 0);
接收方:
char buffer[1024];
recv(socket, buffer, 1024, 0);
然后通过 | 来拆分数据:
char *token = strtok(buffer, "|");
while (token) {printf("Received message: %s\n", token);token = strtok(NULL, "|");
}
缺点:
- 需要保证
|不会出现在正常数据中。 - 需要解析和处理数据,稍微增加了协议复杂度。
(3)消息头 + 消息体(推荐)
在数据前面加上消息长度,接收方先读取长度,再读取完整数据:
struct Message {uint32_t length; // 4字节,表示消息长度char data[1024]; // 消息体
};
发送数据:
uint32_t len = htonl(strlen(data)); // 转换为网络字节序
send(socket, &len, 4, 0); // 先发送长度
send(socket, data, strlen(data), 0); // 再发送数据
接收方:
uint32_t len;
recv(socket, &len, 4, 0); // 先读取 4 字节长度
len = ntohl(len); // 转换回主机字节序
recv(socket, buffer, len, 0); // 再读取数据
优势:
- 适用于任何长度的消息,比定长方案更灵活。
- 不会出现边界问题,比分隔符方案更可靠。
4. 总结
粘包的原因
- 发送端合并小数据包(TCP 缓冲区满了才发,Nagle 算法)。
- 接收端一次性读取多个数据包(TCP 没有消息边界)。
如何解决
| 方案 | 适用场景 | 复杂度 |
|---|---|---|
| 固定长度消息 | 适用于消息长度固定的协议 | 低 |
特殊分隔符(如 \n、` | `) | 适用于文本协议(如 HTTP) |
| 消息头 + 消息体(推荐) | 适用于二进制协议(如 TCP 长连接) | 高 |
重点
- TCP 是流式协议,没有边界,需要应用层协议解决粘包问题!
- 消息头 + 消息体方式最通用,适用于大部分场景。🚀
这样就能高效避免 TCP 粘包问题啦!🎯
相关文章:
说一下 Tcp 粘包是怎么产生的?
TCP 粘包是什么? TCP 粘包(TCP Packet Merging) 是指多个小的数据包在 TCP 传输过程中被合并在一起,接收方读取时无法正确分辨数据边界,导致数据解析错误。 TCP 是流式协议,没有数据包的概念,…...
详解享元模式
引言 在计算机中,内存是非常宝贵的资源,而程序中可能会有大量相似或相同的对象,它们的存在浪费了许多空间。而享元模式通过共享这些对象,从而解决这种问题的。 1.概念 享元模式(Flyweight Pattern):运用共享技术有效地…...
第18章 不可变对象设计模式(Java高并发编程详解:多线程与系统设计)
1.线程安全 所谓共享的资源,是指在多个线程同时对其进行访问的情况下,各线程都会使其发生变化,而线程安全性的主要目的就在于在受控的并发访问中防止数据发生变化。除了使用synchronized关键字同步对资源的写操作之外, 还可以在线…...
openEuler22.03LTS系统升级docker至26.1.4以支持启用ip6tables功能
本文记录了openEuler22.03LTS将docker升级由18.09.0升级至26.1.4的过程(当前docker最新版本为27.5.1,生产环境为保障稳定性,选择升级到上一个大版本26的最新小版本)。 一、现有环境 1、系统版本 [rootlocalhost opt]# cat /etc…...
< OS 有关 > Ubuntu 版本升级 实践 24.04 -> 24.10, 安装 .NET
原因: 想安装 .NET 9 去编译 GitHut 项目,这回用不熟悉的 Ubuntu来做,不知道怎么拐去给 Ubuntu 升级,看到现在版本是 24.10 但不是 LTS 版本,记录下升级过程。 一、实践过程: 1. 查看当前版本 命令1: l…...
某咨询大数据解决方案介绍(32页PPT)
本文档介绍了一个大数据平台解决方案,旨在解决企业当前面临的数据问题,包括数据定义缺失、重复采集和存储、数据不完整以及缺乏可靠决策依据等。通过引入大数据技术,该方案强调从被动的IT支撑向主动的数据核心服务转型,以实现科学…...
ZooKeeper作为注册中心有什么问题? ZooKeeper作为注册中心,海量服务同时重启有什么问题?
目录 ZooKeeper作为注册中心存在的问题 性能瓶颈 一致性保证 复杂性 扩展性 单点故障 数据模型限制 社区和生态 安全性 总结 ZooKeeper作为注册中心,海量服务同时重启有的问题 1. ZooKeeper集群压力剧增 2. ZooKeeper Leader节点压力 3. 会话和临时节点管理 4.…...
matlab simulink 汽车四分之一模型主动被动悬架-LQR
1、内容简介 略 matlab simulink 可以交流、咨询、答疑 124- 2、内容说明 略汽车悬架系统由弹性元件、导向元件和减振器组成,是车身与车轴之间连接的所有组合体零件的总称,也是车架(或承载式车身)与车桥(或车轮)之间一切力传递装置的总称,其主要功能是使车轮与地面有很好的…...
从零开始:OpenCV 图像处理快速入门教程
文章大纲 第1章 OpenCV 概述 1.1 OpenCV的模块与功能 1.2 OpenCV的发展 1.3 OpenCV的应用 第2章 基本数据类型 2.1 cv::Vec类 2.2 cv::Point类 2.3 cv::Rng类 2.4 cv::Size类 2.5 cv:&…...
基础相对薄弱怎么考研
复习总体规划 明确目标 选择专业和院校:根据你的兴趣、职业规划和自身实力,选择适合自己的专业和院校。可以参考往年的分数线、报录比、复试难度等。了解考试科目:不同专业考试科目不同,一般包括: 公共课:…...
强化学习笔记6——异同策略、AC、等其他模型总结
异步两种方法:1:经验回放 2:数据动作非同时产生 举例QLearning为什么是异策略? 生成动作时e的概率从Q表选,1-e概况随机。 更新策略时,贪心策略选择Q_max作为动作。 策略优化两种主要方法:基于梯…...
Linux提权--passwd提权
passwd 命令用于更改用户密码。在 Linux 系统中,普通用户可以通过 passwd 更改自己的密码,但如果攻击者能够以某种方式执行 passwd 命令更改 root 用户的密码,他们就能获取 root 权限。 1.常见的 passwd 提权方法 SUID 设置࿱…...
一、本地部署安装 DeepSeek 并训练本地知识库,并调用对话框进行问答
本地部署安装 DeepSeek 1、硬件环境 操作系统:Windows10 内存:16G 显卡:NIVIDIA GeForce RTX 2060 6G 2、安装步骤 (1)安装 Ollama 访问Ollama 官网,点击 “Download for Windows” 下载安装程序。下载…...
海思的一站式集成环境Hispark Studio更新了
HiSpark Studio是海思提供的面向智能设备开发者提供一站式集成开发环境,支持代码编辑、编译、烧录和调试等功能。我以前在评测星闪芯片的时候用过,当时写了篇博客:【星闪开发连载】WS63E开发板Windows环境的构建_hispark studio-CSDN博客。那…...
从零开始构建强大 AI 对话系统:ollama + deepseek + open-webui 完整部署教程(Docker 版)
文章目录 前言一、工具简介二、前期准备三、部署步骤1. 安装并配置 ollama2. 部署 open-webui 四、调试与验证五、Docker Compose 简化部署六、注意事项与常见问题1. ollama run 500 报错2. 硬件配置对性能的影响3. **ollama** 启动与 **open-webui** 调用速度差异4. 内存不足导…...
unity学习29:摄像机camera相关skybox 和 Render Texture测试效果
目录 1 摄像机 1.1 每个Scene里都自带一个摄像机 camera 1.2 可以创建多个camera 1.3 下面先看backgroundtype: 2 backgroundtype: 天空盒 skybox 2.1 清除标志,清除:天空盒 自选天空盒 2.2 window /Asset Store 2.3 导入skybox 3 backgroundtype: 纯色…...
【Elasticsearch】Geo-distance聚合
geo_distance聚合的形状是圆形。它基于一个中心点(origin)和一系列距离范围来计算每个文档与中心点的距离,并将文档分配到相应的距离范围内。这种聚合方式本质上是以中心点为圆心,以指定的距离范围为半径的圆形区域来划分数据。 为…...
音频进阶学习十二——Z变换
文章目录 前言一、Z变换1.Z变换的作用2.Z变换公式3.Z的状态表示1) r 1 r1 r12) 0 < r < 1 0<r<1 0<r<13) r > 1 r>1 r>1 4.关于Z的解释 二、收敛域1.收敛域的定义2.收敛域的表示方式3.ROC的分析1)当 …...
easyxor
easyxor 一、查壳 无壳,64位 二、IDA分析 1.main 2.查看key与r(shifee提取) 三、脚本 r [0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, …...
通过多层混合MTL结构提升股票市场预测的准确性,R²最高为0.98
“Boosting the Accuracy of Stock Market Prediction via Multi-Layer Hybrid MTL Structure” 论文地址:https://arxiv.org/pdf/2501.09760 摘要 本研究引入了一种创新的多层次混合多任务学习架构,致力于提升股市预测的效能。此架构融…...
日本游戏机市场5年来首次陷入萎缩;特斯拉招人推进人形机器人量产;任天堂专利显示Switch2手柄可用作鼠标...| 游戏智眼日报
美团成立“算法顾问委员会” 美团宣布,近日,由外部专家学者组成的算法顾问委员会成立,为美团改进算法提供常态化咨询和指导。每个季度美团将举办算法恳谈会,持续邀请骑手、商家、用户、专家学者和媒体代表等共同参加。美团表示&a…...
114-机器学习分类算法
1、内容简介 略 matlab simulink 114-机器学习分类算法可以交流、咨询、答疑 2、内容说明 略 Elong_6.24。ROCAUC confusion newdata Unbalanced_LR.car 3、仿真分析 略 4、参考论文 略...
【论文阅读】On the Security of “VOSA“
On the Security of Verifiable and Oblivious Secure Aggregation for Privacy-Preserving Federated Learning -- 关于隐私保护联邦中可验证与遗忘的安全聚合的安全性 论文来源摘要Introduction回顾 VOSA 方案对VOSA不可伪造性的攻击对于类型 I 的攻击对于类型 II 的攻击 论文…...
12.6 LangChain检索器(Retrievers)全解析:构建高效RAG应用的核心引擎
LangChain检索器(Retrievers)全解析:构建高效RAG应用的核心引擎 一、检索器的核心价值 检索器是大模型应用的智能导航系统,通过将用户查询与知识库精准匹配,解决了传统搜索的三大痛点: 语义鸿沟:突破关键词匹配,理解用户真实意图多源整合:融合向量搜索、关键词搜索和…...
707设计链表(链表操作)
1、题目描述 你可以选择使用单链表或者双链表,设计并实现自己的链表。 单链表中的节点应该具备两个属性:val 和 next 。val 是当前节点的值,next 是指向下一个节点的指针/引用。 如果是双向链表,则还需要属性 prev 以指示链表中…...
储能系统-系统架构
已更新系列文章包括104、61850、modbus 、单片机等,欢迎关注 IEC61850实现方案和测试-1-CSDN博客 快速了解104协议-CSDN博客 104调试工具2_104协议调试工具-CSDN博客 1 电池储能系统(BESS) 架构 电池储能系统主要包括、电池、pcs、本地控制…...
Spring Boot 需要独立的容器运行吗
Spring Boot 不需要独立的容器运行,它内置了一个嵌入式的Web服务器(如Tomcat、Jetty或Undertow),所以可以直接作为一个独立的应用程序运行,而不需要外部的Servlet容器。你只需要运行Spring Boot应用,它会自…...
Spring Security在java中的详细用处///为什么用了jwt之后就不能用session
Spring Security 是一个功能强大且高度可定制的认证和授权框架,主要用于基于 Spring 的应用程序中。它不仅处理 HTTP 请求的安全性(包括认证和授权),还提供了其他安全相关的特性如防止 CSRF 攻击、会话管理、安全头信息设置等。以…...
Ubuntu系统 Zabbix 7.2LTS一键部署脚本
为了在 Ubuntu 系统上快速部署 Zabbix 7.2 LTS 版本,您可以使用一个自动化 Bash 脚本来简化安装过程。以下是一个适用于 Ubuntu 系统的 Zabbix 7.2 LTS 一键部署脚本。此脚本将安装 Zabbix Server、Zabbix Web 界面(基于 Nginx 和 PHP)以及 Z…...
基于HTML、CSS 和 JavaScript 开发个人读书类网站
以下是一个使用 HTML、CSS 和 JavaScript 开发个人读书类网站的示例代码,包含基本功能和样式: 我的读书空间 我的书库 首页 添加新书 <div class="container"><!-- 首页内容 --><div id="home"><h2>当前阅读列表</h2><…...
