Results 1 to 20 of 47

Thread: QTcpSocket readyRead strange behavior

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: QTcpSocket readyRead strange behavior

    Your code in the first post does NOT wait for the expected size:
    Qt Code:
    1. qint64 nBytes = pSocket->bytesAvailable(); //you check bytes available
    2.  
    3. qDebug()<<"onSocketReadyRead bytes="<<nBytes;
    4.  
    5. if (nBytes < 2) // it could be you get 0 or 1 bytes, so you get out here. But lets say you got 3, so we go on.
    6. return;
    7. qDebug()<<"Bytes="<<nBytes;
    8. pSocket->peek((char*)&sSize, 2);//why do you use peek and not bytesAvailable? also, why do you peel only 2 bytes ahead? it will alway be at most 2 bytes this the following if will always get out.
    9.  
    10. qDebug()<<"Packet size="<<sSize;
    11.  
    12. if (sSize != 19998) //so we didn't read 19998, (sSize will be at most 2 because of the peek) which is the size you are waiting for, so we get in to the if.
    13. {
    14. QMessageBox::critical(NULL, tr("error"), tr("This is it"));
    15. pSocket->disconnectFromHost();
    16. return; //And what do you do? you get out!!
    17. }
    18.  
    19. if (nBytes < 2 + sSize)
    20. {
    21. qDebug()<<" not enough data in stream";
    22. return;
    23. }
    To copy to clipboard, switch view to plain text mode 

    EDIT:
    Qt Code:
    1. if (sSize != 19998)
    To copy to clipboard, switch view to plain text mode 
    is a tottaly a problem.
    Read the peek documentation and be sure to understand it.
    sSize should be a buffer, as long as the the data you want to read.
    It does not store the size read size, but the read data!
    If at all, you probably then use it like this:
    Qt Code:
    1. int iSize = peel(buff,maySize);
    2.  
    3. if(iSize != iExpectedSize){...}
    To copy to clipboard, switch view to plain text mode 
    Last edited by high_flyer; 19th January 2011 at 09:11.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  2. #2
    Join Date
    Nov 2010
    Posts
    28
    Thanks
    1
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTcpSocket readyRead strange behavior

    the buffer i want to stream contains:
    2 bytes, containing the size of the buffer
    rest of the buffer.
    in the final program, the size may differ from one packet to another, so i have to put it at the beginning of the send data.
    For my tests here, i put it at 19998.

    the goal is to read
    * the size (in the 2 first bytes)
    * then the buffer, corresponding to size just read
    then redo the same.

    here's my code with comments:

    Qt Code:
    1. void Client::onSocketReadyRead()
    2. {
    3. short sSize;
    4. char* data;
    5. unsigned long lPacketIndex;
    6. qint64 nBytes = pSocket->bytesAvailable();
    7.  
    8. qDebug()<<"onSocketReadyRead bytes="<<nBytes;
    9.  
    10. if (nBytes < 2) //we haven't read enough data to get the buffer size, return
    11. return;
    12. qDebug()<<"Bytes="<<nBytes;
    13. pSocket->peek((char*)&sSize, 2); //we read 2 bytes, we get the size of the buffer INSIDE these 2 bytes
    14. //here i use peek to get the 2 bytes containing the size, without removing it from the buffer, because i may have not enough data, and i'll have to redo it.
    15.  
    16. qDebug()<<"Packet size="<<sSize;
    17. /* this IF is only to get easily the error . It's DEBUG code.
    18.   as i KNOW the size must be 19998, if it's not, there was an error.
    19. */
    20. if (sSize != 19998)
    21. {
    22. //i put a breakpoint here, the code stops.
    23. QMessageBox::critical(NULL, tr("error"), tr("This is it"));
    24. pSocket->disconnectFromHost();
    25. return;
    26. }
    27.  
    28. if (nBytes < 2 + sSize) //here we wait to have enough data to read sSize bytes
    29. {
    30. qDebug()<<" not enough data in stream";
    31. return;
    32. }
    33.  
    34. data = new char[sSize];
    35.  
    36. pSocket->read((char*)&sSize, 2);
    37. pSocket->read(data, sSize);
    38.  
    39. memcpy((char*)&lPacketIndex, data, 4);
    40.  
    41. qDebug()<<" data read, packet index="<<lPacketIndex;
    42.  
    43. delete data;
    44. }
    To copy to clipboard, switch view to plain text mode 

    is it clearer?

  3. #3
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: QTcpSocket readyRead strange behavior

    wysota gave you the solution, why don't you use it?
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  4. #4
    Join Date
    Nov 2010
    Posts
    28
    Thanks
    1
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTcpSocket readyRead strange behavior

    I have answrered : i've exactly the same problem with wysota's solution.

    As i already said, it works well for a certain time, then it randomly fail. In addition, it does not fail in a "good" network with no TCP retransmission, and often fails in a "bad" network, like low wifi.

    well, i'll use directly windows sockets.
    Last edited by naroin; 19th January 2011 at 10:10.

  5. #5
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QTcpSocket readyRead strange behavior

    Can we see the code for the sender? Also are the sender and the receiver running the same operating system and the same CPU type?
    Last edited by wysota; 19th January 2011 at 10:37.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  6. #6
    Join Date
    Nov 2010
    Posts
    28
    Thanks
    1
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTcpSocket readyRead strange behavior

    yes, they are both on windows,

    here's the server side code :
    Qt Code:
    1. #define DATA_SIZE 20000
    2.  
    3. Server::Server(QObject *parent) : QThread(parent)
    4. {
    5.  
    6. }
    7.  
    8. Server::~Server()
    9. {
    10.  
    11. }
    12.  
    13. void Server::run()
    14. {
    15. pServer = new QTcpServer();
    16. pMapperReadyRead = new QSignalMapper();
    17. pMapperDisconnected = new QSignalMapper();
    18. pMapperError = new QSignalMapper();
    19.  
    20. connect(pServer, SIGNAL(newConnection()), this, SLOT(onNewConnection()), Qt::DirectConnection);
    21. connect(pMapperReadyRead, SIGNAL(mapped(QObject*)), this, SLOT(onSocketReadyRead(QObject*)), Qt::DirectConnection);
    22. connect(pMapperDisconnected, SIGNAL(mapped(QObject*)), this, SLOT(onSocketDisconnected(QObject*)), Qt::DirectConnection);
    23.  
    24. pServer->listen(QHostAddress::Any, 1234);
    25.  
    26. //timer d'envoi
    27. lPacketIndex = 0;
    28. QTimer* pTimer = new QTimer(this);
    29. connect(pTimer, SIGNAL(timeout()), this, SLOT(onTimeout()));
    30.  
    31. pTimer->setSingleShot(false);
    32. pTimer->start(100);
    33.  
    34.  
    35.  
    36. exec();
    37.  
    38. pServer->close();
    39. delete pServer;
    40.  
    41. delete pMapperReadyRead;
    42. delete pMapperDisconnected;
    43. delete pMapperError;
    44. }
    45.  
    46. void Server::onNewConnection()
    47. {
    48. QTcpSocket* pSocket = pServer->nextPendingConnection();
    49. if (pSocket == NULL)
    50. return;
    51.  
    52. qDebug()<<"new connection";
    53.  
    54. vecClient.push_back(pSocket);
    55.  
    56. connect(pSocket, SIGNAL(readyRead()), pMapperReadyRead, SLOT(map()), Qt::DirectConnection);
    57. pMapperReadyRead->setMapping(pSocket, pSocket);
    58. connect(pSocket, SIGNAL(disconnected()), pMapperDisconnected, SLOT(map()), Qt::DirectConnection);
    59. pMapperDisconnected->setMapping(pSocket, pSocket);
    60. }
    61.  
    62. void Server::onSocketReadyRead( QObject* pObject )
    63. {
    64.  
    65. }
    66.  
    67. void Server::onSocketDisconnected( QObject* pObject )
    68. {
    69. int i;
    70. QTcpSocket* pSocket = (QTcpSocket*)pObject;
    71.  
    72. qDebug()<<"Socket disconnected";
    73.  
    74. for (i=0;i<vecClient.size();++i)
    75. {
    76. if (pSocket = vecClient[i])
    77. {
    78. vecClient.erase(vecClient.begin() + i);
    79. break;
    80. }
    81. }
    82.  
    83. pSocket->deleteLater();
    84. }
    85.  
    86. void Server::onSocketError( QObject* pObject, QAbstractSocket::SocketError error )
    87. {
    88. QTcpSocket* pSocket = (QTcpSocket*)pObject;
    89.  
    90. qDebug()<<"Socket error : "<<pSocket->errorString();
    91. }
    92.  
    93. void Server::onTimeout()
    94. {
    95. int i;
    96. char data[DATA_SIZE];
    97. short sSize = DATA_SIZE - 2;
    98.  
    99.  
    100. memset(data, 0, DATA_SIZE);
    101. memcpy(data, &sSize, 2);
    102. memcpy(data+2, &lPacketIndex, 4);
    103.  
    104. ++lPacketIndex;
    105.  
    106. for (i=0;i<vecClient.size();++i)
    107. {
    108. vecClient[i]->write(data, DATA_SIZE);
    109.  
    110. }
    111. }
    To copy to clipboard, switch view to plain text mode 

    i can also send you VC++ projects, if you need them

  7. #7
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QTcpSocket readyRead strange behavior

    This code is not compliant with what I have shown you. You have not implemented what I suggested so do that first and then we can continue.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  8. #8
    Join Date
    Nov 2010
    Posts
    28
    Thanks
    1
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTcpSocket readyRead strange behavior

    yeah, that's my server.

    the client connects to it, then the server regulary sends data (onTimeout)
    In my project, it's the server that pushes bytes in the socket.

    as you can see line 108 :
    Qt Code:
    1. vecClient[i]->write(data, DATA_SIZE);
    To copy to clipboard, switch view to plain text mode 

  9. #9
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QTcpSocket readyRead strange behavior

    You are sending raw bytes and interpreting them on the other end as integers. Don't do that. I told you to encode the size explicitly. If your sender is a 32 bit OS and your receiver a 64 bit OS (or the other way round) your code will fail immediately.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  10. #10
    Join Date
    Nov 2010
    Posts
    28
    Thanks
    1
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTcpSocket readyRead strange behavior

    you're totally right, but for this example, that's not the point : the code does not fail immediately.
    As i am on 2 32bits windows, it works.

    (does the size of "short" change between 32 and 64bit OS? i though it could be a problem only if the endianness changed)

  11. #11
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QTcpSocket readyRead strange behavior

    It is the point because it is this exact variable that is giving you an incorrect result. So first make sure the problem is not there (and not assume it is not there) and then continue elsewhere.

    This is sender side compatible with my previous suggestion.

    Qt Code:
    1. QByteArray data; // external byte array containing your data to be sent
    2.  
    3. quint16 s = data.size();
    4. QByteArray ba(2, 0);
    5. ba[0] = (s >> 8) & 0xFF;
    6. ba[1] = s & 0xFF;
    7. ba.append(data);
    8. for (i=0;i<vecClient.size();++i)
    9. {
    10. vecClient[i]->write(ba);
    11. }
    To copy to clipboard, switch view to plain text mode 
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  12. #12
    Join Date
    Nov 2010
    Posts
    28
    Thanks
    1
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTcpSocket readyRead strange behavior

    i've got the same problem.

    receiver side code :
    Qt Code:
    1. void Client::onSocketReadyRead()
    2. {
    3. bufferSocket += pSocket->readAll();
    4.  
    5. while (bufferSocket.size() >= 2)
    6. {
    7. quint16 size = (bufferSocket.at(0) << 8) + bufferSocket.at(1); // 16bit unsigned value
    8.  
    9. qDebug()<<"size="<<size;
    10.  
    11. if (size != 19998)
    12. {
    13.  
    14. QMessageBox::critical(NULL, tr("error"), tr("This is it"));
    15. pSocket->disconnectFromHost();
    16. return;
    17. }
    18.  
    19. if(bufferSocket.size() <= 2+size) return;
    20.  
    21. qDebug()<<"data read";
    22.  
    23. QByteArray data = bufferSocket.mid(2, size);
    24.  
    25. bufferSocket.remove(0,2+size);
    26. }
    To copy to clipboard, switch view to plain text mode 

    sender side code:
    Qt Code:
    1. void Server::onTimeout()
    2. {
    3. QByteArray data;
    4. int i;
    5.  
    6. data.fill(1, 19998);
    7.  
    8. quint16 s = data.size();
    9. QByteArray ba(2, 0);
    10. ba[0] = (s >> 8) & 0xFF;
    11. ba[1] = s & 0xFF;
    12. ba.append(data);
    13. for (i=0;i<vecClient.size();++i)
    14. {
    15. vecClient[i]->write(ba);
    16. }
    17. }
    To copy to clipboard, switch view to plain text mode 

  13. #13
    Join Date
    Jan 2006
    Location
    Belgium
    Posts
    1,938
    Thanked 268 Times in 268 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows
    Wiki edits
    20

    Default Re: QTcpSocket readyRead strange behavior

    Note that the slot you call from the thread is not performed inside the thread.

  14. #14
    Join Date
    Aug 2009
    Location
    Belgium
    Posts
    310
    Thanks
    10
    Thanked 31 Times in 25 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTcpSocket readyRead strange behavior

    Hi,
    You could look at the fortunecookie server and client examples.

    In that example the length of the "packet" is put upfront. On the receiving side, the length is read, and they keep on receiving until all the bytes are received. This is what you want.

    It is best to see a TCP connection as a 'stream' of bytes that are coming in. You have to find the start and end of your 'message' yourself.

    Best regards,
    Marc

  15. #15
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QTcpSocket readyRead strange behavior

    Quote Originally Posted by marcvanriet View Post
    In that example the length of the "packet" is put upfront. On the receiving side, the length is read, and they keep on receiving until all the bytes are received. This is what you want.
    That's exactly what he has, you know
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  16. #16
    Join Date
    Aug 2009
    Location
    Belgium
    Posts
    310
    Thanks
    10
    Thanked 31 Times in 25 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTcpSocket readyRead strange behavior

    Oops... didn't go to the very last page of this thread. Well, better safe then sorry...

Similar Threads

  1. QtcpSocket readyRead Problem with Java Client
    By Bernie in forum Qt Programming
    Replies: 6
    Last Post: 12th February 2011, 11:59
  2. QTcpSocket and readyRead and QTimer
    By cafu in forum Qt Programming
    Replies: 2
    Last Post: 18th December 2009, 13:36
  3. Question in readyRead(QTCPSOCKET)
    By morgana in forum Qt Programming
    Replies: 2
    Last Post: 24th July 2008, 18:11
  4. QTcpSocket readyRead and buffer size
    By pdoria in forum Qt Programming
    Replies: 4
    Last Post: 2nd February 2008, 10:11
  5. Strange QTcpSocket behavior (debugged with Ethereal)
    By mdecandia in forum Qt Programming
    Replies: 23
    Last Post: 28th May 2007, 20:44

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.