Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. problem with QLocalSocket sending continues data to QLocalServer
QtWS25 Last Chance

problem with QLocalSocket sending continues data to QLocalServer

Scheduled Pinned Locked Moved Solved General and Desktop
qlocalsocketqlocalserverreadyread
14 Posts 4 Posters 2.7k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • V Offline
    V Offline
    Venkateswaran
    wrote on 30 Oct 2020, 14:47 last edited by
    #1

    I'm trying to send some data from QLocalSocket to QLocalSever in a loop. Sever only gets the first data and not receiving subsequent data, but if I introduce 1 mec delay between each call from the client then the server starts to receive everything. Please check out the below Client & Server code.

    client.cpp

    #include "client.h"
    #include "QDataStream"
    #include <QTest>
    
    TestClient::TestClient() : m_socket{new QLocalSocket(this)}{
        m_socket->connectToServer("TestServer");
        if (m_socket->waitForConnected(1000)) {
          qDebug("socket Connected!");
        }
        connect(m_socket, &QLocalSocket::readyRead, this, &TestClient::onNewData);
    }
    
    void TestClient::onNewData() {
        qCritical() << "data received from server";
    }
    
    void TestClient::sendDataToServer() {
        QByteArray block;
        QDataStream out(&block, QIODevice::WriteOnly);
        out.setVersion(QDataStream::Qt_5_10);
        QString testString = "test data";
        out << quint32(testString.size());
        out << testString;
        m_socket->write(block);
        m_socket->flush();
    }
    
    void TestClient::startClient() {
        for(int i = 0; i < 5; i++) {
            //QTest::qWait(1); //works if I uncomment this line
            sendDataToServer();
        }
    }
    

    server.cpp

    #include "server.h"
    
    TestServer::TestServer() : m_server{new QLocalServer(this)} {
        QLocalServer::removeServer("TestServer");
        if (!m_server->listen("TestServer")) {
            qCritical() << "couldn't connect to server";
        }
        connect(m_server, &QLocalServer::newConnection, this, &TestServer::onNewConnection);
    }
    
    void TestServer::onNewConnection() {
        m_socket = m_server->nextPendingConnection();
        connect(m_socket, &QLocalSocket::readyRead, this,
                &TestServer::onNewData);
        connect(m_socket, &QLocalSocket::disconnected, m_socket,
                &QLocalSocket::deleteLater);
    }
    
    void TestServer::onNewData() {
        QLocalSocket* client = qobject_cast<QLocalSocket*>(sender());
        client->readAll();
        qCritical() << "data read by server";
    }
    

    from the qt doc, it's stated that

    readyRead() is not emitted recursively; if you reenter the event loop or call waitForReadyRead() inside a slot connected to the readyRead() signal, the signal will not be reemitted (although waitForReadyRead() may still return true).

    so is this my problem? adding timer is the only solution here?

    You can compile this test project -> testsocket

    J 1 Reply Last reply 30 Oct 2020, 14:55
    0
    • C Offline
      C Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on 30 Oct 2020, 14:53 last edited by
      #2

      All is fine - you get all data with one readyRead signal / readAll() call.

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      1 Reply Last reply
      2
      • V Venkateswaran
        30 Oct 2020, 14:47

        I'm trying to send some data from QLocalSocket to QLocalSever in a loop. Sever only gets the first data and not receiving subsequent data, but if I introduce 1 mec delay between each call from the client then the server starts to receive everything. Please check out the below Client & Server code.

        client.cpp

        #include "client.h"
        #include "QDataStream"
        #include <QTest>
        
        TestClient::TestClient() : m_socket{new QLocalSocket(this)}{
            m_socket->connectToServer("TestServer");
            if (m_socket->waitForConnected(1000)) {
              qDebug("socket Connected!");
            }
            connect(m_socket, &QLocalSocket::readyRead, this, &TestClient::onNewData);
        }
        
        void TestClient::onNewData() {
            qCritical() << "data received from server";
        }
        
        void TestClient::sendDataToServer() {
            QByteArray block;
            QDataStream out(&block, QIODevice::WriteOnly);
            out.setVersion(QDataStream::Qt_5_10);
            QString testString = "test data";
            out << quint32(testString.size());
            out << testString;
            m_socket->write(block);
            m_socket->flush();
        }
        
        void TestClient::startClient() {
            for(int i = 0; i < 5; i++) {
                //QTest::qWait(1); //works if I uncomment this line
                sendDataToServer();
            }
        }
        

        server.cpp

        #include "server.h"
        
        TestServer::TestServer() : m_server{new QLocalServer(this)} {
            QLocalServer::removeServer("TestServer");
            if (!m_server->listen("TestServer")) {
                qCritical() << "couldn't connect to server";
            }
            connect(m_server, &QLocalServer::newConnection, this, &TestServer::onNewConnection);
        }
        
        void TestServer::onNewConnection() {
            m_socket = m_server->nextPendingConnection();
            connect(m_socket, &QLocalSocket::readyRead, this,
                    &TestServer::onNewData);
            connect(m_socket, &QLocalSocket::disconnected, m_socket,
                    &QLocalSocket::deleteLater);
        }
        
        void TestServer::onNewData() {
            QLocalSocket* client = qobject_cast<QLocalSocket*>(sender());
            client->readAll();
            qCritical() << "data read by server";
        }
        

        from the qt doc, it's stated that

        readyRead() is not emitted recursively; if you reenter the event loop or call waitForReadyRead() inside a slot connected to the readyRead() signal, the signal will not be reemitted (although waitForReadyRead() may still return true).

        so is this my problem? adding timer is the only solution here?

        You can compile this test project -> testsocket

        J Offline
        J Offline
        JonB
        wrote on 30 Oct 2020, 14:55 last edited by JonB
        #3

        @Venkateswaran said in problem with QLocalSocket sending continues data to QLocalServer:

        Sever only gets the first data and not receiving subsequent data,

        How are you sure? You do not debug out the content/length of client->readAll();, so you don't know. My guess is: you assume a readAll() or onNewData signal correspond one-to-one with write/flish from client. But they don't. Your "1 msec delay" will make that true, probably, which is why you think you need that. You don't.

        V 1 Reply Last reply 30 Oct 2020, 14:57
        1
        • J JonB
          30 Oct 2020, 14:55

          @Venkateswaran said in problem with QLocalSocket sending continues data to QLocalServer:

          Sever only gets the first data and not receiving subsequent data,

          How are you sure? You do not debug out the content/length of client->readAll();, so you don't know. My guess is: you assume a readAll() or onNewData signal correspond one-to-one with write/flish from client. But they don't. Your "1 msec delay" will make that true, probably, which is why you think you need that. You don't.

          V Offline
          V Offline
          Venkateswaran
          wrote on 30 Oct 2020, 14:57 last edited by
          #4

          @JonB yes I thought it's a one-to-one relationship. if I write 5 from client-side then I will get 5 readyRead signals.

          C J 2 Replies Last reply 30 Oct 2020, 14:58
          0
          • V Venkateswaran
            30 Oct 2020, 14:57

            @JonB yes I thought it's a one-to-one relationship. if I write 5 from client-side then I will get 5 readyRead signals.

            C Offline
            C Offline
            Christian Ehrlicher
            Lifetime Qt Champion
            wrote on 30 Oct 2020, 14:58 last edited by Christian Ehrlicher
            #5

            @Venkateswaran Why? It's a stream with no further protocol. It can even happen that you get a readyRead signal for every single byte you sent.

            Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
            Visit the Qt Academy at https://academy.qt.io/catalog

            1 Reply Last reply
            1
            • V Venkateswaran
              30 Oct 2020, 14:57

              @JonB yes I thought it's a one-to-one relationship. if I write 5 from client-side then I will get 5 readyRead signals.

              J Offline
              J Offline
              JonB
              wrote on 30 Oct 2020, 15:00 last edited by JonB
              #6

              @Venkateswaran
              And it absolutely is not! :)

              • readyRead fires when there is at least 1 byte available.
              • readAll reads all that happens to be there when it is called. Anything ranging from 0 bytes to every byte sent!
              • readyRead won't fire again till you've done a readAll.

              That's it. No one-to-one. Your job to buffer received data at receiver, or split it up, if that's what you want to do.

              V V 3 Replies Last reply 30 Oct 2020, 15:08
              0
              • J JonB
                30 Oct 2020, 15:00

                @Venkateswaran
                And it absolutely is not! :)

                • readyRead fires when there is at least 1 byte available.
                • readAll reads all that happens to be there when it is called. Anything ranging from 0 bytes to every byte sent!
                • readyRead won't fire again till you've done a readAll.

                That's it. No one-to-one. Your job to buffer received data at receiver, or split it up, if that's what you want to do.

                V Offline
                V Offline
                Venkateswaran
                wrote on 30 Oct 2020, 15:08 last edited by
                #7

                @JonB Thanks for clarifying this. Now I have another problem, on the server-side, I need to call another function with received test string from the client. I have tested the readAll() and as you said I'm receiving 130 bytes all at once (which is 5 times my test string). So how do I separate on server-side? I'm using QDataStream on client-side to send data and is there an elegant way to decouple the received bytes at server-side with QDataStream? maybe its a really basic question but it would be helpful for me if you show some example.

                J 1 Reply Last reply 30 Oct 2020, 15:15
                0
                • V Venkateswaran
                  30 Oct 2020, 15:08

                  @JonB Thanks for clarifying this. Now I have another problem, on the server-side, I need to call another function with received test string from the client. I have tested the readAll() and as you said I'm receiving 130 bytes all at once (which is 5 times my test string). So how do I separate on server-side? I'm using QDataStream on client-side to send data and is there an elegant way to decouple the received bytes at server-side with QDataStream? maybe its a really basic question but it would be helpful for me if you show some example.

                  J Offline
                  J Offline
                  JonB
                  wrote on 30 Oct 2020, 15:15 last edited by JonB
                  #8

                  @Venkateswaran
                  Start by: have you read (and understood!) all the detail in https://doc.qt.io/qt-5/qdatastream.html#details ? And do look at subsection https://doc.qt.io/qt-5/qdatastream.html#using-read-transactions, because you may be looking for that.

                  How is the client sending? ("I'm using QDataStream on client-side to send data" --- with just which calls on what data object types?) If you are using QDataStream at client send you will want QDataStream at server receive. And just btw: when you talk sometimes about "bytes" and sometimes about "string" do you indeed want QDataStream or did you maybe want QTextStream?

                  1 Reply Last reply
                  2
                  • J JonB
                    30 Oct 2020, 15:00

                    @Venkateswaran
                    And it absolutely is not! :)

                    • readyRead fires when there is at least 1 byte available.
                    • readAll reads all that happens to be there when it is called. Anything ranging from 0 bytes to every byte sent!
                    • readyRead won't fire again till you've done a readAll.

                    That's it. No one-to-one. Your job to buffer received data at receiver, or split it up, if that's what you want to do.

                    V Offline
                    V Offline
                    Venkateswaran
                    wrote on 30 Oct 2020, 15:20 last edited by
                    #9

                    @JonB also should i need to call m_socket->waitForBytesWritten(); at client side ?

                    J 1 Reply Last reply 30 Oct 2020, 15:24
                    0
                    • V Venkateswaran
                      30 Oct 2020, 15:20

                      @JonB also should i need to call m_socket->waitForBytesWritten(); at client side ?

                      J Offline
                      J Offline
                      JonB
                      wrote on 30 Oct 2020, 15:24 last edited by
                      #10

                      @Venkateswaran
                      Nope :) Not unless you want to, it just stops client proceeding to the next line of code till bytes are written. But it makes no difference to the protocol/behaviour. And no effect at server-side.

                      V 1 Reply Last reply 30 Oct 2020, 15:31
                      0
                      • J JonB
                        30 Oct 2020, 15:24

                        @Venkateswaran
                        Nope :) Not unless you want to, it just stops client proceeding to the next line of code till bytes are written. But it makes no difference to the protocol/behaviour. And no effect at server-side.

                        V Offline
                        V Offline
                        Venkateswaran
                        wrote on 30 Oct 2020, 15:31 last edited by
                        #11

                        @JonB Thanks for the information. I want to send Boolean, Number, String from the client so DataStream would be the right one.
                        This is how I'm sending data from the client :

                        void TestClient::sendDataToServer() {
                            QByteArray block;
                            QDataStream out(&block, QIODevice::WriteOnly);
                            out.setVersion(QDataStream::Qt_5_10);
                            QString testString = "test data";
                            out << quint32(testString.size());
                            out << testString;
                            m_socket->write(block);
                            m_socket->flush();
                        }
                        

                        This is what I tried at the server side to receive data (and it work for this basic example).

                        void TestServer::onNewData() {
                            QLocalSocket* client = qobject_cast<QLocalSocket*>(sender());
                            qCritical() << "TestServer::onNewData" << client->bytesAvailable();
                            QDataStream in;
                            in.setDevice(client);
                            in.setVersion(QDataStream::Qt_5_10);
                            quint32 blockSize = 0;
                            QString test;
                        
                            while(client->bytesAvailable() > (int)sizeof(quint32)) {
                                in >> blockSize;
                                if (client->bytesAvailable() < blockSize || in.atEnd()) return;
                                in >> test;
                                qDebug() << test << "printing received value";
                            }
                            qCritical() << "data read by server";
                        }
                        

                        But looks like This Answer has a nice example to start with

                        J 1 Reply Last reply 30 Oct 2020, 15:33
                        0
                        • V Venkateswaran
                          30 Oct 2020, 15:31

                          @JonB Thanks for the information. I want to send Boolean, Number, String from the client so DataStream would be the right one.
                          This is how I'm sending data from the client :

                          void TestClient::sendDataToServer() {
                              QByteArray block;
                              QDataStream out(&block, QIODevice::WriteOnly);
                              out.setVersion(QDataStream::Qt_5_10);
                              QString testString = "test data";
                              out << quint32(testString.size());
                              out << testString;
                              m_socket->write(block);
                              m_socket->flush();
                          }
                          

                          This is what I tried at the server side to receive data (and it work for this basic example).

                          void TestServer::onNewData() {
                              QLocalSocket* client = qobject_cast<QLocalSocket*>(sender());
                              qCritical() << "TestServer::onNewData" << client->bytesAvailable();
                              QDataStream in;
                              in.setDevice(client);
                              in.setVersion(QDataStream::Qt_5_10);
                              quint32 blockSize = 0;
                              QString test;
                          
                              while(client->bytesAvailable() > (int)sizeof(quint32)) {
                                  in >> blockSize;
                                  if (client->bytesAvailable() < blockSize || in.atEnd()) return;
                                  in >> test;
                                  qDebug() << test << "printing received value";
                              }
                              qCritical() << "data read by server";
                          }
                          

                          But looks like This Answer has a nice example to start with

                          J Offline
                          J Offline
                          JonB
                          wrote on 30 Oct 2020, 15:33 last edited by JonB
                          #12

                          @Venkateswaran
                          Note that the link you reference (by @VRonin) uses the transactions I suggested earlier: https://doc.qt.io/qt-5/qdatastream.html#using-read-transactions. No bytesAvailable() or buffering. Up to you.

                          1 Reply Last reply
                          3
                          • J JonB
                            30 Oct 2020, 15:00

                            @Venkateswaran
                            And it absolutely is not! :)

                            • readyRead fires when there is at least 1 byte available.
                            • readAll reads all that happens to be there when it is called. Anything ranging from 0 bytes to every byte sent!
                            • readyRead won't fire again till you've done a readAll.

                            That's it. No one-to-one. Your job to buffer received data at receiver, or split it up, if that's what you want to do.

                            V Offline
                            V Offline
                            VRonin
                            wrote on 30 Oct 2020, 16:22 last edited by
                            #13

                            @JonB said in problem with QLocalSocket sending continues data to QLocalServer:

                            readyRead won't fire again till you've done a readAll.

                            This is not correct. From https://doc.qt.io/qt-5/qabstractsocket.html

                            The readyRead() signal is emitted every time a new chunk of data has arrived.

                            So it doesn't care whether you read the data or not


                            I suggest having a look at this article it uses QTcpSocket but the code is exactly the same for QLocalSocket. I'd focus on the ChatClient::onReadyRead method and its explanation below

                            "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                            ~Napoleon Bonaparte

                            On a crusade to banish setIndexWidget() from the holy land of Qt

                            J 1 Reply Last reply 30 Oct 2020, 17:05
                            3
                            • V VRonin
                              30 Oct 2020, 16:22

                              @JonB said in problem with QLocalSocket sending continues data to QLocalServer:

                              readyRead won't fire again till you've done a readAll.

                              This is not correct. From https://doc.qt.io/qt-5/qabstractsocket.html

                              The readyRead() signal is emitted every time a new chunk of data has arrived.

                              So it doesn't care whether you read the data or not


                              I suggest having a look at this article it uses QTcpSocket but the code is exactly the same for QLocalSocket. I'd focus on the ChatClient::onReadyRead method and its explanation below

                              J Offline
                              J Offline
                              JonB
                              wrote on 30 Oct 2020, 17:05 last edited by
                              #14

                              @VRonin said in problem with QLocalSocket sending continues data to QLocalServer:

                              This is not correct.

                              Damn, and sorry! I thought that it had said that, but not. I may have confused with

                              readyRead() is not emitted recursively; if you reenter the event loop or call waitForReadyRead() inside a slot connected to the readyRead() signal, the signal will not be reemitted (although waitForReadyRead() may still return true).

                              1 Reply Last reply
                              0

                              2/14

                              30 Oct 2020, 14:53

                              topic:navigator.unread, 12
                              • Login

                              • Login or register to search.
                              2 out of 14
                              • First post
                                2/14
                                Last post
                              0
                              • Categories
                              • Recent
                              • Tags
                              • Popular
                              • Users
                              • Groups
                              • Search
                              • Get Qt Extensions
                              • Unsolved