Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Qtcpsocket read large data from server



  • Hi everyone

    I have a qtcpsocket client that I want it to receive a black and white png from a server. The server is written in another language and have checked it with another client and it works fine but the client written in qt, doesn't receive the current data size. I send around 53258 bytes but the client, each time receives different amount, from 4000 to 16000. Here is my qt code:

    socket = new QTcpSocket();
    socket->connectToHost(Address, Port.toUShort());
    if(socket->waitForConnected(3000))
    {
         qDebug()<< "connected";
         emit connected();
    }
    
    socket->write("Sendmethedata\n");
    socket->waitForBytesWritten(1000);
    socket->waitForReadyRead(3000);
    QByteArray document2 = socket->readAll();
    qDebug()<<document2.length();
    

    Any suggestions?


  • Moderators

    You should wait and collect the data in a loop (or better - use the async API). Qt sockets will report data ready for reading as soon as it gets a proper chunk of it - which is not necessarily the whole file that the server is sending. Then it will emit readyRead() again when next part of data is received etc. So you need to keep reading from the socket until the whole file is ready.

    BTW. If your server is a HTTP/ HTTPS server, you can also use QNetworkAccessManager to get the file more easily.



  • @sierdzio Can you give me an example please.



  • I tried to make 5 second sleep and it read the data correctly, but is there better way that writing a delay in the thread?



  • @PouryaTorabi I Change the delay to 1 MilliSecond and it still works (-:


  • Lifetime Qt Champion

    @PouryaTorabi You should not use sleep or waitFor in the main thread. Use proper Signals&Slots, see for example here: https://doc.qt.io/Qt-5/qtnetwork-fortuneclient-example.html

    Regards



  • @aha_1980 As you know waitForReadyRead is a signal so I am using signal slot, but the problem is the waitForReadyRead as @sierdzio mentioned, will be emited when the first byte is available, so I need to give some time to my client to receive all data, besides my client is in another thread which is different from Main thread, so would there be any problem?


  • Lifetime Qt Champion

    @PouryaTorabi said in Qtcpsocket read large data from server:

    As you know waitForReadyRead is a signal so I am using signal slot

    No, that is wrong. readyRead() is a signal. waitForReadyRead() is a blocking function and that causes your problems.

    You should really take a look at the example I linked above.

    Regards



  • @PouryaTorabi
    Do what @sierdzio & @aha_1980 are telling you:

    1. Get rid of any call to waitForReadyRead() (and also to waitForBytesWritten(), you don't need it). Do not put any sleep() in.

    2. Hook to the readyRead() signal and read the bytes from the socket there, e.g. via https://doc.qt.io/qt-5/qiodevice.html#readAll. Each time that is called there will be some new bytes arrived, but do not assume it will be all the bytes you are waiting for. You have to keep reading & accumulating when bytes arrive till the desired number have arrived. You may find that https://doc.qt.io/qt-5/qdatastream.html#startTransaction etc. helps you with this.

    3. When all the necessary data has been received, emit a signal or whatever to start acting on the data.

    Since you will now by using asynchronous socket calls instead of synchronous ones, you do not need to have a separate thread to handle the socket I/O --- your Qt GUI will not be blocked anyway. I do not know whether you have good reason to be using a separate thread in any case, if you do you will probably want to send a signal from that thread to your main thread when all the data has arrived so that the main thread can then handle the data.


Log in to reply