[Help] Async Client-Server protocol handling.



  • Hi,

    I'm trying to code an application that communicates with a server using JSON. I'm using QNetworkAccessManager and QxtJSON to accomplish that.

    I successfully established a connection and got response on any request I send, but now I need to add some logic to it.

    For instance, the connection protocol is something like this:

    @
    SEND: {"method": "startSession", "parameters": {}}
    RECEIVE: {"result": {"session":"123456789123465"}}

    SEND: {"method": "getToken", "parameters": { "session": "123456789123465" }}
    RECEIVE {"result": {"session": "123456789123465", "token": "ABCTOKENABC"}}

    SEND: {"method": "login", "parameters": { "session": "123456789123465", "token": "ABCTOKENABC", "user": "ivan", "pass": "somepass"}}
    RECEIVE {"result": {"loggedIn": "1"}}
    @

    There are basic methods to start a session and identify the client, and more advanced ones that require specifying information retrieved with the basic ones.

    The problem is that QNAM doesn't work synchroniously, so I can't wait until I got the session to request for the token, and can't wait to get the token to login.

    I wonder if any of you has experience in this issue and can point me in the right direccion. Maybe there are coding patterns for situations like this?



  • You can use a local event loop to fake the async QNAM operations into some synchronous mode:

    @
    QNetworkAccessManager *nam = new QNetworkAccessManager();
    QNetworkRequest req;
    // assemble your request here

    QNetworkReply *reply = nam->get(req);
    QEventLoop loop;
    connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
    loop.exec();
    @

    Code is memorized from some DevDays session, you might have to tweak it a bit.



  • I would try to avoid the trick Volker mentions. Instead, I would add additional information to your QNetworkReply instance that helps you to work with it in an asynchronic way.

    One way to do that, is to simply recognize that QNetworkReply is a QObject, and that QObject has a feature called dynamic properties. So you can simply do something like this:

    @
    //stole sample code from Volker above :-)
    QNetworkAccessManager *nam = new QNetworkAccessManager();
    QNetworkRequest req;
    // assemble your request here

    QNetworkReply *reply = nam->get(req);
    reply->setProperty("requestType", "startSession");
    //add any other data you may need
    @

    And then later, when the reply comes in, use it like this:
    @
    //method handing the QNAM reply:
    //reply is of type QNetworkReply again

    QString requestType = reply.property("requestType").toString();
    if (requestType == "startSession") {
    handleStartSessionReply(reply);
    } else if (requestType == "getToken") {
    handleGetTopenReply(reply);
    } // etc.
    @

    There are other ways of course, like keeping a hash like this:
    @
    QHash<QNetworkReply*, MyNetworkRequestDataStruct> m_networkRequestMetaData;
    @

    The MyNetworkRequestDataStruct can then include any metadata that you might want to keep around about your network request.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.