#include "sendprogthread.h" #include "gutil/qnetwork.h" #include #include #include #include #include #include SendProgThread::SendProgThread(const QString &progDir, const QString &ip, int port) : prog_dir(progDir), ip(ip), port(port) { connect(this, &QThread::finished, this, &QThread::deleteLater); } void SendProgThread::run() { emit emProgress(0); // 进度条归零 auto fileInfos = QDir(prog_dir).entryInfoList(QDir::Files); if(fileInfos.isEmpty()) { emit emErr(tr("Program is empty")); return; } if(stoped) return; TcpSocket tcp; tcp.connectToHost(ip, port); if(! tcp.waitForConnected()) { emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" when waitForConnected"); tcp.close(); return; } if(stoped) { tcp.close(); return; }; //发送节目列表协商 QJsonArray ids; foreach(auto fileInfo, fileInfos) { auto baseName = fileInfo.baseName(); if(baseName!="program") ids.append(baseName); } if(! ids.isEmpty()) { QJsonObject req; req.insert("_type", "consult"); req.insert("proName", "program"); req.insert("idList", ids); req.insert("zVer", "xixun1"); auto requ = QJsonDocument(req).toJson(QJsonDocument::Compact); auto resNum = tcp.write(requ); tcp.flush(); if(resNum == -1 || ! tcp.waitForBytesWritten()) { emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" when write 'consult'. size"+QString::number(requ.size())); tcp.close(); return; } if(! tcp.waitForReadyRead()) { emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" when waitForRead 'consult'. size"+QString::number(requ.size())); tcp.close(); return; } auto resp = tcp.readAll(); if(resp.isEmpty()) { emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" when read 'consult'. size"+QString::number(requ.size())); tcp.close(); return; } if(stoped) { tcp.close(); return; }; QJsonParseError parseErr; QJsonDocument res = QJsonDocument::fromJson(resp, &parseErr); for(int i=2; parseErr.error == QJsonParseError::UnterminatedString && i < 10; i++) { if(! tcp.waitForReadyRead()) { emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" when waitForRead 'consult' "+QString::number(i)); tcp.close(); return; } auto resp2 = tcp.readAll(); if(resp2.isEmpty()) { emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" when read 'consult' "+QString::number(i)); tcp.close(); return; } resp += resp2; res = QJsonDocument::fromJson(resp, &parseErr); } if(parseErr.error != QJsonParseError::NoError) { emit emErr(parseErr.errorString()+" when parse consult. size:"+QString::number(resp.size())); tcp.close(); return; } if(res["_type"].toString()=="consult") { fileInfos.clear(); fileInfos.append(QFileInfo(prog_dir+"/program")); auto ids = res["idList"].toArray(); for(auto id : ids) fileInfos.append(QFileInfo(prog_dir+"/"+id.toString())); } } if(stoped) { tcp.close(); return; } qint64 progSize = 0; foreach(auto fileInfo, fileInfos) progSize += fileInfo.size(); if(progSize == 0) { emit emErr(tr("Program is empty")); tcp.close(); return; } auto req = QJsonObject(); req.insert("_type", "proStart"); req.insert("proName", "program"); req.insert("proSize", progSize); req.insert("zVer","xixun1"); auto resNum = tcp.write(QJsonDocument(req).toJson(QJsonDocument::Compact)); if(resNum == -1 || ! tcp.waitForBytesWritten()) { emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" when write 'proStart'"); tcp.close(); return; } if(stoped) { tcp.close(); return; } //4.发送协商列表应答里的文件 int64_t sentBytes = 0; char buf[8192]; for(auto &info : fileInfos) if(info.isFile()) { auto baseName = info.baseName(); auto remain = info.size(); req = QJsonObject(); req.insert("_type", "fileStart"); req.insert("id", baseName); req.insert("size", remain); req.insert("relative_path", ""); req.insert("zVer","xixun1"); auto resNum = tcp.write(QJsonDocument(req).toJson(QJsonDocument::Compact)); if(resNum == -1 || ! tcp.waitForBytesWritten()) { emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" when write 'fileStart'"); tcp.close(); return; } auto file = new QFile(info.filePath()); if(! file->open(QFile::ReadOnly)) { emit emErr(tr("Open file failed")+" "+file->errorString()); tcp.close(); return; } while(remain > 0) { resNum = file->read(buf, qMin(8192LL, remain)); if(resNum <= 0) { emit emErr(tr("Read file failed")+" "+file->errorString()); tcp.close(); file->close(); return; } if(stoped) { tcp.close(); file->close(); return; }; if(! tcp.waitForBytesWritten(60000)) { emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" when waitForWritten file: "+file->fileName()); tcp.close(); file->close(); return; } resNum = tcp.write(buf, resNum); if(resNum <= 0) { emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" when write file: "+file->fileName()); tcp.close(); file->close(); return; } if(stoped) { tcp.close(); file->close(); return; }; remain -= resNum; sentBytes += resNum; if(sentBytes != 0) emit emProgress(sentBytes * 99 / progSize); } file->close(); if(stoped) { tcp.close(); return; }; req = QJsonObject(); req.insert("_type", "fileEnd"); req.insert("id", baseName); req.insert("zVer", "xixun1"); resNum = tcp.write(QJsonDocument(req).toJson(QJsonDocument::Compact)); if(resNum == -1 || ! tcp.waitForBytesWritten()) { emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" when write 'fileEnd'"); tcp.close(); return; } } if(stoped) { tcp.close(); return; }; //5.发送结束 req = QJsonObject(); req.insert("_type", "proEnd"); req.insert("proName", "program"); req.insert("zVer","xixun1"); resNum = tcp.write(QJsonDocument(req).toJson(QJsonDocument::Compact)); if(resNum == -1 || ! tcp.waitForBytesWritten()) { emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" when write 'proEnd'"); tcp.close(); return; }; if(! tcp.waitForReadyRead()) { emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" when waitForRead 'proEnd'"); tcp.close(); return; } auto resp = tcp.readAll(); if(resp.isEmpty()) { emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" when read 'proEnd'"); tcp.close(); return; } tcp.close(); emit emProgress(100); emit emErr("OK"); }