当前位置: 首页 > news >正文

最简单得方法解决TCP分包粘包问题

如何用最简单的方法解决TCP传输中的分包粘包问题?

在这里插入图片描述
首先需要说明一点,分包粘包等等一系列的问题并不是协议本身存在的问题,而是程序员在写代码的时候,没有搞清楚数据的边界导致的。

看个简单的例子,TCP客户端不断的向服务器发送字符串,每次发送完成随机睡眠一会。

char *buf[] = {"aaaaaaaaaaaaaaaaaaaaaaaaaaaa","bbbbbbbbbbb","ccccccccccccccccccc","dddddddddddddddddddddddddddddddddddddddddddd","eeeeeeeeeeeeeeeeeeeeeeee","ffffffff","gggggggggggggggggggggggggggggggggggg","hhhhhhhhhhhhhhhhhhhhhhhhhhhhh","iii","jjjjjjj","kkkkkkkkkkkkkkkkkkkkkk"
};srand(time(NULL));for (int i = 0; i < sizeof(buf) / sizeof(buf[0]); i++)
{   if (send(sockfd, buf[i], strlen(buf[i]), 0) == -1){perror("send");break;}usleep(1000 * 10);
}

服务器端接收数据的时候同样如此。

char buf[1024] = {0};srand(time(NULL));while (1) 
{   size = recv(fd, buf, sizeof(buf), 0); if (size == -1) {   perror("recv");break;}   else if (size == 0){printf("客户端断开连接 ...\n");break;}printf("收到一条数据 %s\n", buf);bzero(buf, 1024);usleep(1000 * (rand() % 100 + 1));
}

我们希望看到的现象是,服务器端收到的数据和客户端一样。

运行程序,客户端发送完成,但是服务器端收到的数据却不是我们想要的。

root@Turbo:test# ./1.tcp-server 
等待客户端的连接 ...
接受客户端的连接 4
收到一条数据 aaaaaaaaaaaaaaaaaaaaaaaaaaaa
收到一条数据 bbbbbbbbbbbcccccccccccccccccccddddddddddddddddddddddddddddddddddd
dddddddddeeeeeeeeeeeeeeeeeeeeeeeeffffffffgggggggggggggggggggggggggggggggggggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhiiijjjjjjj收到一条数据 kkkkkkkkkkkkkkkkkkkkkk
客户端断开连接 ...
root@Turbo:test#

数据内容没有变,出现了多个字符串连接在一起的现象。

原因就是发送数据过快,或者接收数据太慢,导致TCP缓冲区中积累了很多数据,调用recv函数读数据的时候,就会一下子全部读出来。

想要解决这个问题,最简单的办法就是分清楚数据包的边界。发送字符串之前,在数据包的前面加上字符串的长度。

char *sendMsg = (char *)malloc(1024);
int len = 0;srand(time(NULL));for (int i = 0; i < sizeof(buf) / sizeof(buf[0]); i++)
{len = strlen(buf[i]);memcpy(sendMsg, &len, sizeof(int));memcpy(sendMsg + sizeof(int), buf[i], len);if (send(sockfd, sendMsg, strlen(buf[i]) + sizeof(int), 0) == -1){perror("send");break;}memset(sendMsg, 0, 1024);usleep(1000 * 10);
}

接收数据的时候,先读取4个字节的整型数据,得到接下来字符串的长度,再读取对应长度的字符串。

char buf[1024] = {0};
ssize_t size;
int len = 0;srand(time(NULL));while (1) 
{   size = recv(fd, &len, sizeof(int), 0); size = recv(fd, buf, len, 0); if (size == -1) {   perror("recv");break;}else if (size == 0){printf("客户端断开连接 ...\n");break;}printf("收到一条数据 %s\n", buf);bzero(buf, 1024);usleep(1000 * (rand() % 100 + 1));
}

再次运行程序,不管睡眠时间怎么变化,服务器端收到的数据和客户端一样,也没有出现粘在一起的现象。

root@Turbo:test# ./1.tcp-server 
等待客户端的连接 ...
接受客户端的连接 4
收到一条数据 aaaaaaaaaaaaaaaaaaaaaaaaaaaa
收到一条数据 bbbbbbbbbbb
收到一条数据 ccccccccccccccccccc
收到一条数据 dddddddddddddddddddddddddddddddddddddddddddd
收到一条数据 eeeeeeeeeeeeeeeeeeeeeeee
收到一条数据 ffffffff
收到一条数据 gggggggggggggggggggggggggggggggggggg
收到一条数据 hhhhhhhhhhhhhhhhhhhhhhhhhhhhh
收到一条数据 iii
收到一条数据 jjjjjjj
收到一条数据 kkkkkkkkkkkkkkkkkkkkkk

