You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Qt控制台应用QNetworkAccessManager GET无流量,Wireshark无捕获

Qt访问ADAM设备请求失败的原因及修复

核心问题分析

  1. 阻塞式调用破坏异步流程
    QNetworkAccessManager是异步设计的,你在调用get()后立刻执行_replyPtr->waitForReadyRead(-1),这会阻塞当前线程。Qt的网络请求依赖事件循环处理收发逻辑,阻塞会导致请求根本无法发送,所以Wireshark捕获不到流量,finished槽也不会触发。此时读取HttpStatusCodeAttribute自然得不到200的结果。

  2. 多余请求头导致异常
    GET请求不需要设置Content-Type: application/x-www-form-urlencoded,这个头是针对POST表单提交场景的。多余的头可能让ADAM设备拒绝请求,或者触发Qt内部的请求校验逻辑异常。

  3. Reply销毁时机错误
    在请求未完成时就调用_replyPtr->deleteLater(),会导致Reply对象提前被销毁,进一步中断请求流程。

修复后的代码示例

初始化代码(保持不变)

_networkAccessManagerPtr = new QNetworkAccessManager(this);
connect(_networkAccessManagerPtr, SIGNAL(finished(QNetworkReply*)), this, SLOT(ReplyFinished(QNetworkReply*)), Qt::DirectConnection);

修改后的Get方法(异步方式)

bool TestClass::Get()
{
    // 简化URL拼接,避免多余的c_str()转换
    QString completeUrl = QString("http://%1:%2%3")
                          .arg(QString::fromStdString(_ipAddress))
                          .arg(_port)
                          .arg(QString::fromStdString(URL_LOGIN));

    QString auth = QString("%1:%2")
                   .arg(QString::fromStdString(_username))
                   .arg(QString::fromStdString(_password));

    QByteArray headerData = "Basic " + auth.toLocal8Bit().toBase64();

    QNetworkRequest request;
    request.setUrl(QUrl(completeUrl));
    // 移除多余的Content-Type头
    request.setRawHeader("Authorization", headerData);

    QNetworkReply *reply = _networkAccessManagerPtr->get(request);
    // 推荐用lambda直接绑定处理逻辑,也可以用原有的ReplyFinished槽
    connect(reply, &QNetworkReply::finished, this, [this, reply]() {
        if (reply->error() != QNetworkReply::NoError) {
            qWarning() << "ERROR:" << reply->errorString();
            _status = DeviceStatus::DEVICE_UNRESPONSIVE;
        } else {
            int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
            if (statusCode == 200) {
                _status = DeviceStatus::EVERYTHING_OK;
                // 读取返回的继电器状态数据
                QByteArray responseData = reply->readAll();
            } else {
                _status = DeviceStatus::DEVICE_UNRESPONSIVE;
                qDebug() << reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
            }
        }
        reply->deleteLater();
    });

    return true; // 返回true表示请求已成功发起,实际结果在回调中处理
}

关键注意事项

  • 确保调用Get()的线程(通常是主线程)正在运行事件循环,否则异步请求无法被处理。
  • 永远不要在Qt网络请求中混用异步API和waitForXXX阻塞方法,这会彻底打乱事件驱动的逻辑。
  • 用QString::arg()拼接字符串比多次调用append()更简洁,也能避免C++字符串与QString转换的潜在问题。

内容的提问来源于stack exchange,提问作者Jafuentes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 11:30:17