【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);}}}
}