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. [SOLVED] reading data in QTCPsocket is incomplete
Forum Updated to NodeBB v4.3 + New Features

[SOLVED] reading data in QTCPsocket is incomplete

Scheduled Pinned Locked Moved General and Desktop
14 Posts 3 Posters 9.6k Views 1 Watching
  • 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.
  • Q Offline
    Q Offline
    qxoz
    wrote on last edited by
    #2

    That is because your message sended not as one TCP packet but several. Ready read called when received any new packet. For solving this issue you need implement some kind of top level protocol where you know start of message and when you got complete data. For example you can use json like structure where you know start and end, or use some start identifier and length of data. All depends from your requirements.

    1 Reply Last reply
    0
    • IamSumitI Offline
      IamSumitI Offline
      IamSumit
      wrote on last edited by
      #3

      Hello Marty,
      When you write your data on socket you use socket->write() function.
      It returns no of bytes written to a socket if your data is written completely then there is no problem on writing side.
      Check it out using qDebug().

      Be Cute

      1 Reply Last reply
      0
      • M Offline
        M Offline
        Marty
        wrote on last edited by
        #4

        Hi and thank you for your suggestions !

        the thing is :

        • the server is a device and i don't have much information about the TCP message format for the answer. The only thing i know is the response message is composed of :

        • the command the device received + EOL (CR/LF)

        • the answer to the query, here this is the message stored in memory + EOL (CR/LF)

        • state of execution (valid or not) + EOL (CR/LF)

        it would be great if the device sends the message size in the TCP frame but i don't have this information.

        So i don't know how to be sure i read all data !

        I will try to get the number of bytes written to the device as suggested.

        Could the EOL (CR/LF) be a problem when reveiving TCP packets ?
        How can i handle this ?

        thanks a lot

        1 Reply Last reply
        0
        • Q Offline
          Q Offline
          qxoz
          wrote on last edited by
          #5

          [quote author="Marty" date="1392894981"]

          • the command the device received + EOL (CR/LF)
          • the answer to the query, here this is the message stored in memory + EOL (CR/LF)
          • state of execution (valid or not) + EOL (CR/LF)
            [/quote]
            You already have enough information. Just wait until you receive all three parts of message which are ends with EOL.
          1 Reply Last reply
          0
          • M Offline
            M Offline
            Marty
            wrote on last edited by
            #6

            how would you write this part ?

            because in the documentation it says the response always ends with "@ + first letter of the command sent + state (like V for valid or E for error) + EOL".
            I tried to detect the character "@" yesterday just for a test purpose but my app froze like in infinite loop while waiting for that character that never arrives.

            Also, why when i send the command with telnet in a terminal i get the entire answer. How does telnet know when it gets the entire response ?

            thanks again

            1 Reply Last reply
            0
            • IamSumitI Offline
              IamSumitI Offline
              IamSumit
              wrote on last edited by
              #7

              @OK your server is a device ,the information you only know the composition of message as response from the server .
              Your problem is you are not getting full data from the server(Which is unknown to you) .
              You can use QQueue data structure -

              QQueue <QByteArray>Queue; (in .h file)

              QBytearray data=pSocket->readAll();
              qDebug() << "Data From Client : " << "\n\n" <<data;
              Queue.enqueue(data);

              while(!Queue.isEmpty())
              {
              QString str=Queue.dequeue();
              QString str=data;

                  qdebug() << str ;
                     str.clear();
              

              }
              try it

              Be Cute

              1 Reply Last reply
              0
              • Q Offline
                Q Offline
                qxoz
                wrote on last edited by
                #8

                Use Wireshark, so you can see what exactly happening(what data sends by device) in network.
                And as IamSumit wrote using QQueue is good solution.

                1 Reply Last reply
                0
                • Q Offline
                  Q Offline
                  qxoz
                  wrote on last edited by
                  #9

                  By the way
                  can you show code how do you doing it?

                  1 Reply Last reply
                  0
                  • M Offline
                    M Offline
                    Marty
                    wrote on last edited by
                    #10

                    yep. will have a look to QQueue.

                    here is some code.

                    When i clic a button :

                    @void ledBar::getStoredMessage(int bank)
                    {
                    QString message;
                    if (bank < 10)
                    {
                    message = sendQuery("COP0" + QString::number(bank) + "\r\n");
                    }
                    else
                    {
                    message = sendQuery("COP" + QString::number(bank) + "\r\n");
                    }
                    qDebug() << message;
                    }@

                    The sendQuery() Method :

                    @void TCPClient::sendQuery(QByteArray query)
                    {
                    if (socket->state() != QAbstractSocket::ConnectedState)
                    {
                    qWarning() << "Can't send command : not connected !";
                    }
                    else
                    {
                    socket->write(query)
                    }
                    }
                    @

                    then my readYread() slot :

                    @void TCPClient::readyRead()
                    {
                    if(socket->waitForBytesWritten(2000) && socket->waitForReadyRead((2000)))
                    {
                    timer->start(timeout);
                    return socket->readAll();
                    }
                    }@

                    1 Reply Last reply
                    0
                    • Q Offline
                      Q Offline
                      qxoz
                      wrote on last edited by
                      #11

                      Is your code compiled ok?
                      Anyway, let's change your code in following way:
                      Add some buffer variables in your class
                      @private:
                      //....
                      QString responseTempalte;
                      QByteArray incommingData;
                      bool isDataComplete;
                      //....@
                      change getStoredMessage(int bank)
                      @void ledBar::getStoredMessage(int bank)
                      {
                      QString message = QStringLiteral("COP%1\r\n").arg(bank, 2, 10, QChar('0'));
                      responseTempalte = QStringLiteral("@%1%2\r\n").arg(message.at(0));
                      incommingData.clear();
                      isDataComplete = false;
                      sendQuery(message.toLatin1());
                      qDebug() << message;
                      }@
                      and most important part, readyRead slot
                      @void TCPClient::readyRead()
                      {
                      incommingData.append(socket->readAll());
                      if(incommingData.contains(responseTempalte.arg("V")) ||
                      incommingData.contains(responseTempalte.arg("E")) )
                      {
                      isDataComplete = true;//or emit some signal
                      }
                      }@
                      something like that, i hope didn't forget something important.

                      1 Reply Last reply
                      0
                      • M Offline
                        M Offline
                        Marty
                        wrote on last edited by
                        #12

                        Great i will give it a try !

                        maybe the best is, if you have time, to have a look at the whole project :

                        https://github.com/martialgallorini/ledManager

                        thanks a lot

                        1 Reply Last reply
                        0
                        • M Offline
                          M Offline
                          Marty
                          wrote on last edited by
                          #13

                          humm... can't make it to work

                          program without change compile and run well (except truncated TCP response)

                          i have applied the changes you suggested. It compiles ok, but when clic on send command button it freezes then close then crashes the app

                          1 Reply Last reply
                          0
                          • M Offline
                            M Offline
                            Marty
                            wrote on last edited by
                            #14

                            Well i figured it out but i don't understand why !

                            With

                            [CODE]socket->readLine();[/CODE]

                            it reads each complete line.

                            I tried everything (read(), readAll()...) and NOTHING but readLine() works !
                            If anybody has a clue why readAll() does'nt make it here...

                            [CODE]
                            void TCPClient::readyRead()
                            {
                            if(socket->waitForReadyRead(2000))
                            {
                            QString resp;
                            while(socket->bytesAvailable() > 0)
                            {
                            resp.append(socket->readLine());
                            }
                            emit sigTcpDataReceived(resp.toUtf8());
                            }
                            else
                            {
                            qWarning() << "Waiting for data to read timed out. No data received !";
                            }
                            }
                            [/CODE]

                            Thank you very much to everybody and for your help !

                            1 Reply Last reply
                            0

                            • Login

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