QNetworkAccessManager需复用、QNetworkRequest须显式配置Content-Type与URL、QNetworkReply必须连接finished信号并检查error()后调用deleteLater,超时需手动通过QTimer实现。

直接用 QNetworkAccessManager 发起 HTTP 请求本身不难,难的是发得稳、收得准、不出内存泄漏、不卡 UI、不漏错误。它不是“调个函数就完事”的工具,而是一套需要明确生命周期和协作关系的组件系统。
QNetworkAccessManager 必须复用,不能每次请求都 new
很多人一上来就写 new QNetworkAccessManager() 放在槽函数里,点一次按钮建一个 manager —— 这会导致连接池失效、DNS 缓存丢弃、Cookie 无法共享、SSL 会话复用失败,还可能引发隐式线程竞争。
- 全局或类成员变量持有单例(推荐):比如在
MainWindow或业务模块中作为成员变量初始化一次 - 绝对避免在临时作用域(如按钮点击槽)里
new+deleteLater()管理:QNetworkAccessManager的析构会强行中断所有未完成请求,且无法保证 reply 已正确清理 - Qt 6 中它已默认支持多线程,但依然要求 manager 实例跨线程安全使用时走
moveToThread(),而非多实例
QNetworkRequest 配置必须显式设好 Content-Type 和 URL
尤其 POST/PUT 提交 JSON 时,Content-Type 不设或设错(比如漏掉 application/json),后端很可能直接返回 415 或静默丢弃请求。
将 WCAG 2 AA 无障碍标准应用于设计系统、UI 组件和网页——通过可运行的验证器进行对比度计算,采用设计 token 模式使颜色天生可访问,设定排版和焦点状态规则,并提供语义检查清单。适用于构建或审查 UI。
- GET 请求只需设置
QUrl,但建议额外调用request.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, false)关闭流水线(多数服务不支持,开了反而出错) - POST JSON 必须手动设置:
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json") - URL 中含中文或特殊字符,务必用
QUrl::toEncoded()或QUrl::fromPercentEncoding()处理,否则QNetworkAccessManager可能静默截断
QNetworkReply 的 finished 信号必须连,且 error() 必须检查
QNetworkReply 是一次性对象,finished 信号触发后,它内部状态就不可再用;不检查 error() 就直接 readAll(),大概率拿到空数据还误以为成功。
- 永远用
connect(reply, &QNetworkReply::finished, this, &MyClass::onReplyFinished),别用 lambda 捕获 reply 指针(容易悬垂) - 在槽函数里第一件事是判断
reply->error() == QNetworkReply::NoError,不是只看 HTTP 状态码 -
reply->attribute(QNetworkRequest::HttpStatusCodeAttribute)才是真正的 HTTP 状态码,reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute)是响应短语 - 读完数据后立即调用
reply->deleteLater(),否则对象常驻内存,尤其高频请求时迅速 OOM
超时必须自己加,QNetworkAccessManager 本身不提供超时机制
QNetworkAccessManager 没有内置超时参数,QNetworkRequest 的 setTransferTimeout() 是 Qt 6.3+ 新增、且仅对部分平台有效;Qt 5.x 和多数场景下,你得靠 QTimer 自己控。
- 发起请求后立刻启动单次定时器:
QTimer::singleShot(10000, reply, &QNetworkReply::abort) - 注意:abort() 后仍会触发
finished信号,所以槽函数里要先判reply->isFinished()再处理 - 不要依赖
QNetworkReply::timeoutError:这个枚举值存在,但 Qt 并不自动触发它,得你自己映射逻辑
最常被忽略的一点是:QNetworkReply 继承自 QIODevice,readAll() 调用后缓冲区即清空,想反复解析或调试打印,必须自己先把 QByteArray 保存下来。

















