所以我有一个奇怪的问题,当我在QTcpSocket上读取数据(QDataStream)时:有些数据似乎丢失了。 bytesAvailable()函数将返回要读取的适当字节数,但QDataStream似乎并不保存所有字节。
首先,这是数据的外观:
bufferX始终包含768个浮点,而bufferY始终包含5376个浮点。因此,我希望发送的总数据为(不包括块大小):int + 768浮点数+ 5376浮点数= 4 + 3072 + 21504 = 24580字节。
现在,这是发件人代码:
void ClientSocket::serverTaskResult()
{
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_DefaultCompiledVersion);
out << quint16(0);
out << mServerTask->getNPoints();
for (size_t i = 0; i < BUFFERX_SIZE; i++)
out << mServerTask->getBufferX(i);
for (size_t i = 0; i < BUFFERY_SIZE; i++)
out << mServerTask->getBufferY(i);
out.device()->seek(0);
out << quint16(block.size() - sizeof(quint16));
write(block);
out << quint16(0xFFFF);
}
这是接收方代码:
void TestClient::recoverResult()
{
QDataStream in(&mTcpSocket);
in.setVersion(QDataStream::Qt_DefaultCompiledVersion);
float wBufferX[BUFFERX_SIZE];
float wBufferY[BUFFERY_SIZE];
int wNPoints;
forever{
if (mNextBlockSize == 0)
{
qint64 nBytesAvailable = mTcpSocket.bytesAvailable();
if (nBytesAvailable < sizeof(quint16))
break;
in >> mNextBlockSize;
}
if (mNextBlockSize == 0xFFFF)
{
closeConnection();
break;
}
if (mTcpSocket.bytesAvailable() < mNextBlockSize)
break;
for (size_t i = 0; i < BUFFERX_SIZE; i++)
in >> wBufferX[i];
for (size_t i = 0; i < BUFFERY_SIZE; i++)
in >> wBufferY[i];
in >> wNPoints;
mNextBlockSize = 0;
}
}
现在,我注意到的第一个奇怪的事情是nBytesAvailable的值始终为49158,大约是我期望值的两倍。我收到的字节数是预期的两倍是怎么回事?
其次,由于我拥有所有这些可用字节,因此我希望QDataStream能够正确填充缓冲区。但是,在315至350之间的任何浮动之后,QDataStream似乎包含不可用的数据。也就是说,wBufferX将在其最初的315-350索引中定义(并更正)值,然后再定义未知值。我不明白那是怎么回事,因为bytesAvailable()清楚地表明套接字上有近5万个字节。我想念什么?
非常感谢您的帮助!谢谢!
所以您注意到您收到了比预期更多的字节。那是因为您期望它们太少了。
请运行此示例以更好地了解:
#include <QCoreApplication>
#include <QDataStream>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_DefaultCompiledVersion);
out << static_cast<short>(0);
out << static_cast<float>(0.0);
qDebug() << "EXPECTED SIZE: " << sizeof(short)+sizeof(float);
qDebug() << "ACTUAL SIZE: " << block.size();
}
这里的输出是:
EXPECTED SIZE: 6
ACTUAL SIZE: 10
我们可以争辩说,流将其自身的四个额外字节填充到了基础数组中,这是很正常且可以理解的:写入流在每条数据之前都留下类型信息。
现在运行此:
#include <QCoreApplication>
#include <QDataStream>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_DefaultCompiledVersion);
short x = 42;
float y = 0.1;
out.writeRawData(reinterpret_cast<char*>(&x), sizeof(short));
out.writeRawData(reinterpret_cast<char*>(&y), sizeof(float));
qDebug() << "EXPECTED SIZE: " << sizeof(short)+sizeof(float);
qDebug() << "ACTUAL SIZE: " << block.size();
}
这次:
EXPECTED SIZE: 6
ACTUAL SIZE: 6
它按预期工作:字节数组的大小只是每个输出变量的大小之和。要读回这样的缓冲区,必须使用readRawData
:
QDataStream in(&block, QIODevice::ReadOnly);
short s;
in.readRawData(reinterpret_cast<char*>(&s), sizeof(short));
float f = 0.1;
in.readRawData(reinterpret_cast<char*>(&f), sizeof(float));
qDebug() << s << ", " << f; //42 , 0.1
我认为您对输出缓冲区大小的错误假设会影响代码中的几乎所有其他内容(例如,此行
out << quint16(block.size() - sizeof(quint16));
没有任何意义,如果您考虑一下...)。