Results 1 to 12 of 12

Thread: QDataStream loses data over QTcpSocket?

  1. #1
    Join Date
    Feb 2006
    Location
    USA
    Posts
    142
    Thanks
    24
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows Android

    Default QDataStream loses data over QTcpSocket?

    This has been bugging me for a while... I'm attempting to send a QImage over a QDataStream (initialized over a QTcpSocket), and finding that it's a lot more difficult than I thought.

    I've verified that the QDataStream is functional (it is properly sending XML content over the wire and is received intact), and I verified that the image is not null when it is sent... but when I attempt to send over a QImage, I get nothing, or at worst, partial data. I've tried something as simple as this for the sender:
    Qt Code:
    1. QDataStream ds(&sock);
    2. ds << myImage;
    To copy to clipboard, switch view to plain text mode 
    ... with the receiver doing something as simple as this:
    Qt Code:
    1. QDataStream ds(&sock);
    2. ds >> myImage;
    To copy to clipboard, switch view to plain text mode 
    ... which results in a null image.

    I then tried to get fancy and use the rawData() functions to send the beast over:
    Qt Code:
    1. char *
    2. readRawData(char *buffer, QDataStream &ds, int length)
    3. {
    4. int bytesRead, bytesTotal(0);
    5. for(; bytesTotal < length; bytesTotal += bytesRead)
    6. {
    7. if((bytesRead = ds.readRawData(buffer + bytesTotal, length - bytesTotal)) == -1)
    8. {
    9. qFatal("%s:%s(%d) - failed to read raw data: %s", __FILE__, __FUNCTION__, __LINE__, ds.device()->errorString().toLocal8Bit().constData());
    10. }
    11. if(!bytesRead)
    12. {
    13. qFatal("%s:%s(%d) - broken connection while reading raw data", __FILE__, __FUNCTION__, __LINE__);
    14. }
    15. }
    16. return buffer;
    17. }
    18.  
    19. const char *
    20. writeRawData(const char *buffer, QDataStream &ds, int size)
    21. {
    22. int bytesWritten, bytesTotal(0);
    23. for(; bytesTotal < size; bytesTotal += bytesWritten)
    24. {
    25. if((bytesWritten = ds.writeRawData(buffer + bytesTotal, size - bytesTotal)) == -1)
    26. {
    27. qFatal("%s:%s(%d) - Failed to write raw bytes: %s", __FILE__, __FUNCTION__, __LINE__, ds.device()->errorString().toLocal8Bit().constData());
    28. }
    29. if(!bytesWritten)
    30. {
    31. qFatal("%s:%s(%d) - stream closed while writing raw data", __FILE__, __FUNCTION__, __LINE__);
    32. }
    33. }
    34. return buffer;
    35. }
    To copy to clipboard, switch view to plain text mode 
    ... which, when viewed in a debugger, shows that I get partial data - the size of the image is 1536000 bytes, and I get 196433 bytes when I do this (then it claims the stream was closed because it can't read anything further). What gives?
    Life without passion is death in disguise

  2. #2
    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: QDataStream loses data over QTcpSocket?

    Quote Originally Posted by KShots View Post
    What gives?
    Why did you expect to receive all data at once?
    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.


  3. #3
    Join Date
    Sep 2009
    Location
    UK
    Posts
    2,447
    Thanks
    6
    Thanked 348 Times in 333 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QDataStream loses data over QTcpSocket?

    You need to learn how TCP works - http://en.wikipedia.org/wiki/Transmi...ntrol_Protocol

    Then you will understand that you can't simply expect to send a chunk of data and receive it at the other side in one go.

    Preferably, you should packetise the data so you know more about whats happening during the transfer.

  4. #4
    Join Date
    Feb 2006
    Location
    USA
    Posts
    142
    Thanks
    24
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows Android

    Default Re: QDataStream loses data over QTcpSocket?

    Yes, I'm aware that I can't send it all in one shot - that's why I wrote the read and write functions like I did, they would keep writing until it's all over the wire, and keep reading until it has all the data it expects. I've done this quite often over plain-jane unix TCP/IP sockets without issues. I had also thought that QDataStream's operator<< (and operator>>) functions were supposed to handle QImage transfers, but as shown above, all you get is a NULL image.
    Life without passion is death in disguise

  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: QDataStream loses data over QTcpSocket?

    Quote Originally Posted by KShots View Post
    I had also thought that QDataStream's operator<< (and operator>>) functions were supposed to handle QImage transfers, but as shown above, all you get is a NULL image.
    They don't handle any "transfers". If not all image data is available to read then you'll get a null image.

    I don't see you wait for any data in the code you posted.
    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
    Feb 2006
    Location
    USA
    Posts
    142
    Thanks
    24
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows Android

    Default Re: QDataStream loses data over QTcpSocket?

    Ah, yes... I had not posted that part. I was calling a QTcpSocket->waitForReadyRead() before entering the readRawData() functions. That's why I get at least partial data.

    I also just recently added more waitForReadyRead() calls inside the readRawData() function, and I now do in fact get the entire image.

    As far as 'operator<<' and 'operator>>', are you suggesting that these are not suitable for use over sockets (meaning they'd work fine for QFile or similar)? Also, should I stop utilizing QDataStream::writeBytes() and QDataStream::readBytes() over TCP/IP for the same reasons? Am I just getting "lucky" that my XML content is small enough to be sent over in the first packet received?
    Life without passion is death in disguise

  7. #7
    Join Date
    Sep 2009
    Location
    UK
    Posts
    2,447
    Thanks
    6
    Thanked 348 Times in 333 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QDataStream loses data over QTcpSocket?

    You do understand that waitForReadyRead() blocks the current thread ? If this is your ui thread, it may cause the OS to terminate your code thinking it has become non-responsive.

    Is there a reason you do not use the much more preferred signals and slots approach?

  8. #8
    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: QDataStream loses data over QTcpSocket?

    Quote Originally Posted by KShots View Post
    As far as 'operator<<' and 'operator>>', are you suggesting that these are not suitable for use over sockets (meaning they'd work fine for QFile or similar)? Also, should I stop utilizing QDataStream::writeBytes() and QDataStream::readBytes() over TCP/IP for the same reasons?
    I'm only suggesting that they require complete data to be available. The source of the data is not relevant. If you'd like to read a rectangle but you have coordinates of only one point then no matter how hard you try, you can't create a rectangle out of it.

    Am I just getting "lucky" that my XML content is small enough to be sent over in the first packet received?
    Yes. Try congesting your link and you won't be so lucky anymore.
    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.


  9. #9
    Join Date
    Feb 2006
    Location
    USA
    Posts
    142
    Thanks
    24
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows Android

    Default Re: QDataStream loses data over QTcpSocket?

    I do understand that, the socket is being utilized in a non-gui thread. I am using signals and slots to the extent that I can, but I seem to be missing my crystal ball for telling me whether I should be expecting XML content (possibly a fragment if I'm understanding the above correctly with QDataStream.readBytes possibly not filling in all the data required before returning), or a QImage fragment. I see two states: (1) Waiting for requests, and (2) processing a request. I don't see (3) resuming processing on an arbitrary fragmented request
    Life without passion is death in disguise

  10. #10
    Join Date
    Sep 2009
    Location
    UK
    Posts
    2,447
    Thanks
    6
    Thanked 348 Times in 333 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QDataStream loses data over QTcpSocket?

    Surely you would have a state machine which tells you what you are expecting and that all data comes with a header which states what is to follow and how many bytes are present in the payload. If you receive something you didn't expect you inform the sender and perform appropriate error recovery procedures. You would also have appropriate timeout mechanisms such that if you receive a partial response and it doesn't complete after such timeout, you reject the already received data, etc.

    If you can receive the data using waitForReadyRead, then you can always receive the data using signals and slots (unless of course you have no event loop).

  11. #11
    Join Date
    Feb 2006
    Location
    USA
    Posts
    142
    Thanks
    24
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows Android

    Default Re: QDataStream loses data over QTcpSocket?

    Quote Originally Posted by squidge View Post
    Surely you would have a state machine which tells you what you are expecting and that all data comes with a header which states what is to follow and how many bytes are present in the payload.
    Yup, got that much... at least, all data comes with a header (in XML format), and even the header is prepended by a size variable telling me how large the header is... but regardless of how much data I expect to receive from what's in the header, that data just isn't going to be there (possibly the header itself is going to be fragmented) - so I need to read in what is available and wait for the rest to come in, and I need to do this outside of the event loop until this data is fully gathered (I can't operate on partial data). I can't see a means of waiting unless I call waitForReadyRead().
    Quote Originally Posted by squidge View Post
    If you can receive the data using waitForReadyRead, then you can always receive the data using signals and slots (unless of course you have no event loop).
    ... how is this possible if your data is fragmented? I'm starting to feel like I'm missing some fundamental concept here...
    Life without passion is death in disguise

  12. #12
    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: QDataStream loses data over QTcpSocket?

    That's simple:

    Qt Code:
    1. class X : ... {
    2. private slots:
    3. void moreDataArrived();
    4. private:
    5. QByteArray buffer;
    6. };
    7. // ...
    8. connect(socket, SIGNAL(readyRead()), this, SLOT(moreDataArrived()));
    9. //...
    10. void X::moreDataArrived() {
    11. QByteArray dat = socket->readAll(); // read all pending data
    12. buffer.append(dat); // and append it to your own buffer
    13.  
    14. while(bufferContainsFullRequest(buffer)){ // if data incomplete then this won't execute
    15. MyRequestClass req = getRequest(buffer); // removes data from buffer
    16. processRequest(req);
    17. }
    18. }
    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.


Similar Threads

  1. QTcpSocket QDataStream QByteArray
    By Grimlock in forum Newbie
    Replies: 1
    Last Post: 14th December 2009, 22:47
  2. QDataStream and QTcpSocket
    By babu198649 in forum Newbie
    Replies: 2
    Last Post: 24th January 2009, 12:29
  3. QTcpSocket and QDataStream
    By December in forum Qt Programming
    Replies: 1
    Last Post: 22nd March 2008, 14:13
  4. Problem with QTcpSocket and QDataStream
    By Valheru in forum Qt Programming
    Replies: 4
    Last Post: 16th September 2006, 13:08
  5. avaiability of data from QDataStream
    By quickNitin in forum Newbie
    Replies: 1
    Last Post: 19th June 2006, 12:32

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.