Qt中的网络模块提供了高级的网络访问功能,但与WinInet API相比,它可能会在性能上略逊一筹。这可能是由于以下几个因素造成的:
-
抽象性和灵活性: Qt的网络模块提供了更高层次的抽象,允许开发者以更简洁的方式编写网络相关的代码。这种抽象性和灵活性可能会导致一些性能开销。
-
跨平台支持: Qt的网络模块是跨平台的,可以在多种操作系统上运行,包括Windows、macOS和Linux等。为了实现跨平台兼容性,可能会引入一些额外的抽象层,从而影响性能。
-
异步处理: Qt的网络模块通常使用异步方式进行网络访问,这意味着网络请求是在单独的线程中进行的,而不会阻塞主线程。虽然这样做提高了程序的响应性,但也可能会导致一些性能损失。
-
底层实现: Qt的网络模块可能使用不同的底层实现,如基于操作系统提供的网络库或者第三方库,这些底层实现的性能差异可能会影响到整体性能。
虽然Qt的网络模块在性能上可能略逊于WinInet API,但它提供了更高级的功能和更好的跨平台支持,适用于需要在不同操作系统上运行的应用程序。如果性能是关键考虑因素,可以考虑使用其他更专门的网络库或API来实现网络访问。
FileDownloaderThread.h
#ifndef FILEDOWNLOADER_H
#define FILEDOWNLOADER_H
#include <QThread>
#include <QDebug>
#include <QUrl>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QFile>
#include <QEventLoop>
#include <QTimer>
class FileDownloader : public QThread
{
Q_OBJECT
public:
explicit FileDownloader(QObject *parent = nullptr);
void setUrl(const QString &url, const QString &outputFile);
signals:
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
void downloadFinished(bool success, QString errorMessage);
protected:
void run() override;
private:
QString m_url;
QString m_outputFile;
};
#endif // FILEDOWNLOADER_H
FileDownloaderThread.cpp
#include "FileDownloaderThread.h"
FileDownloader::FileDownloader(QObject *parent) : QThread(parent), m_url(""), m_outputFile("")
{
}
void FileDownloader::setUrl(const QString &url, const QString &outputFile)
{
m_url = url;
m_outputFile = outputFile;
}
void FileDownloader::run()
{
// 如果URL或输出文件为空,则发出错误信号并返回
if (m_url.isEmpty() || m_outputFile.isEmpty()) {
emit downloadFinished(false, "url或保存路径有误");
return;
}
QUrl qurl(m_url);
QNetworkRequest xrqt(qurl);
QNetworkAccessManager manager;
QNetworkReply *reply = NULL;
QTimer timeoutTimer;
QEventLoop loop;
// 如果网络请求失败,则发出错误信号并返回
reply = manager.get(xrqt);
if (!reply) {
emit downloadFinished(false, "连接服务器失败.");
return;
}
// 创建超时定时器
timeoutTimer.setSingleShot(true);
connect(&timeoutTimer, &QTimer::timeout, [&](){
// 如果超时,则中止下载
reply->abort();
});
// 连接下载进度信号
connect(reply, &QNetworkReply::downloadProgress, [&](qint64 bytesReceived, qint64 bytesTotal){
emit downloadProgress(bytesReceived, bytesTotal);
// 更新超时计时器
timeoutTimer.start(10000); // 重启超时定时器
});
// 连接下载完成信号
connect(reply, &QNetworkReply::finished, [&](){
// 停止超时计时器
timeoutTimer.stop();
// 根据网络响应的状态进行处理
if (reply->error() == QNetworkReply::NoError)
{
QFile file(m_outputFile);
if (file.open(QIODevice::WriteOnly))
{
file.write(reply->readAll());
file.close();
emit downloadFinished(true, "下载成功.");
}
else
{
emit downloadFinished(false, "下载完毕,但写入文件失败.");
}
}
else
{
emit downloadFinished(false, reply->errorString());
}
// 删除网络回复对象
reply->deleteLater();
});
// 启动超时定时器
timeoutTimer.start(10000); // 设置初始超时时间为10秒
// 开启事件循环
connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
loop.exec();
// 如果超时计时器仍在运行,则说明下载超时
if (timeoutTimer.isActive())
{
timeoutTimer.stop(); // 停止超时计时器
emit downloadFinished(false, "下载超时.");
}
}
调用测试方法:
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void startDownload();
void updateProgress(qint64 bytesReceived, qint64 bytesTotal);
void handleDownloadFinished(bool success, QString errorMessage);
void on_btnDown_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
MainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "FileDownloaderThread.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::startDownload() {
FileDownloader *downloader = new FileDownloader(this);
downloader->setUrl("http://xxx.com/xxx.png", "xxx.png");
connect(downloader, &FileDownloader::downloadProgress, this, &MainWindow::updateProgress);
connect(downloader, &FileDownloader::downloadFinished, this, &MainWindow::handleDownloadFinished);
downloader->start();
}
void MainWindow::updateProgress(qint64 bytesReceived, qint64 bytesTotal) {
if (bytesTotal > 0) {
ui->progressBar->setValue(100 * bytesReceived / bytesTotal);
}
}
void MainWindow::handleDownloadFinished(bool success, QString errorMessage) {
if (success) {
qDebug() << "Download successful!";
} else {
qDebug() << "Download failed: " << errorMessage;
}
ui->btnDoiwn->setEnabled(true);
}
void MainWindow::on_btnDown_clicked()
{
ui->btnDoiwn->setEnabled(false);
startDownload();
}

5666

被折叠的 条评论
为什么被折叠?



