228 lines
8.6 KiB
C++
228 lines
8.6 KiB
C++
#include "sendprogthread.h"
|
|
#include "gutil/qnetwork.h"
|
|
#include <QHostAddress>
|
|
#include <QDir>
|
|
#include <QJsonArray>
|
|
#include <QDirIterator>
|
|
#include <QMessageBox>
|
|
#include <QMetaEnum>
|
|
|
|
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.发送协商列表应答里的文件
|
|
long long 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");
|
|
}
|