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

[SOLVED] reading data in QTCPsocket is incomplete

Scheduled Pinned Locked Moved General and Desktop
14 Posts 3 Posters 9.4k 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.
  • M Offline
    M Offline
    Marty
    wrote on last edited by
    #1

    hi !

    i am trying to have my data read correctly over TCP for days and i can't make it work !

    i send a command like "COP01" and i am supposed to get this a s a response :

    @COP01
    ~MSG~My message
    @CV@

    but i get only

    @COP01@

    I am using readyRead() signal along with a slot where i do a simple

    @qDebug() << socket->readAll();@

    Note : when i use telnet in a terminal and send the command manually, i get the right answer.

    I also tried some mixed solutions like using .atEnd(), canReadLine() and other tricks i grabbed on internet and had a look on Fortune example from Qt... but with no success at all !

    can you tell me how you manage reading messages over TCP ?

    Thank you very much

    1 Reply Last reply
    0
    • 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