QNetworkAccessManager永远不会发出finished()信号 [英] QNetworkAccessManager never emits finished() signal
问题描述
我正在为一个项目的模块工作,其中HTTP GET请求用于检索一些XML数据,然后将其转换为另一种格式并发送到子系统。
I'm working on a module for a project where HTTP GET requests are used to retrieve some XML data, which is then converted to another format and send to a sub-system.
我到目前为止编写的代码如下:
The code I have written so far is below:
CMakeLists.txt:
project(HttpDemo)
cmake_minimum_required(VERSION 2.8)
set(CMAKE_BUILD_TYPE Debug)
#find_package(Qt5Widgets)
find_package(Qt5Core)
find_package(Qt5Network)
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
aux_source_directory(. SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST})
qt5_use_modules(${PROJECT_NAME} Core Network) #Gui Widgets
main.cpp
#include <QtCore>
#include <QtNetwork>
class HttpHandler : public QObject
{
Q_OBJECT
public:
HttpHandler(QObject* parent=Q_NULLPTR) : QObject(parent)
{
QObject::connect(&nm, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
qDebug() << QSslSocket::sslLibraryBuildVersionString();
}
private:
QNetworkAccessManager nm;
public slots:
void post(QString urlLink)
{
QUrl url(urlLink);
QNetworkRequest request(url);
QSslConfiguration sslConf;
sslConf.setProtocol(QSsl::SslV3);
request.setSslConfiguration(sslConf);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencded");
QUrlQuery query;
query.addQueryItem("client_id", "1234");
query.addQueryItem("code", "abcd");
QUrl params;
params.setQuery(query);
nm.post(request, params.toEncoded());
}
void get(QString urlLink)
{
QUrl url(urlLink);
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
nm.get(request);
}
void replyFinished(QNetworkReply* reply)
{
QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
if(statusCode.isValid())
{
// Print or catch the status code
QString status = statusCode.toString(); // or status_code.toInt();
qDebug() << status;
qDebug() << QString::fromStdString(reply->readAll().toStdString());
}
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
HttpHandler hh;
hh.get("SOME_URL");
return a.exec();
}
#include "main.moc"
With SOME_URL
我尝试了很多链接,所有这些链接都没有任何问题,比如说Firefox的 Http Requester 插件。我得到:
With SOME_URL
I have tried a lot of links all of which work without any issues in let's say the Http Requester addon for Firefox. I get:
OpenSSL 1.0.1j 2014年10月15日
"OpenSSL 1.0.1j 15 Oct 2014"
qt .network.ssl:QSslSocket:无法解析SSLv2_client_method
qt.network.ssl: QSslSocket: cannot resolve SSLv2_client_method
qt.network.ssl:QSslSocket:无法解析SSLv2_server_method
qt.network.ssl: QSslSocket: cannot resolve SSLv2_server_method
根据称为互联网的权威机构,这应该不是问题。有一件事是肯定的 - 我的 replyFinished(QNetworkReply *)
插槽虽然连接到 finished()$ c $但不会被触发c>
QNetworkAccessManager
的信号。这意味着无论发出信号的原因是什么。将 QSslConfiguration
更改为其他 QSsl :: SslProtocol
对结果没有影响。
According to the authority called the Internet this shouldn't be a problem. One thing's for certain - my replyFinished(QNetworkReply*)
slot doesn't get triggered although it is connected to the finished()
signal of the QNetworkAccessManager
. This means that whatever the reason the signal is not emitted. Changing the QSslConfiguration
to a different QSsl::SslProtocol
doesn't make a difference in the outcome.
更新(根据评论中的要求):
UPDATE (as requested in the comments):
以下代码使用 readyRead()
并动态分配回复。结果 - 与上述相同。
Following code uses readyRead()
and dynamically allocated reply. The result - same as above.
#include <QtCore>
#include <QtNetwork>
class HttpHandler : public QObject
{
Q_OBJECT
public:
HttpHandler(QObject* parent=Q_NULLPTR) : QObject(parent)
{
qDebug() << QSslSocket::sslLibraryBuildVersionString();
this->manager = new QNetworkAccessManager(this);
this->reply = Q_NULLPTR;
}
private:
QNetworkAccessManager* manager;
QNetworkReply* reply;
signals:
void finished();
public slots:
void post(QString urlLink)
{
QUrl url(urlLink);
QNetworkRequest request(url);
QSslConfiguration sslConf;
sslConf.setProtocol(QSsl::SslV2);
request.setSslConfiguration(sslConf);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QUrlQuery query;
query.addQueryItem("client_id", "1234");
query.addQueryItem("code", "abcd");
QUrl params;
params.setQuery(query);
manager->post(request, params.toEncoded());
}
void get(QString urlLink)
{
QUrl url(urlLink);
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
this->reply = manager->get(request);
QObject::connect(reply, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
}
void slotReadyRead()
{
qDebug() << "Hello"; // I never land here
}
void replyFinished(QNetworkReply* reply)
{
QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
if(statusCode.isValid())
{
QString status = statusCode.toString(); // or status_code.toInt();
qDebug() << status;
qDebug() << QString::fromStdString(reply->readAll().toStdString());
}
emit finished();
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
HttpHandler *hh = new HttpHandler(&a);
QObject::connect(hh, SIGNAL(finished()), &a, SLOT(quit()));
hh->get("http://httpbin.org/ip"); // or any other httpbin.org endpoint
return a.exec();
}
#include "main.moc"
更新2:
我刚发现 Qt文档中的示例。下载,编译和运行的东西 - 相同的错误,但它的工作原理。
I just found an example in the Qt documentation. Downloaded, compiled and ran the thing - same error but it works.
推荐答案
问题已解决(见here )。基本上问题是公司的代理。我的一位同事给了它一个镜头并用HTTPS取代了HTTP(即使链接是HTTP),它突然起作用了。然后它打动了我们 - 公司的代理缓存HTTP(并做其他事情),这导致巨大的延迟,如果超时容限足够小 QNetworkAccessManager
将返回套接字超时。
Issue resolved (see here). Basically the problem was the company's proxy. A colleague of mine gave it a shot and replaced the HTTP with HTTPS (even though the link is HTTP) and it worked all of a sudden. Then it struck us - the company's proxy caches HTTP (and does other things too), which leads to huge delays and if the timeout tolerance is small enough QNetworkAccessManager
will return a socket timeout.
使用 QNetworkProxyFactory :: setUseSystemConfiguration(true)
以不会使您的应用程序的方式启用代理取决于代码中的配置,而不是系统的配置。
Using QNetworkProxyFactory::setUseSystemConfiguration(true)
enables the proxy in a way that doesn't make your application dependent on a configuration in your code but rather the configuration of the system.
这篇关于QNetworkAccessManager永远不会发出finished()信号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!