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

发布于:2025-09-11 ⋅ 阅读:(21) ⋅ 点赞:(0)

主要是使用协议头
发送方

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

网站公告

今日签到

点亮在社区的每一天
去签到