一、HTTP 服务器实现方案
-
QtWebApp 集成
-
原生 Qt 网络模块
- 使用
QTcpServer
监听端口,通过incomingConnection()
接收客户端连接。 - 解析 HTTP 请求头(如
QByteArray
处理报文),动态生成响应内容(如 HTML/JSON)。
- 使用
二、HTTP 客户端实现方案
Qt中的QNetworkAccessManager
是网络请求管理的核心类,用于异步处理HTTP/HTTPS等协议通信。以下是其关键特性及使用方式:
1. 核心功能
- 单例管理:整个Qt应用只需一个实例即可管理所有网络请求,负责维护代理、缓存等全局配置。
- 请求调度:支持GET、POST、PUT、DELETE等标准HTTP方法,并通过队列管理并发请求(如HTTP协议默认同一主机/端口允许6个并发请求)。
2. 基本使用步骤
// 创建实例
QNetworkAccessManager *manager = new QNetworkAccessManager(this);// 发送GET请求示例
connect(manager, &QNetworkAccessManager::finished, this, [=](QNetworkReply *reply) {// 处理响应数据QByteArray data = reply->readAll();reply->deleteLater(); // 避免内存泄漏
});
manager->get(QNetworkRequest(QUrl("http://example.com")));
通过finished
信号接收响应,使用QNetworkReply
对象解析返回数据和元信息(如HTTP头)。
QNetworkAccessManager manager;
QUrl url("http://example.com/api/resource");
QNetworkRequest request(url); // 添加鉴权信息(与 GET 请求相同)
QByteArray authHeaderData = "Basic " + yourBase64EncodedAuthString;
request.setRawHeader(QByteArray("Authorization"), authHeaderData); // 准备 POST 数据(这里只是一个简单的示例)
QByteArray postData = "key1=value1&key2=value2"; // 发送 POST 请求
QNetworkReply *reply = manager.post(request, postData);
3. 异步处理与资源管理
- 异步API:所有请求非阻塞主线程,通过信号槽机制通知完成状态。
- 资源释放:需手动调用
reply->deleteLater()
释放QNetworkReply
对象,不可在槽函数中直接delete
。
4. 高级配置
- 代理与缓存:可通过
setProxy()
和setCache()
方法设置全局代理及缓存策略。 - SSL加密连接:使用
connectToHostEncrypted()
建立HTTPS连接,支持自定义SSL配置。
5. 错误处理
监听errorOccurred
信号处理网络错误:
connect(reply, &QNetworkReply::errorOccurred, [](QNetworkReply::NetworkError code) {qDebug() << "Error:" << code;
});
6. 超时控制
通过QTimer
实现异步请求超时机制:
QTimer::singleShot(5000, :ml-search[reply] { // 5秒超时if (reply && reply->isRunning()) {reply->abort();qDebug() << "Request timeout";}
});
7. 鉴权处理
在请求头中添加鉴权信息(如Authorization
):
QNetworkRequest request;
request.setRawHeader("Authorization", "Bearer token123");
manager->get(request):ml-citation{ref="3" data="citationList"}。
8. 设置请求头
如果你需要设置请求头(例如,设置Content-Type
为application/json
):
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
8. 同步阻塞网络请求
QEventLoop在接收网络返回内容结束之前,一直阻塞等待。
#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QEventLoop>
#include <QDebug>struct TestA {int data; // 示例数据// 其他字段
};class NetworkManager : public QObject {Q_OBJECTpublic:NetworkManager(QObject* parent = nullptr) : QObject(parent) {manager = new QNetworkAccessManager(this);}TestA getTestA() {QEventLoop loop;TestA result;// 发起网络请求QNetworkRequest request(QUrl("http://www.example.com"));QNetworkReply* reply = manager->get(request);// 连接槽函数解析数据connect(reply, &QNetworkReply::finished, [&]() {if (reply->error() == QNetworkReply::NoError) {QByteArray response = reply->readAll();result = parseResponse(response);} else {qWarning() << "Network error:" << reply->errorString();}reply->deleteLater();loop.quit();});// 阻塞等待网络请求完成loop.exec();return result;}private:QNetworkAccessManager* manager;TestA parseResponse(const QByteArray& response) {TestA parsedData;// 假设解析为整数数据parsedData.data = QString(response).toInt();return parsedData;}
};
#include <QCoreApplication>int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);NetworkManager networkManager;TestA data = networkManager.getTestA();qDebug() << "Received data:" << data.data;return a.exec();
}
9. 异步非阻塞网络请求
通过设置回调函数,将网络请求应答回调出去。
#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QDebug>
#include <functional>struct TestA {int data; // 示例数据// 其他字段
};class NetworkManager : public QObject {Q_OBJECTpublic:using Callback = std::function<void(const TestA&)>;NetworkManager(QObject* parent = nullptr) : QObject(parent) {manager = new QNetworkAccessManager(this);}void getTestA(const Callback& callback) {// 发起网络请求QNetworkRequest request(QUrl("http://www.example.com"));QNetworkReply* reply = manager->get(request);// 连接槽函数解析数据connect(reply, &QNetworkReply::finished, this, [this, reply, callback]() {TestA result;if (reply->error() == QNetworkReply::NoError) {QByteArray response = reply->readAll();result = parseResponse(response);} else {qWarning() << "Network error:" << reply->errorString();}reply->deleteLater();callback(result);});}private:QNetworkAccessManager* manager;TestA parseResponse(const QByteArray& response) {TestA parsedData;// 假设解析为整数数据parsedData.data = QString(response).toInt();return parsedData;}
};
#include <QCoreApplication>void handleResult(const TestA& data) {qDebug() << "Received data:" << data.data;QCoreApplication::quit();
}int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);NetworkManager networkManager;networkManager.getTestA(handleResult);return a.exec();
}