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

【qt】通过TCP传输json,json里包含图像

主要是使用协议头
发送方

        connect(m_pDetectWorker, &DetectionWorker::sig_detectImg, this, [=](const QJsonObject &json){// 转换为JSON数据QJsonDocument doc(json);QByteArray jsonData = doc.toJson(QJsonDocument::Compact);// 构建增强协议头struct EnhancedHeader {quint32 magic = 0x4A534F4E; // "JSON"quint32 version = 1;        // 协议版本quint32 dataSize;quint32 checksum;quint8 dataType;           // 0=JSON, 1=Image, 2=Text等char timestamp[20];        // 时间戳char reserved[15];};EnhancedHeader header;header.dataSize = jsonData.size();header.dataType = 0; // JSON数据类型// 计算校验和quint32 checksum = 0;for (int i = 0; i < jsonData.size(); ++i) {checksum += static_cast<quint8>(jsonData[i]);}header.checksum = checksum;// 添加时间戳QByteArray timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz").toUtf8();memcpy(header.timestamp, timestamp.constData(), qMin(timestamp.size(), 19));header.timestamp[19] = '\0';memset(header.reserved, 0, sizeof(header.reserved));// 发送给所有客户端foreach(QTcpSocket* client, clients) {if(client->state() == QAbstractSocket::ConnectedState) {client->setSocketOption(QAbstractSocket::LowDelayOption, 1);// 发送协议头client->write(reinterpret_cast<const char*>(&header), sizeof(header));// 发送JSON数据client->write(jsonData);}}});

接收方

void OnlineFrameViewModel::receiveImageData()
{QTcpSocket* socket = qobject_cast<QTcpSocket*>(sender());if(!socket) return;// 定义协议头结构(与发送端一致)struct EnhancedHeader {quint32 magic;          // 魔数 "JSON"quint32 version;        // 协议版本quint32 dataSize;       // 数据大小quint32 checksum;       // 校验和quint8 dataType;        // 数据类型char timestamp[20];     // 时间戳char reserved[15];      // 保留字段};static QByteArray receivedDataBuffer;receivedDataBuffer.append(socket->readAll());// 处理可能存在的多个数据包(粘包处理)while (!receivedDataBuffer.isEmpty()) {// 如果缓冲区大小不足以包含协议头,等待更多数据if (receivedDataBuffer.size() < sizeof(EnhancedHeader)) {return;}// 提取协议头EnhancedHeader header;memcpy(&header, receivedDataBuffer.constData(), sizeof(EnhancedHeader));// 验证魔数if (header.magic != 0x4A534F4E) { // "JSON"qDebug() << u8"无效的数据包魔数,清空缓冲区";receivedDataBuffer.clear();return;}// 检查是否收到完整的数据包(协议头 + 数据)if (receivedDataBuffer.size() < sizeof(EnhancedHeader) + header.dataSize) {// 数据不完整,等待更多数据return;}// 提取JSON数据QByteArray jsonData = receivedDataBuffer.mid(sizeof(EnhancedHeader), header.dataSize);// 验证校验和quint32 calculatedChecksum = 0;for (int i = 0; i < jsonData.size(); ++i) {calculatedChecksum += static_cast<quint8>(jsonData[i]);}if (calculatedChecksum != header.checksum) {qDebug() << u8"数据校验失败,丢弃数据包";// 移除损坏的数据包receivedDataBuffer.remove(0, sizeof(EnhancedHeader) + header.dataSize);continue;}// 移除已处理的数据包receivedDataBuffer.remove(0, sizeof(EnhancedHeader) + header.dataSize);// 解析JSON数据QJsonParseError jsonError;QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &jsonError);if(jsonError.error != QJsonParseError::NoError) {qDebug() << u8"JSON解析错误:" << jsonError.errorString();continue;}if(jsonDoc.isObject()) {QJsonObject jsonObj = jsonDoc.object();// 处理图像数据(原有逻辑保持不变)if(jsonObj.contains("image_path")) {QString jsonOriPath = jsonObj["image_path"].toString();//原始路径,pc1的路径QString imgPath;// 指定检测 E 盘QStorageInfo volume("Y:/");if (volume.isValid()) {// 双工控机测试是肯定存在imgPath = jsonOriPath.replace(u8"E:/raw图/","Y:/");emit sig_sendMsg(u8"检测路径:"+ imgPath);QFileInfo fileInfo(imgPath);if (!fileInfo.exists()) {qCritical() << "Error: Path does not exist:" << imgPath;continue; // 继续处理下一个数据包}} else {emit sig_sendMsg("Y:/ is not a valid volume.");imgPath = jsonOriPath;emit sig_sendMsg(u8"Y盘读取失败,检查PLC网口的网络情况");emit sig_sendMsg(u8"检测路径:"+ imgPath);QFileInfo fileInfo(imgPath);if (!fileInfo.exists()) {qCritical() << "Error: Path does not exist:" << imgPath;continue; // 继续处理下一个数据包}}QImage enhanceImg(imgPath);//=============================👇=============================if(jsonObj.contains("image_data")) {QString base64String = jsonObj["image_data"].toString();QByteArray byteArray = QByteArray::fromBase64(base64String.toUtf8());QImage img;if (img.loadFromData(byteArray)) {qDebug() << u8"图片加载成功,尺寸为:" << img.size();enhanceImg = img;} else {qDebug() << u8"图片加载失败";}}//=============================👆=============================QSharedPointer<ImageDataInfo> imgInfo(new ImageDataInfo);imgInfo->imageFilePath = imgPath;imgInfo->enhanceImg = enhanceImg;imgInfo->barcode = jsonObj["barcode"].toString();imgInfo->device = jsonObj["device"].toInt();imgInfo->pointIndex = jsonObj["pointIndex"].toInt();imgInfo->skipframe = jsonObj["skipframe"].toInt();imgInfo->overlayframe = jsonObj["overlayframe"].toInt();imgInfo->kv = jsonObj["kv"].toInt();imgInfo->ua = jsonObj["ua"].toInt();imgInfo->grayMean = jsonObj["grayMean"].toInt();emit sig_sendMsg(u8"检测开始"+imgInfo->barcode);int device = imgInfo->pointIndex;int pointIndex = imgInfo->pointIndex;QtConcurrent::run([=]() {saveBarcodeLog(imgInfo->barcode,device,pointIndex);});if(m_pDetectWorker!=nullptr)m_pDetectWorker->enqueueImage(*imgInfo);emit sig_didDisplayLiveImg(enhanceImg,imgInfo->device);}}}
}

文章转载自:

http://LsIWo0m7.txzmy.cn
http://ui3gXVpg.txzmy.cn
http://pWw1mh9o.txzmy.cn
http://7h3ucV80.txzmy.cn
http://PSDX1vmN.txzmy.cn
http://HV3mYM6T.txzmy.cn
http://bTcgVeXL.txzmy.cn
http://5Dg42LKC.txzmy.cn
http://0NqJfKln.txzmy.cn
http://itEcyd3Q.txzmy.cn
http://A7WJJNju.txzmy.cn
http://xdWNiNZX.txzmy.cn
http://dYqDWxXU.txzmy.cn
http://XjxAFBtx.txzmy.cn
http://tarFx8PA.txzmy.cn
http://oVtZNIbb.txzmy.cn
http://hiLGBr2Y.txzmy.cn
http://JPE1tWOk.txzmy.cn
http://4UrnTti7.txzmy.cn
http://SdMrjQ8K.txzmy.cn
http://ucIox6ta.txzmy.cn
http://wPl9qV2n.txzmy.cn
http://ZoqvPyXV.txzmy.cn
http://Nh9BW5uY.txzmy.cn
http://b48nIlV7.txzmy.cn
http://nxeEwoHe.txzmy.cn
http://6G96kPYm.txzmy.cn
http://sem0gvHx.txzmy.cn
http://ih7ObzLY.txzmy.cn
http://NBBCe1NL.txzmy.cn
http://www.dtcms.com/a/376628.html

相关文章:

  • 力扣每日一刷Day 20
  • 线程池队列与活跃度报警检测器实现详解
  • 【硬件-笔试面试题-80】硬件/电子工程师,笔试面试题(知识点:MOS管与三极管的区别)
  • A股大盘数据-20250910分析
  • 大数据毕业设计-基于大数据的健康饮食推荐数据分析与可视化系统(高分计算机毕业设计选题·定制开发·真正大数据)
  • 墨水屏程序
  • 小米自带浏览器提示“已停止访问该网页”的解决办法以及一些优化
  • 零代码入侵:Kubernetes 部署时自动注入 kube-system UID 到 .NET 9 环境变量
  • Python核心技术开发指南(049)——文件操作综合应用
  • 机器学习项目中正确进行超参数优化:Optuna库的使用
  • QueryWrapper 全面解析:从原理到实战
  • 2025时序数据库选型:深入解析IoTDB从主从架构基因到AI赋能的创新之路
  • 云手机可以用来托管游戏吗?
  • 每日算法之:给定一个有序数组arr,代表坐落在X轴上的点,给定一个正数K,代表绳子的长度,返回绳子最多压中几个点? 即使绳子边缘处盖住点也算盖住
  • 如何利用AI工具更好地服务人:从效率到温度的平衡
  • ADC模数转换器详解(基于STM32)
  • 深入理解网络浏览器运行原理
  • 线扫相机不出图原因总结
  • 【Linux系统】日志与策略模式
  • 物联网时序数据库IoTDB是什么?
  • Rust:系统编程的革新者
  • 【postMan / apifox 文件上传】
  • 使用 javax.net.ssl.HttpsURLConnection 发送 HTTP 请求_以及为了JWT通信选用OSS的Jar的【坑】
  • 9.10 Swiper-layer-laydate
  • 基于代理模式:深入了解静态代理和动态代理
  • 崔传波教授:以科技与人文之光,点亮近视患者的清晰视界‌
  • java 代理模式实现
  • 2025最新的软件测试面试八股文(800+道题)
  • 深入浅出LVS负载均衡群集:原理、分类与NAT模式实战部署
  • Nginx 配置 SSL/TLS 全指南:从安装到安全强化