文章目录
前言
1. 定义的接口
- public公共接口,用作单线程
- public slots公共槽函数,支持类对象调用,在哪个线程调用即在哪个线程运行
- signals 信号,通过调用信号的方式在其对应槽函数线程创建事件执行,用于多线程
public:
bool get(QString url, QString &data, int timeout = 20000);
bool post(QString url, QString &data, QByteArray jsonData, int timeout = 20000);
bool getDownload(QString url, QString filePath, int timeout = 20000);
signals:
void sgnGet(QString url, int timeout = 20000);
void sgnPost(QString url,QByteArray jsonData, int timeout = 20000);
void sgnGetDownload(QString url, QString filePath, int timeout = 20000);
void Progress(qint64, qint64);
void finished(QString data, bool result);
public slots:
void gets(QString url, int timeout = 20000);
void posts(QString url,QByteArray jsonData, int timeout = 20000);
void getDownloads(QString url, QString filePath, int timeout = 20000);
2.connect信号槽
connect(this, &Http::sgnGet, this, &Http::gets);
connect(this, &Http::sgnGetDownload, this, &Http::getDownloads);
connect(this, &Http::sgnPost, this, &Http::posts);
3. get
//! 通过信号槽的方式调动
void Http::gets(QString url, int timeout)
{
QString data = "";
bool rt = this->get(url, data, timeout);
emit finished(data, rt);
}
//! get请求数据
bool Http::get(QString url, QString& data, int timeout)
{
qDebug()<<"Http QThread::currentThread() = "<<QThread::currentThread();
int repeatSend = 0;
// 三次请求失败结束请求数据
while(!repeatGet(url, data, timeout))
{
if(++repeatSend >= 3) return false;
}
return true;
}
//!
bool Http::repeatGet(QString& url, QString& data, int& timeout)
{
// 建立事件循环
QEventLoop loop;
//设置发送请求所需的信息
QNetworkRequest request;
request.setUrl(QUrl(url));
request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/x-www-form-urlencoded"));
//管理网络请求和响应
QNetworkAccessManager manager;
connect(&manager, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
// 超时检测
QTimer timer;
timer.setSingleShot(true);
connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
// 处理网络请求的响应数据
QNetworkReply* pReply = manager.get(request);
connect(pReply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
connect(pReply, SIGNAL(error(QNetworkReply::NetworkError)), &loop, SLOT(quit()));
// 超时检测定时器启动
timer.start((timeout > 0) ? timeout : 2000);
//执行事件循环,直到退出循环再执行后面代码
loop.exec();
//! 退出事件循环,判断定时器是否触发,触发即超时
if(!timer.isActive())
{
pReply->deleteLater();
return false;
}
//! 未超时停止定时器
timer.stop();
//
QNetworkReply::NetworkError err = pReply->error();
if(err != QNetworkReply::NoError)
{
// 检测状态码
int statusCode = pReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
qDebug()<<"get error, statusCode = "<<statusCode;
return false;
}
//
data = QString::fromUtf8(pReply->readAll());
pReply->deleteLater();
return true;
}
QString data = "";
qDebug()<<"----------------------------------";
qDebug()<< "MainWindow QThread::currentThread() = "<< QThread::currentThread();
qDebug()<<data.size();
data.clear();
qDebug()<<"--------------- 1 ----------------";
http->get(QString("http://www.baidu.com"),data, 2000);
qDebug()<<data.size();
data.clear();
qDebug()<<"--------------- 2 ----------------";
http->gets(QString("http://www.baidu.com"), 2000);
qDebug()<<data.size();
data.clear();
qDebug()<<"--------------- 3 ----------------";
emit http->sgnGet(QString("http://www.baidu.com"), 2000);
qDebug()<<data.size();
qDebug()<<"----------------------------------";
// 保存HTTP响应内容
// 组装保存的文件名 文件名格式: 路径/年_月_日 小时_分_秒 httpfile.html
QDateTime current_date_time =QDateTime::currentDateTime();
QString current_date =current_date_time.toString("yyyy_MM_dd hh_mm_ss");
QString filePath = ".";
QString fileName = filePath + '/' + current_date + " httpfile" + ".html";
QFile file(fileName);
if (!file.open(QIODevice::ReadWrite | QIODevice::Text)){
//qDebug() << "file open error!";
return ;
}
QTextStream out(&file);
out.setCodec("UTF-8");
out<<data;
file.close();
data.clear();
4. get 下载文件
void Http::getDownloads(QString url, QString filePath, int timeout)
{
bool rt = this->getDownload(url, filePath, timeout);
emit finished(filePath, rt);
}
bool Http::getDownload(QString url, QString filePath, int timeout)
{
qDebug()<<"Http QThread::currentThread() = "<<QThread::currentThread();
int repeatSend = 0;
//
while(!repeatGetDownload(url, filePath, timeout))
{
if(++repeatSend >= 3) return false;
}
return true;
}
bool Http::repeatGetDownload(QString& url, const QString& filePath, const int& timeout)
{
if(!pFile.isOpen()) pFile.setFileName(filePath);
//
QEventLoop loop;
//
QNetworkRequest request;
request.setUrl(QUrl(url));
//
QNetworkAccessManager manager;
connect(&manager, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
//
QTimer timer;
timer.setSingleShot(true);
connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
//
QNetworkReply* pReply = manager.get(request);
connect(pReply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
connect(pReply, SIGNAL(error(QNetworkReply::NetworkError)), &loop, SLOT(quit()));
connect(pReply, &QNetworkReply::readyRead, &loop, &QEventLoop::quit);
//
timer.start((timeout > 0) ? timeout : 20000);
loop.exec(QEventLoop::ExcludeSocketNotifiers);
disconnect(pReply, &QNetworkReply::readyRead, &loop, &QEventLoop::quit);
//! 超时
if(!timer.isActive())
{
pReply->deleteLater();
return false;
}else{
timer.stop();
}
QNetworkReply::NetworkError err = pReply->error();
if(err != QNetworkReply::NoError)
{
// 检测状态码
int statusCode = pReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
qDebug()<<"get error, statusCode = "<<statusCode;
//! 重定向
const QVariant redirectionTarget = pReply->attribute(QNetworkRequest::RedirectionTargetAttribute);
if(!redirectionTarget.isNull())
{
QUrl redirectedUrl = redirectionTarget.toUrl();
url = redirectedUrl.toString();
}
return false;
}
connect(pReply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(LoadProgress(qint64,qint64)));
connect(pReply, &QNetworkReply::readyRead, this, &Http::readSave);
loop.exec();
return true;
}
void Http::readSave()
{
QNetworkReply* pReply = (QNetworkReply*)sender();
if(!pFile.isOpen())
{
//! save file
if(!pFile.open(QIODevice::WriteOnly))
{
qDebug() << pFile.errorString();
}
}
pFile.write(pReply->readAll());
}
void Http::LoadProgress(qint64 recved, qint64 total)
{
QNetworkReply* pReply = (QNetworkReply*)sender();
if(recved >= total)
{
pFile.close();
pReply->deleteLater();
}
}
QString url = "https://1.as.dl.wireshark.org/win64/Wireshark-win64-4.0.10.exe";
url = "https://enigmaprotector.com/assets/files/enigma_en_demo.exe";
qDebug()<<"----------------------------------";
qDebug()<< "MainWindow QThread::currentThread() = "<< QThread::currentThread();
qDebug()<<"--------------- 1 ----------------";
QString path = "./enigma1.exe";
//http->getDownload(url, path, 4000);
qDebug()<<"--------------- 2 ----------------";
path = "./enigma2.exe";
//http->getDownloads(url, path, 4000);
qDebug()<<"--------------- 3 ----------------";
path = "./enigma3.exe";
emit http->sgnGetDownload(url, path, 4000);
qDebug()<<"----------------------------------";
5. post
void Http::posts(QString url,QByteArray jsonData, int timeout)
{
QString data;
bool rt = this->post(url, data, jsonData, timeout);
emit finished(data, rt);
}
//!
bool Http::post(QString url, QString& data, QByteArray jsonData, int timeout)
{
int repeatSend = 0;
//
while(!repeatPost(url, data, jsonData, timeout))
{
++repeatSend;
if(++repeatSend >= 3)
return false;
}
return true;
}
//
bool Http::repeatPost(QString& url, QString& data, QByteArray& jsonData, int& timeout)
{
//
QEventLoop loop;
//
QNetworkRequest request;
request.setUrl(QUrl(url));
request.setHeader(QNetworkRequest::ContentTypeHeader, "text/xml;charset=UTF-8");
//
QNetworkAccessManager manager;
connect(&manager, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
//
QTimer timer;
timer.setSingleShot(true);
connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
//
QNetworkReply* pReply = manager.post(request, jsonData);
connect(pReply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
connect(pReply, SIGNAL(error(QNetworkReply::NetworkError)), &loop, SLOT(quit()));
//
timer.start((timeout > 0) ? timeout : 2000);
loop.exec();
//! 超时
if(!timer.isActive())
{
pReply->deleteLater();
return false;
}
//!
timer.stop();
//
QNetworkReply::NetworkError err = pReply->error();
if(err != QNetworkReply::NoError)
{
//! 检测状态码
int statusCode = pReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
qDebug()<<"get error, statusCode = "<<statusCode;
//! 重定向
const QVariant redirectionTarget = pReply->attribute(QNetworkRequest::RedirectionTargetAttribute);
if(!redirectionTarget.isNull())
{
QUrl redirectedUrl = redirectionTarget.toUrl();
url = redirectedUrl.toString();
}
return false;
}
//!
data = QString::fromUtf8(pReply->readAll());
pReply->deleteLater();
return true;
}
总结
学啥记啥,好记性不如烂笔头!