Results 1 to 2 of 2

Thread: QDataStream::writeRawData() bug?

  1. #1
    Join Date
    Oct 2010
    Posts
    2
    Qt products
    Qt3 Qt4
    Platforms
    MacOS X Unix/X11

    Default QDataStream::writeRawData() bug?

    Hi all -- I've been scouring the forums and Google trying to find more info on this, but have been unsuccessful so here goes (all done on Linux):

    I have a client-server setup using QTcpSocket and QTcpServer respectively. In a nutshell, the client and server transmit binary data to one-another by reading/writing data to the QTcpSocket through a QDataStream. The binary data is actually a GNU tar stream -- tar sends the binary stream to a named pipe (FIFO) and I read in the tar stream using QDataStream on the other end of the named pipe. I read the binary in 1MB chunks into a char* from a QFile using read(), write it to the QDataStream using writeRawData(), then write it to the QTcpSocket. On the other side of the connection, I have the readyRead() function return until it has all of the data for that particular chunk buffered (1MBish). Once the block of binary is ready, I read it from the QDataStream using readRawData() (read it into a char*), then write it to a QFile using write(). The QFile is another named pipe that has GNU tar listening on the other end. So, as I write the tar stream to the FIFO, tar reads it and extracts the data.

    The problem is, when I build the client/server with Qt 4.7.1 -- there are no issues (...and yes, I am doing a QDataStream::setVersion()) -- I can send data between the client and server and it works beautifully. When I re-compile with Qt 4.5.3, I the binary tar stream received from the server has been corrupt. (or when compiling against 4.7.1 but calling setVersion(QDataStream::Qt_4_5)). I tried reading it with a hex editor and it looks like there are some additional 0's (zeroes) in the tar stream. Is anyone familiar with a bug in QDataStream or maybe a bug with QFile::read() or QFile::write()?

    I am at a loss -- and due to platform limitations, I have to run Qt 4.5.3 on one of the platforms we're supporting, so upgrading is not an option. Here are the code snippets -- any help would be appreciated. I have a software release coming up soon and don't know what to do!

    This is the server code that reads the binary tar stream from the named pipe and sends it via QTcpSocket to the client. (ignore the char* thisChunk stuff, I thought Qt might be padding some zeroes to binaryChunk if less than 1MB was read)

    Qt Code:
    1. void Server::sendDataToClient()
    2. {
    3. QByteArray dataBlock;
    4. QFile inFile(exportFifo);
    5. QDataStream outboundStream(&dataBlock, QIODevice::ReadWrite);
    6. QDataStream fileStream(&inFile);
    7.  
    8. outboundStream.setVersion(QDataStream::Qt_4_5);
    9. fileStream.setVersion(QDataStream::Qt_4_5);
    10.  
    11. int bytesRead;
    12. int binaryChunkSize = 1048576; // Read 1MB chunks
    13. char* binaryChunk = new char[binaryChunkSize];
    14.  
    15. qDebug("opening named pipe");
    16.  
    17. if (!inFile.open(QIODevice::ReadOnly))
    18. {
    19. qDebug("open() on named pipe failed");
    20. logMessage("Unable to open named pipe for reading");
    21. return;
    22. }
    23.  
    24. bytesRead = inFile.read(binaryChunk, binaryChunkSize);
    25.  
    26. qDebug() << "read bytes: " << bytesRead;
    27.  
    28. while(bytesRead > 0)
    29. {
    30. int bytes = bytesRead;
    31. char* thisChunk = new char[bytes];
    32. memcpy(thisChunk, binaryChunk, bytes);
    33.  
    34. // Create a data block for the binary
    35. outboundStream << quint64(0);
    36. outboundStream << quint16('BD');
    37. outboundStream.writeRawData(thisChunk, bytes);
    38. // outboundStream.writeRawData(binaryChunk, bytesRead);
    39. outboundStream.device()->seek(0);
    40. outboundStream << quint64(dataBlock.size() - sizeof(quint64));
    41.  
    42. // This is crucial!! When the QDataStream is passed, it retains its
    43. // current reference. This was a PITA BUG TO FIND!!!!!! (for testing)
    44. outboundStream.device()->seek(0);
    45.  
    46. socket.write(dataBlock);
    47.  
    48. if(!socket.waitForBytesWritten())
    49. {
    50. // Something bad happened, bail out
    51. logMessage("Timed out waiting for bytes from FIFO");
    52. break;
    53. }
    54.  
    55. outboundStream.device()->reset();
    56.  
    57. // Continue to read chunks from the pipe
    58. bytesRead = inFile.read(binaryChunk, binaryChunkSize);
    59. delete[] thisChunk;
    60. qDebug() << "read bytes: " << bytesRead;
    61. }
    62.  
    63. if(bytesRead == 0)
    64. {
    65. // All bytes have been read from the pipe. Let the client know that
    66. // the transfer is finished.
    67. binaryTransferFinished();
    68. }
    69.  
    70. // Clean up
    71. inFile.close();
    72. delete[] binaryChunk;
    73. }
    To copy to clipboard, switch view to plain text mode 



    And here is the client code that reads the data from the server...

    Qt Code:
    1. void ComponentNPT::receiveBinaryData(QDataStream& inboundStream, quint64& dataSize)
    2. {
    3. // Don't include the 16-bit response code, we just want the size of the binary
    4. quint64 binarySize = dataSize - sizeof(quint16);
    5.  
    6. inboundStream.setVersion(QDataStream::Qt_4_5);
    7.  
    8. int bytesRead = 0;
    9. int tmpRead = 0;
    10. int tmpWrite = 0;
    11. int bytesWritten = 0;
    12. char* binaryChunk = new char[binarySize];
    13.  
    14. // Loop until we've read all of the binary sent in the data block
    15. while(bytesRead < binarySize)
    16. {
    17. tmpRead = inboundStream.readRawData(binaryChunk, (binarySize - bytesRead));
    18.  
    19. // tmpRead < 0 is an error, tmpRead == 0 indicates all bytes have been read
    20. if(tmpRead < 0)
    21. qDebug() << "Read error: ";
    22. else if(tmpRead == 0)
    23. break;
    24. else
    25. {
    26. bytesRead += tmpRead;
    27.  
    28. while(bytesWritten < tmpRead)
    29. {
    30. tmpWrite = outFile.write(binaryChunk, bytesRead);
    31.  
    32. if(tmpWrite < 0)
    33. {
    34. qDebug() << "Write error: " << outFile.errorString();
    35. break;
    36. }
    37. else
    38. {
    39. bytesWritten += tmpWrite;
    40. }
    41. }
    42. }
    43. }
    44.  
    45. // Make progress updates based on writes to the FIFO
    46. updateProgressDialog(bytesWritten);
    47.  
    48. // Clean up
    49. delete[] binaryChunk;
    50. }
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Feb 2007
    Location
    Karlsruhe, Germany
    Posts
    469
    Thanks
    17
    Thanked 90 Times in 88 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QDataStream::writeRawData() bug?

    Hi!

    I don't know of any bugs in QFile or QDataStream! Sorry! Can't offer a simple way out :->

    I glanced at your code, and couldn't figure out how the size of your last datablock can be correct! As far as I can see you are not releasing your byteArray from one iteration to the next, but use its size. But in the last iteration the stream will not have written till the end but presumably shorter. If my observation is correct, just use the stream->device->position() before you seek back as "datasize". Or much simpler: bytes+10. If not, then its time for me to go to bed, I guess :->

    However that might be, I would suggest that you create a small test project, that you can share with us, that leaves the client server stuff out, but reads and writes your files in exactly the same way locally. That should help to pinpoint the problem!

    Good luck!

    Johannes

Similar Threads

  1. QDataStream and QDebug
    By babu198649 in forum Newbie
    Replies: 4
    Last Post: 21st December 2007, 09:21
  2. QDataStream use
    By Doug Broadwell in forum Qt Programming
    Replies: 2
    Last Post: 21st July 2007, 22:17
  3. Using QDataStream
    By toratora in forum Qt Programming
    Replies: 1
    Last Post: 2nd May 2007, 15:35
  4. QDataStream
    By TheKedge in forum Qt Programming
    Replies: 1
    Last Post: 23rd August 2006, 14:40
  5. QDataStream
    By frankoz in forum Qt Programming
    Replies: 1
    Last Post: 1st March 2006, 07:18

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.