2017-10-12 144 views
1

我正在使用HTTP GET请求来检索某些XML数据,然后转换为其他格式并发送到子系统的项目的模块。QNetworkAccessManager永远不会发出finished()信号

到目前为止,我写的代码如下:

的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" 

随着SOME_URL我已经尝试了很多所有这些链接在没有任何问题的情况下运行,比如说Http Requester Firefox的插件。我得到:

“的OpenSSL 1.0.1j二○一四年十月一十五日”

qt.network.ssl:QSslSocket:无法解析SSLv2_client_method

qt.network.ssl:QSslSocket:无法解析SSLv2_server_method

根据称为互联网的权威,这应该不成问题。有一件事是确定的 - 我的replyFinished(QNetworkReply*)插槽不会被触发,尽管它连接到QNetworkAccessManagerfinished()信号。这意味着无论信号发出的原因如何。将QSslConfiguration更改为不同的QSsl::SslProtocol对结果没有影响。


UPDATE(的要求,在评论):

下面的代码使用readyRead()和动态分配的答复。结果 - 与上面相同。

#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:

我只是找到了一个example in the Qt documentation。下载,编译和运行的东西 - 同样的错误,但它的作品。

+0

难道你的OpenSsl库连接到Qt有问题吗? – Alex

+0

这是可能的,但我不知道如何“调试”这个问题。我已经读过,SSL库可以静态链接到Qt,这样你就可以发布自己的版本,但我不确定这会给我的工作带来多少工作。 – rbaleksandar

+0

你可以尝试看看'void sslErrors(QNetworkReply * reply,const QList &errors)',也许你可以找到一些东西?或者可能ar'NetworkError QNetworkReply :: error()const'? – Alex

回答

0

问题已解决(请参阅here)。基本上问题是公司的代理人。我的一位同事给了它一个镜头,并用HTTPS取代了HTTP(即使这个链接是HTTP),并且它突然发挥作用。然后它让我们感到震惊 - 该公司的代理缓存HTTP(并执行其他操作),这会导致巨大的延迟,并且如果超时容限足够小,则QNetworkAccessManager将返回套接字超时。

使用QNetworkProxyFactory::setUseSystemConfiguration(true)启用代理的方式不会使您的应用程序依赖于代码中的配置,而是系统的配置。

+0

很高兴听到您找到问题的原因。你可以通过解释你如何诊断它,特别是当别处看到这个问题时能够找出这个问题,从而使你的答案对未来的读者更有帮助。并且请用简要说明替换/增加该链接,以便您的答案本身完整;谢谢。 –