本文主要介绍qt在网络编程方面的应用方法

1. QNetworkAccessManager(核心管理器)

核心功能:
  • 发送 HTTP/HTTPS/FTP 等请求(GET/POST/PUT/DELETE 等);
  • 管理网络配置(代理、Cookie、SSL 证书、超时);
  • 复用网络连接(避免频繁创建连接)。
常用 API:
方法 作用
QNetworkReply* get(QNetworkRequest) 发送 GET 请求(获取资源);
QNetworkReply* post(QNetworkRequest, QByteArray) 发送 POST 请求(提交数据,如表单、JSON);
QNetworkReply* put(...) 发送 PUT 请求(更新资源);
void setProxy(QNetworkProxy) 设置网络代理(如 HTTP 代理、SOCKS5);
QNetworkCookieJar* cookieJar() 获取 / 设置 Cookie 容器(管理会话 Cookie);
关键注意:
  • 一个程序建议只创建一个 QNetworkAccessManager 实例(多实例会浪费连接资源);
  • 所有请求都是异步的,永远不要在主线程阻塞等待(除非用 QEventLoop 临时测试)。

2. QNetworkRequest(请求配置)

核心功能:
  • 封装请求的 URL、请求头、超时、缓存策略、SSL 配置等。
常用 API:
方法 作用
setUrl(QUrl) 设置请求的目标 URL(必选);
setHeader(QNetworkRequest::KnownHeaders, QVariant) 设置标准请求头(如 User-Agent、Content-Type);
setRawHeader(QByteArray, QByteArray) 设置自定义请求头(如 Token: xxx);
setTransferTimeout(int msec) 设置请求超时时间(毫秒);
setSslConfiguration(QSslConfiguration) 设置 HTTPS 证书配置(忽略证书错误、自定义证书);
示例(POST JSON 配置):
1
2
3
4
5
QNetworkRequest request(QUrl("https://api.example.com/post"));
// 设置 Content-Type 为 JSON
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
// 设置自定义 Token
request.setRawHeader("Authorization", "Bearer xxxxxx");

3. QNetworkReply(响应处理)

核心功能:
  • 代表一个请求的响应,通过信号槽通知状态变化,提供响应数据 / 错误信息。
核心信号(异步处理关键):
信号 作用
finished() 请求完成(成功 / 失败都会触发);
errorOccurred(QNetworkReply::NetworkError) 请求出错(如网络断开、404、500);
readyRead() 有响应数据可读取(分批接收大数据时用,如下载文件);
downloadProgress(qint64 bytesReceived, qint64 bytesTotal) 下载进度(文件下载时显示进度条);
常用 API:
方法 作用
readAll() 读取所有响应数据(小数据用,如接口返回的 JSON);
read(qint64 maxSize) 读取指定长度数据(大数据分批读取);
error() 获取错误码(NoError 表示无错误);
errorString() 获取错误描述(如 “Connection refused”);
attribute(QNetworkRequest::Attribute) 获取响应属性(如 HTTP 状态码、重定向 URL);
header(QNetworkRequest::KnownHeaders) 获取响应头(如 Content-Length、Content-Type);

实战:异步 POST 请求(JSON 提交)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <QMainWindow>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QJsonObject>
#include <QDebug>

class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) {
// 1. 创建全局 QNAM(类成员,避免局部销毁)
qnam = new QNetworkAccessManager(this);

// 2. 构建 POST 请求(JSON 数据)
QNetworkRequest request(QUrl("https://httpbin.org/post"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
request.setTransferTimeout(5000);

// 构建 JSON 数据
QJsonObject json;
json["name"] = "Qt";
json["version"] = "6.6";
QByteArray postData = QJsonDocument(json).toJson(QJsonDocument::Compact);

// 3. 发送 POST 请求
QNetworkReply *reply = qnam->post(request, postData);

// 4. 异步监听响应
// 监听完成信号
connect(reply, &QNetworkReply::finished, this, [=]() {
if (reply->error() == QNetworkReply::NoError) {
// 成功:解析响应
QByteArray data = reply->readAll();
QJsonDocument doc = QJsonDocument::fromJson(data);
qDebug() << "POST 响应 JSON:" << doc.toJson();
// 获取 HTTP 状态码
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
qDebug() << "HTTP 状态码:" << statusCode;
} else {
// 失败:打印错误
qDebug() << "POST 错误:" << reply->errorString();
}
reply->deleteLater(); // 必须释放 reply 资源
});

// 监听错误信号(可选,和 finished 里判断 error 二选一)
connect(reply, &QNetworkReply::errorOccurred, this, [=](QNetworkReply::NetworkError code) {
qDebug() << "请求错误码:" << code << ",描述:" << reply->errorString();
});
}

private:
QNetworkAccessManager *qnam; // 类成员,全局复用
};

关键注意事项

  1. 资源释放QNetworkReply 必须调用 deleteLater() 释放(不能直接 delete,否则可能导致崩溃);
  2. 异步特性:所有请求都是异步的,不能在主线程阻塞等待(如 sleep),必须用信号槽处理结果
  3. HTTPS 证书:默认情况下,Qt 会验证 HTTPS 证书,若证书无效(如自签名),请求会失败;可通过 QSslConfiguration 忽略证书错误(仅测试用,生产环境需配置合法证书):cpp运行
1
2
3
QSslConfiguration config = QSslConfiguration::defaultConfiguration();
config.setPeerVerifyMode(QSslSocket::VerifyNone); // 忽略证书验证
request.setSslConfiguration(config);
  1. 大数据下载:若下载大文件(如图片、视频),不要用 readAll(),应在 readyRead() 信号中分批读取数据并写入文件:
1
2
3
4
5
6
7
connect(reply, &QNetworkReply::readyRead, this, [=]() {
QFile file("download.bin");
if (file.open(QIODevice::Append)) {
file.write(reply->readAll());
file.close();
}
});
  1. QNAM 生命周期QNetworkAccessManager 应作为全局对象(如类成员),避免频繁创建 / 销毁(否则会丢失 Cookie、断开持久连接)。

总结

一句话核心用法
QNetworkAccessManager 全局单例,调用 get()/post() 发送请求,返回 QNetworkReply
QNetworkRequest 配置 URL、请求头、超时等参数,作为 get()/post() 的入参;
QNetworkReply 监听 finished()/errorOccurred() 信号,读取响应数据 / 错误信息,最后 deleteLater()

Qt 网络模块的核心是 “异步非阻塞”,所有请求结果都通过信号槽处理,这是和传统同步网络请求的最大区别,也是 Qt 网络编程的核心原则。