一、HTTP 服务器实现方案
-
QtWebApp 集成
- 将QtWebApp源码的
httpserver
目录导入项目,并在.pro
文件中添加include ($$PWD/httpserver/httpserver.pri)
。 - 配置
WebApp.ini
文件定义服务参数(IP、端口、线程池等),通过HttpListener
类启动监听。 - 自定义
RequestMapper
类处理不同 URL 路径的请求,继承HttpRequestHandler
实现业务逻辑。 - 详细使用方法参考:QtWebApp - wuyuan2011woaini - 博客园
- 将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_OBJECT
public:
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_OBJECT
public:
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();
}