主要是使用協議頭
發送方
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);}}}
}