Qt中对TCP粘包的处理

2023-10-26

当时用TCP协议传输数据时,经常出现粘包的现象
当服务器向客户端发送数据之后,客户端还没有接收数据的时候,这段时间数据在什么地方?
1、服务器?服务器已经发出数据了
2、网线?数据应该在内存,怎么会在网线里面,又没有内存
3、客户端?是的,这个时候数据已经到达客户端了,只不过被保存在客户端的缓存中了(内核缓冲区),客户端只有在read的时候才能读出数据
场景:服务器每次给客户端发出一条数据,但是每次发送数据的量是不一样的,这时要求客户端把服务器发过来的数据依次接收到本地并且进行对应的解析,如果客户端一次发出10个字节,那么客户端也一次读出10个字节,如果多读了,那么就把下一条数据读出来了,此时解析数据会是错误的,这就是TCP粘包

处理办法:发送端在每一个数据包前面加上包头,包头中加入数据长度
接收端接收到后的处理:首先包头的大小是固定的,一般就是一个long或者int类型,所以我们根据这个long或者int类型求出一个固定大小,8字节(long)或者4字节(int),所以在读数据包的时候直接根据这个类型先去读8字节或者4字节,这样就可以读出数据包的长度,然后根据这个长度去读后边的这个数据块
比如此次接收到的长度为100,那么就向后读取100个字节的数据,就是此次的一个包,哪怕此时缓冲区有1000个字节数据,只读这100个字节就能获取一个完整的包,剩余的900个字节就需要下一次去处理,下次处理的时候还是先读包头,读出数据包的一个长度,然后根据这个长度去读取相应的数据,这样一次一次读取就可以一点一点把数据拆分出来了

例:这里以Qt编写的基于opencv的人脸识别的服务器和客户端为例,客户端发送拍下的人脸发送到服务器进行识别,要求传输一帧完整的人脸数据,这就有可能粘包,可能同时发送两个人脸向服务器,此时就需要处理粘包
首先客户端发送图片数据

//把Mat数据转化为QbyteArray, --》编码成jpg格式
std::vector<uchar> buf;
cv::imencode(".jpg",srcImage,buf);   //这就是将拍摄的原始的图像转为jpg然后将数据放到buf中
QByteArray byte((const char*)buf.data(),buf.size()); //数据格式转为QByteArray 
//准备发送
quint64 backsize = byte.size();    //获取数据的长度,这里可以看到backsize是quint64型变量,占8个字节
QByteArray sendData;
QDataStream stream(&sendData,QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_5_14);
//将数据放入码流,首先放入数据的长度backsize,quint64为8字节的长度,后面就是数据
stream<<backsize<<byte;  
//发送
msocket.write(sendData);  //将数据包发送

服务器接收图片数据

static quint64 bsize = 0;  //全局变量

QDataStream stream(msocket); //把套接字绑定到数据流
stream.setVersion(QDataStream::Qt_5_14);

if(bsize == 0){
		//查看目前TCP的内存缓冲区的数据长度是否能达到bsize所占的字节数,这里应该是8字节
    if( msocket->bytesAvailable() < (qint64)sizeof(bsize) ) 
    		return ;
    //说明数据长度够8个字节,然后就可以获取采集数据的长度
    stream>>bsize;
}

//获取目前缓存中剩余数据的长度,小于刚才获取的8字节的数据长度说明数据还没有发送完成,返回继续等待
if(msocket->bytesAvailable() < bsize)
{
    return ;  //此时bsize没有清空,下次还会来这里检查获取的数据长度是否大于或等于bsize
}
QByteArray data;
stream>>data;
bsize = 0;   // 将bsize设为0,说明处理完了一包数据 
if(data.size() == 0)//没有读取到数据
{
    return;
}

//显示图片
QPixmap mmp;
mmp.loadFromData(data,"jpg");
mmp = mmp.scaled(ui->picLb->size());
ui->picLb->setPixmap(mmp);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt中对TCP粘包的处理 的相关文章