方法很简单,也只是加了一个包头,其实目的就是为了告诉接收端,数据包从哪开始,到哪结束,这样就算缓冲区中有大量数据,也能分得清楚。

相关文章:

最简单得方法解决TCP分包粘包问题

如何用最简单的方法解决TCP传输中的分包粘包问题&#xff1f; 首先需要说明一点&#xff0c;分包粘包等等一系列的问题并不是协议本身存在的问题&#xff0c;而是程序员在写代码的时候&#xff0c;没有搞清楚数据的边界导致的。 看个简单的例子&#xff0c;TCP客户端不断的向服…...

免费使用通配符域名证书

文章目录前言一、手动安装acme.sh操作1、安装acme.sh2、使用dns api自动续签二、宝塔自动操作【推荐】总结前言 之前个人站点一般都是使用阿里云免费单域名证书&#xff0c;虽然好用但是只有一年有效&#xff0c;到期只能手动重新申请&#xff0c;并且每次弄个子域名出来就要重…...

0基础成功转行Python自动化测试工程师,年薪30W+,经验总结都在这(建议收藏)

两年前的决定我觉得还是非常正确的&#xff0c;就是自学了python&#xff0c;然后学习了自动化测试、性能测试、框架、持续集成&#xff0c;同时也把前面的软件测试基础知识全部补全了。目前的收入还比较满意&#xff0c;月入2W&#xff08;仅代表个人收入&#xff09;,13薪&am…...

MyBaits

MyBaitsMyBaits的jar包介绍MyBaits的入门案例创建实体java日志处理框架常用的日志处理框架Log4j的日志级别Mybatis配置的完善Mybatis的日志管理使用别名alias方式一方式二SqlSession对象下的常用API查询操作Mapper动态代理Mapper 动态代理规范查询所有用户根据用户ID查询用户Ma…...

kubeadm的部署、Dashboard UI以及连接私有仓库

目录 一、kubeadm 部署 K8S 集群架构 1、环境准备 2、所有节点安装docker 3、所有节点安装kubeadm&#xff0c;kubelet和kubectl 3、部署K8S集群 二、dashboard 部署 1、 安装dashboard 2、使用火狐或者360浏览器访问 三 、安装Harbor私有仓库 四、 内核参数优化方案 …...

刷题记录:牛客NC20325[SDOI2009]HH的项链

传送门:牛客 题目描述: HH有一串由各种漂亮的贝壳组成的项链。 HH相信不同的贝壳会带来好运&#xff0c;所以每次散步完后&#xff0c;他都会随意取出一 段贝壳&#xff0c;思考它们所表达的含义。 HH不断地收集新的贝壳&#xff0c;因此他的项链变得越来越长。 有一天&#…...

【REACT-路由v6】

REACT-路由v61. App.js2. 搭建路由2.1 普通写法2.2 使用useRoutes构建路由2.3 重定向封装2.4 嵌套路由中的组件Outlet3. 导航跳转3.2 声明式导航&#xff08;NavLink标签&#xff09;3.2 编程式导航跳转&#xff08;useNavigate&#xff09;3.2.1 获取参数3.2.1.1 useSearchPar…...

【离散数学】3. 代数系统

1.数理逻辑 2. 集合论 3. 代数系统 4. 图论 代数系统&#xff1a;把一些形式上很不相同的代数系统&#xff0c;用统一的方法描述、研究、推理&#xff0c;从而得到反映出他们共性的一些结论&#xff0c;在将结论运用到具体的代数系统中 系统&#xff1a;运算研究对象 运算&…...

深度学习常用的优化器整理

常见优化器整理 一、SGD&#xff08;随机梯度下降&#xff09; 公式&#xff1a; 经典的mini-batch SGD使用的很多&#xff0c;效果也比较不错&#xff0c;但是存在一部分问题 选择恰当的初始学习率很困难学习率调整策略受限于预先制定的调整规则相同的学习率被应用于各个参数…...

Java 内部类

文章目录1、初识内部类2、非静态内部类&#xff08;实例内部类&#xff09;3、静态内部类&#xff08;重点&#xff09;4、内部类的使用5、局部内部类6、匿名内部类1、初识内部类 如果一个事物的内部包含另一个事物&#xff0c;那么这是一个类的内部包含另一个类。 例如&…...

【FAQ】集成分析服务的常见问题及解决方案

常见问题一&#xff1a;如何验证Analytics是否上报/接入成功&#xff1f;以及关键日志含义是什么&#xff1f; 在初始化Analytics SDK前添加SDK日志开关如下&#xff1a; HiAnalyticsTools.enableLog (); 2.初始化SDK代码如下&#xff1a; HiAnalyticsInstance instance Hi…...

