Please nominate your Qt Champions for 2021!

[SOLVED] QWebSocketServer: strange behaviour

  • Hallo.

    I have derived my Websocket server from the example .

    However, I see some strange behaviour:

    • the user authenticates himself with an auth message
    • this message is parsed correctly
    • then the user sends his first normal message to the chat
    • this first normal message can not be parsed as the previous auth message is prepended to this normal message
    • the debug output of the first chat message arriving at the server is:
    "{"action":"auth","data":{"username":"testchat1","password":"test1"}}{"action":"msg","data":{"channelid":"3","msg":"message testchat1"}}"
     WebSocket Server Error:  ""

    As you see, the auth message is prepended to the "normal" message as if it were buffered on the chat server. I tried to intercept any WebSocket Server Error with m_pWebSocketServer->errorString() , but there seems to be no error.
    This happens only once, the next chat message is parsed correctly and nothing is prepended to it.
    My executable is compiled with msvc13 and runs under Win 8.

    Things get worse if I move to Ubuntu and compile with g++ 4.9.1. Then it seems that the auth message is always bufffered and a normal message is never processed/parsed as only the unintentionally buffered auth message is parsed each time I send a "normal" chat message.

    Because of this difference between OS and compilers I do think the reason lies within Qt and not on the client side which is a simple javacript client.

    Just to give you some idea of my code:

    void ChatServer::onNewConnection()
        QWebSocket *pSocket = m_pWebSocketServer->nextPendingConnection();
        connect(pSocket, &QWebSocket::textMessageReceived, this, &ChatServer::processJsonString);
        connect(pSocket, &QWebSocket::disconnected, this, &ChatServer::socketDisconnected);
       m_clients << pSocket;
    void ChatServer::processJsonString(const QString &jsonstring)
        qDebug()<<"processJsonString called";
        QWebSocket *pSender = qobject_cast<QWebSocket*>(sender());
        QJsonObject dataObject = QJsonDocument::fromJson(jsonstring.toUtf8()).object();
     //switch (dataObject.value("action").toString()[0].toLatin1()){
       // case 'a':
        if (dataObject.value("action").toString()=="auth")
            qDebug()<< "auth";
            QString password=dataObject.value("data").toObject().value("password").toString();
            QString username=dataObject.value("data").toObject().value("username").toString();
            //quint64 userID=dataObject.value("data").toObject().value("userID").toInt();
            qDebug()<<"password: " << password;
            qDebug()<<"username: " <<username;
            //qDebug()<<"userID: " <<userID;
            rc=new RestConn(username , password, apiToken, baseUrl, pSender);
           connect(rc,&RestConn::gotAuthJSONReply, this, &ChatServer::processAUTH);
     // case 'm':
        if (dataObject.value("action").toString()=="msg")
           // qDebug()<< "msg: " << dataObject.value("data").toString()<< "channelid: " <<dataObject.value("channelid").toInt();
          qDebug()<< "msg: "  << jsonstring ; //<< "\n";
            quint64 userID=userWebsockets->value(pSender, 0); // 0 is SYSTEM's userID
           quint64 channelID=dataObject.value("data").toObject().value("channelid").toString().toInt();
             qDebug()<< "msg: channelid: "  <<channelID ; // << "\n";
            QString message=dataObject.value("data").toObject().value("msg").toString();
            qDebug()<< "msg: message: "  << message<< "\n";
            QString serverTime= QDateTime::currentDateTime().toString(Qt::ISODate);  // check if ISO or compliant to Postgres date/time types
           // incmsg
            if (channels->value(channelID, NULL)==NULL) // ?????????
                 pSender->sendTextMessage("{ action: 'msg',status: 'error', data: {id: '2', msg: 'Request parse error'} }" );
            pSender->sendTextMessage("{ action: 'msg',status: 'ok',data: {} }" );
    //        //json_object('{senderID, author, receiverID, message, channel, time}'
    //        // remove receiverID, leave only channel ID  !!!!!!!!
            QString stringToInsert=QString::number(userID) % "," % QString::number(messageCounter)% ","  % message % ","
                    % QString::number(channelID) % "," % serverTime;
           // break;
         qDebug()<< jsonstring<<"\n" <<"WebSocket Server Error: " << m_pWebSocketServer->errorString() << "\n";

    So what is this? A bug?

  • Ok, just solved it through trial and error.

    Had a messy QEventLoop and another place, which, however, was used during auth parsing.
    Now it looks like this:

     QNetworkAccessManager nam;
            QEventLoop loop;     
            connect(&nam, &QNetworkAccessManager::finished, this, &RestConn::processReply);
             loop.connect(&nam, SIGNAL(finished(QNetworkReply*)),&loop, SLOT(quit()));

    And before - in the error case - the last two lines did not follow in correct order as they were:

    // This order is not correct
     loop.connect(&nam, SIGNAL(finished(QNetworkReply*)),&loop, SLOT(quit()));

    Thanks to all anyway.