2017-12-16 3 views
1

Guten TagQt erhalten externe IP-Adresse mit QNetworkReply

Intro:

Meine Anwendung erfordert die externe IP-Adresse bekommen und es mit einer intern gewonnenen Adresse übereinstimmt, so dass die Anwendung fortzufahren.

Dazu verwende ich eine QNetworkAccessManager und QNetworkReply für diesen Zweck.

Mein Code wurde unter Verwendung this Beispiel als eine Referenz gebaut.

Was habe ich versucht:

eine externe IP-Erwerb von der ipify API, indem sie ein JSON-Objekt durchgeführt werden.

bestätigte ich diese durch:

curl "https://api.ipify.org?format=json"

die wiederum mit meiner aktuellen IP-Adresse im Format antwortet:

{"ip":"255.255.255.255"}

, die ein JSONObject ist. Damit habe ich den folgenden Code erstellt.

Problem:

Das Problem ist ganz einfach, bekomme ich keine Antwort. Die post Anfrage wird ausgeführt, aber es wird einfach keine Antwort (oder finished) Signal ausgelöst.

  • POST ->GET Anfrage

ich den Code für eine get Anfrage geändert haben, da dies diese keine Antwort Problem gelöst, auf this thread gefunden.

Ich tat dies, indem die gesamte URL mit Abfrage-Parametern in der URL angeben:

QNetworkRequest request(QUrl("https://api.ipify.org?format=json")); 

einschließlich Header Content-Typ und Größe (wie im Beispiel unten schließlich den anruf QNetworkAccessManager::get() mit:

replyExternalAddress = networkManager->get(request); 

aber das gab auch keine Antwort.

ich dachte, dass es etwas klein ist, dass ich fehle, aber ich kann einfach nicht sehen.

Beratung?


-Code zur Abfrage externer IP:

// public callable method, starting network request 
void APICommunicator::requestExternalAddress(){ 
    qInfo(apicommunicator) << "Requesting external IP address from ipify.org"; 

    // creates network request 
    // specifies "format=json" 
    QUrlQuery postData; 
    postData.addQueryItem("format", "json"); 
    QByteArray encodedQuery = postData.toString(QUrl::FullyEncoded).toUtf8(); 
    QNetworkRequest request(QUrl("https://api.ipify.org")); 

    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); 
    request.setHeader(QNetworkRequest::ContentLengthHeader, QString::number(encodedQuery.size())); 

    // creates merged URL from URL and query items and sends a post: 
    // https://api.ipify.org?format=json 
    replyExternalAddress = networkManager->post(request, encodedQuery); 

    // Creates QMetaObject::Connection connection for finished signal from QNetworkReply 
    conExternalAddress = QObject::connect(replyExternalAddress, SIGNAL(finished()), this, SLOT(externalAddressResponse())); 

    // attach error listener to reply 
    addErrorListener(replyExternalAddress, conExternalAddress); 


} 

void APICommunicator::externalAddressResponse(){ 
    qDebug(apicommunicator) << "External Address response recieved"; 

    // disconnect signals 
    QObject::disconnect(conExternalAddress); 
    QObject::disconnect(conErrorListener); 

    // read all output from JSon object 
    QByteArray ba = replyExternalAddress->readAll(); 

    // delete QNetworkReply 
    replyExternalAddress->deleteLater(); 

    LogMessageHandler::writeToApiLog(QString("\n\nCALL EXTERNAL [" + replyExternalAddress->request().url().toString() + "]\n" + QString(ba))); 

    QJsonObject doc = QJsonDocument::fromJson(ba).object(); 
    QString ip = doc.value("ip").toString();  
    QHostAddress address = QHostAddress(); 

    if (ip.isEmpty()) { 
     qWarning(apicommunicator) << "External Address: no data received"; 
    } 
    else { 
     address = QHostAddress(version); 
    } 

    // replies with address to external slot (in main application) 
    emit ExternalAddressReply(address); 
} 

Antwort

1

Das Problem ist, dass Sie eine POST Anfrage senden, während ipify.org nur GET Anfragen erwartet. Sie scheinen das Missverständnis zu haben, dass Sie eine POST Anfrage senden müssen, um Parameter (format=json) zusammen mit Ihrer Anfrage senden zu können, das ist nicht wahr. In Ihrem Code senden Sie die Parameter als POST Daten, das ist die gleiche Technik, die verwendet wird, wenn Sie ein Webformular in Ihrem Browser senden (weil Sie den Inhaltstypheader auf application/x-www-form-urlencoded festlegen).

Sie müssen nicht unbedingt die Anfrage eines Webbrowsers imitieren ein Formular senden, um in der Lage sein, mit der API ipify.org bietet. ipify.org bietet eine viel einfachere Schnittstelle; Sie müssen nur Ihre Abfragezeichenfolge in Ihrer Abrufanforderung senden. Qt macht den Job noch einfacher, indem es die Klasse QUrlQuery bereitstellt, die eine Möglichkeit zum Erstellen von URL-Abfragen bietet. Hier ist ein funktionierendes Beispiel:

#include <QtCore> 
#include <QtNetwork> 

int main(int argc, char *argv[]) { 
    QCoreApplication a(argc, argv); 

    QNetworkAccessManager networkManager; 

    QUrl url("https://api.ipify.org"); 
    //the query used to add the parameter "format=json" to the request 
    QUrlQuery query; 
    query.addQueryItem("format", "json"); 
    //set the query on the url 
    url.setQuery(query); 

    //make a *get* request using the above url 
    QNetworkReply* reply = networkManager.get(QNetworkRequest(url)); 

    QObject::connect(reply, &QNetworkReply::finished, 
        [&](){ 
     if(reply->error() != QNetworkReply::NoError) { 
      //failure 
      qDebug() << "error: " << reply->error(); 
     } else { //success 
      //parse the json reply to extract the IP address 
      QJsonObject jsonObject= QJsonDocument::fromJson(reply->readAll()).object(); 
      QHostAddress ip(jsonObject["ip"].toString()); 
      //do whatever you want with the ip 
      qDebug() << "external ip: " << ip; 
     } 
     //delete reply later to prevent memory leak 
     reply->deleteLater(); 
     a.quit(); 
    }); 
    return a.exec(); 
} 
+0

Ich habe versucht, bekommen, aber ich habe eine vollständige URL mit der Abfrage in der URL erstellt. Warum sollte das nicht funktionieren? – KGCybeX

+0

@KGCybeX, gut, etwas wie [das] (https://pastebin.com/DvmWDpPH) funktioniert perfekt für mich. Ich denke, dass das Problem, das Sie hatten, mit etwas anderem in Ihrem Code zusammenhängt. – Mike

+0

in jedem Fall, vielen Dank für die Mühe, die Frage zu beantworten. Ich werde die Lösung anwenden und Feedback geben – KGCybeX