QNetworkAccessManager correct stack/heap handling for QByteArray and QNetworkRequest



  • Hi,

    ich habe das schon im Qt Forum gepostet aber noch keine Antwort erhalten, deswegen versuche ich es hier nochmal.

    Falls jemand das Englisch abschrecken sollte aber Erfahrungen mit Qt-Network hat dann schreib ich es gerne nochmal in Deutsch hin.

    Gruß

    I am a little bit confused about the send NetworkRequest functions of the QNetworkAccessManager.
    Sadly I have only the DLL's so I can not jump into the declaration of e.g. get, post, head etc. to see what exactly happens.

    I am new in Network programming in Qt so I had a look at some sides and some tutorials and it looks like every tutorial makes it different and even the Qt function documentation is open for interpretation.

    In the official Qt tutorial I saw this.

    void HttpWindow::startRequest(QUrl url){
        reply = qnam.get(QNetworkRequest(url));
    }
    

    So I saw this and thought ok the NetworkRequest is put on stack and the *.get() Function will create a copy of that and send it to the server because the stack object is destroyed after startRequest function is finished and the chance is high that in get function is a thread launched so that start request function is not blocking.

    But in another tutorial I saw this:

    void sendRequest(){
        // create custom temporary event loop on stack
        QEventLoop eventLoop;
    
        // "quit()" the event-loop, when the network request "finished()"
        QNetworkAccessManager mgr;
        QObject::connect(&mgr, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));
    
        // the HTTP request
        QNetworkRequest req( QUrl( QString("http://ip.jsontest.com/") ) );
        QNetworkReply *reply = mgr.get(req);
        eventLoop.exec(); // blocks stack until "finished()" has been called
    
        if (reply->error() == QNetworkReply::NoError) {
            //success
            qDebug() << "Success" <<reply->readAll();
            delete reply;
       }
    }
    

    Additional to that I saw the function description of ::sendCustomRequest() which states that if data is not empty, data must be open for reading and must remain valid until finished() signal is emitted.
    The same description is not written e.g. for QNetworkAccessManager::post() but this has the same function signature so also takes a const QByteArray & data.
    Is in the post case the data copied and in the sendCustomRequest() not or it is also necessary for the post request that QByteArray remains valid?

    My Questions:

    1.how does send functions work internally?
    2. What is the correct design to send requests (Must QNetworkRequest and QByteArray remain valid until slot function: replyFinished(QNetworkReply*) is called? That means do I have to put them on the heap or on stack in a "higher" level?



  • Das ist fast schon ein Implementierungsdetail. Du kannst übrigens jederzeit selber in den Code schauen, z.B. auf github.
    Hab grad in meinen 4.8er Stand geschaut. Wenn du QNetworkAccessManager::post mit dem QByteArray und nicht dem QIODevice Parameter aufrufst, erstellt der einen QBuffer und ruft dann die andere Überladung auf. Der QBuffer im ReadOnly Modus sollte das QByteArray kopieren (Copy on write, keine Deep Copy).
    Da das alles aber nicht wirklich spezifiziert ist (und ich würds auch nicht so genau spezifizieren), kann sich das irgendwann einfach ändern. Man muss also evtl. aufpassen.
    Notfalls würde ich bei eine Funktion, die eine Referenz bekommt, dafür sorgen, dass die Referenz gültig bleibt, und mich nicht darauf verlassen, dass die Funktion eine Kopie macht.

    Und grundsätzlich würde ich bei Qt schon empfehlen, sich den Source zu holen und sie selber zu bauen. Je nachdem, wie kompliziert das was man macht ist, kann die Qt ziemlich verbuggt sein oder sich komisch verhalten. Wir haben in der Arbeit schon ziemlich in Qt gefixt oder umgebaut/angepasst und erweitert. Und man muss sehr oft einfach mal reindebuggen und zu schauen, was da wirklich passiert. So als Blackbox funktioniert das nur für Hello World.



  • Ok, vielen Dank hat mir sehr geholfen.

    Ich werde mich dann mal am Wochenende mit qmake und den build scripten beschäftigen.


Anmelden zum Antworten