What is wrong with my QDataStream
-
Hello, I am writing piece of code for a basic TCP client based on the Blocking Fortune Client Example.
I adapted my code but I am facing an issue with this part of the code:do { if (!socket.waitForReadyRead(Timeout)) { emit error(socket.error(), socket.errorString()); return; } in.startTransaction(); in >> fortune; } while (!in.commitTransaction());
The problem is always get a timeout error even if the data are correctly sent by the server.
I checked the satus of in with in.status() and I always get a QDataStream::ReadCorruptData.
I checked that data are here using
const int len = 2048; char *text = new char[len]; in.readRawData(text, len); qDebug() << text;
Doing so, text contains data I expect to receive.
So the question is why in.commitTransaction() is not true even if data are there? Or the question might be, how to use QDataStream?
Thanks in advance.
-
@odelaune
I don't think you understand, I am not asking you about your receiving code, I am asking about your sending code. What Qt type is that sending?I have a feeling it is not sending any Qt type (like
QString
orQByteArray
). Rather it is just sending a stream of bytes/characters? In which case, how do you expect a transaction to work at receiving side? I suspect you are failing to understand that usingQDataStream
/types/transactions requires both sides to be using Qt and sending the same type as the receiver attempts to read?As I am not sure what type of data the server sends (text or byte)
Then you can't use transactions. You can only use the
readRawData()
you showed. https://doc.qt.io/qt-6/qdatastream.html#reading-and-writing-raw-binary-data -
@JonB said in What is wrong with my QDataStream:
But is the writer sending a QString (assuming you have QString fortune), or just a stream of bytes/characters, which it sounds like to me?
Good point, fortune was declared as a QString. As I am not sure what type of data the server sends (text or byte), I switch the declaration of fortune to QByteArray.
Now, the status has changed to QDataStream::ReadPastEnd but my data are still empty.
So to have the full view of the code, here is the current version
QDataStream in(&socket); in.setVersion(QDataStream::Qt_4_0); QByteArray data; do { if (!socket.waitForReadyRead(Timeout)) { emit error(socket.error(), socket.errorString()); return; } in.startTransaction(); in >> data; qDebug() << in.status(); } while (!in.commitTransaction());
So something is still wrong.
-
@odelaune
I don't think you understand, I am not asking you about your receiving code, I am asking about your sending code. What Qt type is that sending?I have a feeling it is not sending any Qt type (like
QString
orQByteArray
). Rather it is just sending a stream of bytes/characters? In which case, how do you expect a transaction to work at receiving side? I suspect you are failing to understand that usingQDataStream
/types/transactions requires both sides to be using Qt and sending the same type as the receiver attempts to read?As I am not sure what type of data the server sends (text or byte)
Then you can't use transactions. You can only use the
readRawData()
you showed. https://doc.qt.io/qt-6/qdatastream.html#reading-and-writing-raw-binary-data -
Indeed, you are write I cannot use QDataStream because the server does not use QDataStream to send data. So I just replaced the do/while loop by
QByteArray data; if (!socket.waitForReadyRead(Timeout)) { emit error(socket.error(), socket.errorString()); } data = socket.readAll();
And now it works fine.
-
@odelaune
Yes, you will have to interpret received data yourself.Be aware that
waitForReadyRead()
will/may return as soon as at least one byte is received. Not necessarily all bytes! Consider changing your logic over not to use this "synchronous" call, but instead thereadyRead()
signal, which is called every time more bytes are available, no matter when they arrive. Depending on your need, you may have to accumulate/buffer till you get all the bytes you are expecting, or work on bytes as they arrive knowing there may be more to come.