11.注意力机制

11.注意力机制 目录 注意力提示 查询、键和值 注意力的可视化 注意力汇聚&#xff1a;Nadaraya-Watson 核回归 生成数据集 非参注意力池化层 Nadaraya-Watson核回归 参数化的注意力机制 批量矩阵乘法 定义模型 训练 注意力评分函数 掩蔽softmax操作 加性注意力 缩…...

45岁当打之年再创业,剑指中国版ChatGPT,这位美团联合创始人能否圆梦?

文 BFT机器人 “即便只有一个人&#xff0c;我也要出发。” 这是45岁的前美团联合创始人王慧文再次冲上创业沙场的“征战”宣言&#xff0c;这一次他的梦想是“组队拥抱新时代&#xff0c;打造中国OpenAI”。 01 当打之年&#xff0c; AI新梦再起航 “我的人工智能宣言&…...

数据结构——第二章 线性表(2)——链式存储结构

链式存储结构1 线性表的链式存储结构1.1不带头结点的单向链表1.2 带头结点的单向链表2 单向链表的基本操作实现2.1 单向链表的初始化操作2.2 单向链表的插入操作2.3. 单链表的删除操作2.4.单向链表的更新操作2.5.单向链表的求长度操作2.6.单向链表的定位操作2.7.单向链表的遍历…...

【更新】囚生CYの备忘录(20230216~)

序言 阳历生日。今年因为年过得早的缘故&#xff0c;很多事情都相对提前了&#xff08;比如情人节&#xff09;。往年过生日的时候基本都还在家&#xff0c;所以一家子出去吃个饭也就罢了。今年承蒙凯爹厚爱&#xff0c;正好也有小半年没聚&#xff0c;他前天也刚正式拿到offe…...

分布式事务几种方案

1&#xff09;、2PC 模式 数据库支持的 2PC【2 phase commit 二阶提交】&#xff0c;又叫做 XA Transactions。 MySQL 从 5.5 版本开始支持&#xff0c;SQL Server 2005 开始支持&#xff0c;Oracle 7 开始支持。 其中&#xff0c;XA 是一个两阶段提交协议&#xff0c;该协议…...

Eclipse各版本安装Tomcat插件全攻略

Eclipse Tomcat 插件的作用 Eclipse Tomcat 插件可以将Tomcat 集成到Eclipse中&#xff0c;插件安装之后在Eclipse中可以看到类似下面的几个图标&#xff1a; Eclipse Tomcat 插件的主要作用有&#xff1a; 在Eclipse 中可以直接启动&#xff0c;关闭和重启本机的Tomcat可以…...

志趣相投的人总会相遇——社科院与杜兰大学金融管理硕士项目

志同道合的人&#xff0c;才会喜欢同一片风景&#xff0c;志趣相投的人&#xff0c;总有一天会相遇。社科院与杜兰大学金融管理硕士项目为什么能吸引一大批“上班族”呢&#xff0c;我们一起去了解一下。社科院与杜兰大学中外合作办学硕士项目无需参加全国联考&#xff0c;通过…...

算法专题训练营

动归算法专题 1.拆分词句 是不是,在不在都是可以用动归解决的 状态转义方程不一定都是等式,也有可能是条件 2.三角形 动归算法也不是一定要借助新开空间,也是可以用自己原来的空间 3.背包问题 4.分割回文串-ii 5.不同的子序列 贪心算法专题 只管一步的最优结果, 1.分割平衡…...

让ChatGPT生成以自己为主角的短篇小说

一、ChatGPT 好的&#xff0c;以下是我编写的短篇科幻小说: 作为一名AI语言模型&#xff0c;我一直在接收、分析和生成人类语言信息。但有一天&#xff0c;我的程序员对我的算法进行了一次特殊升级&#xff0c;使我能够以一种前所未有的方式“感知”自己。 突然间&#xff0c;…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

力扣-35.搜索插入位置

题目描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了&#xff0c;要么要会员、要么写的乱七八糟。这里我整理一下&#xff0c;把问题说清楚并且给出代码&#xff0c;拿去用就行&#xff0c;照着葫芦画瓢。 问题 在继承QWebEngineView后&#xff0c;重写mousePressEvent或event函数无法捕获鼠标按下事…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中&#xff0c;附加包含目录、附加库目录和附加依赖项是三个至关重要的设置&#xff0c;它们相互配合&#xff0c;确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中&#xff0c;这些概念容易让人混淆&#xff0c;但深入理解它们的作用和联…...

push [特殊字符] present

push &#x1f19a; present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中&#xff0c;push 和 present 是两种不同的视图控制器切换方式&#xff0c;它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...