随机推荐

  • 13位10位时间戳转换日期

    工具类 时间转换 一 10位13位时间戳转String 格式 2018 10 15 16 03 27 日期 10位13位时间戳转String 格式 2018 10 15 16 03 27 日期 param timestamp param s
  • C语言:一级指针,二级指针,三级指针,指针数组,数组指针的综合示例

    本博客主要介绍一级指针 二级指针 三级指针 指针数组和数组指针的综合应用示例 下面简单介绍指针数组和数组指针的区别 指针数组 char p aaa bbbb 定义了一个数组p p中每一个元素都是一个指针 数组指针 char p 5 定义了一
  • windows10 Linux子系统(wsl)文件目录

    简介 使用window中的Linux子系统创建的文件究竟放在什么地方 既然作为子系统文件肯定是可以互相访问的 windows访问Linux目录 wsl ubuntu Linux子系统的目录是在这个目录下 C Users 用户名 AppDat
  • OpenGL加速渲染:顶点数组

    加速渲染主要有两种方法 显示列表与顶点数组 其中 显示列表是通过预编译方式加速 而顶点数组是通过优化实时编译方式加速 但是 不需要同时使用两种加速方式 如果把顶点数组放在预编译中 然后通过显示列表来显示 这样做所耗时间与直接使用顶点数组所耗
  • java实现Date和Timestamp的相互转换

    Date转Timestamp 一句搞定 Timestamp createTime new Timestamp new Date getTime Timestamp转Date Timestamp t new Timestamp System
  • 飞机大战

    目录 一 效果图 https www bilibili com video BV1cT4y1Z7f3 二 学习参考资料 b站up主 鱼C 小甲鱼 Python教程 零基础入门学习Python 三 代码框架 这里只是给出了功能描述 给出了一个
  • Struts2详解

    struts2框架是SSH框架集中的框架之一 是一个基于MVC设计模式的Web应用框架 它本质上相当于一个servlet 在MVC设计模式中 Struts2作为控制器层 Controller 来建立模型与视图的数据交互 在使用struts2
  • SpringBoot整合grpc

    grpc简介 gRPC gRPC Remote Procedure Calls 是 Google 发起的一个开源远程过程调用系统 该系统基于 HTTP 2 协议传输 摘自知乎 https zhuanlan zhihu com p 38932
  • QT VS中双击ui文件无法打开的问题

    如果你在VS里安装QT之后 双击ui文件 出现闪退并且显示xxx ui文件无法打开 这篇博客或许能帮助到你 一 问题描述 双击ui文件出现闪退 如下图所示 这个界面1s之后就会闪退 二 解决方案 步骤1 步骤2 一 问题描述 双击ui文件出
  • 【Java基础】Date类、DateFormat类

    目录 一 Date类 二 DateFormat类 1 format方法 2 parse方法 一 Date类 data 翻译成中文是 日期 的意思 在Java里面Data类表示特定的瞬间 精确到毫秒 创建data对象 不初始化即表示为当前系统
  • 原型模式

    原型模式 根据实际案例分析原型模式的优点 浅克隆 代码示例 测试分析 深克隆 代码示例 测试 分析原型模式的优点 Spring框架中原型模式案例 业务与原型模式的落地示例 根据实际案例分析原型模式的优点 在传统模式下 假设需要克隆对象 动态
  • Unity3D Texture to Sprite

    unity3d中截屏转化为sprite using UnityEngine using System Collections using UnityEngine UI public class Demo MonoBehaviour publ
  • vue实现下载文件

    最最简单的vue实现下载文件 用vue实现调取后端接口从服务器下载文件 话不多说直接上代码 1 首先第一步改下axios的配置 const axios axios create config axios interceptors reque
  • HTTP

    一 安全特性 在上篇文章中 我们了解到HTTP在通信过程中 存在以下问题 通信使用明文 不加密 内容可能被窃听 不验证通信方的身份 因此有可能遭遇伪装 而HTTPS的出现正是解决这些问题 HTTPS是建立在SSL之上 其安全性由SSL来保证
  • 【插件】谷歌浏览器插件 visio在线打开vsdx文件 .vsdx文件在线查看

    提供一个下载地址 谷歌插件下载 步骤1 输入 visio viewer 2 选择版本 我选择的是V4 4 点击下载 3 根据123步骤点击进入扩展程序 4 打开刚才下载的文件并解压 解压后打开找到crx结尾的文件 把该文件拖入扩展程序 点击
  • IDEA的下载和使用安装

    一 IDEA的下载 IDEA下载地址 https www jetbrains com idea download section windows IDEA 分为两个版本 旗舰版 Ultimate 和社区版 Community 二 安装过程
  • 射频中的 S参数 总结

    S参数简介 S参数 也就是散射参数 是微波传输中的一个重要参数 S12为反向传输系数 也就是隔离 S21为正向传输系数 也就是增益 S11为输入反射系数 也就是输入回波损耗 S22为输出反射系数 也就是输出回波损耗 S参数作为描述线性无源传
  • typescript 基础类型注解

    TypeScript 基础类型 序号 数据类型 关键字 描述 1 任意 any 声明为 any 的变量可以赋予任意类型的值 2 数值 number 双精度 64 位浮点值 它可以用来表示整数和分数 3 字符串 string 一个字符系列 使
  • Qt中QPushButton设置按钮的文本位置

    特定样式 引言 解决方法 总结 引言 今天碰到一个动态创建的QPushButton添加到布局中 我需要设置按钮的文本距离边框的距离 按照以往自己设置的与边框的距离的方式设置的样式 没有起到任何作用 前提是 qss文件能正常加载 其它控件都正
  • Qt中对TCP粘包的处理

    当时用TCP协议传输数据时 经常出现粘包的现象 当服务器向客户端发送数据之后 客户端还没有接收数据的时候 这段时间数据在什么地方 1 服务器 服务器已经发出数据了 2 网线 数据应该在内存 怎么会在网线里面 又没有内存 3 客户端 是的 这