QDataStream 将错误值写入 QByteArray

QDataStream writing wrong values to QByteArray

我正在 Qt 中编写一个简单的基于 TCP 的网络应用程序,并希望使用 QDataStreamQByteArray 通过网络发送数据。问题是,当我将数据放入 QByteArray 时,它们是 "zeroed"。例如(连接到定时器超时信号的 MainWindow 中的一个槽):

void MainWindow::SendPlayer1Data(){
  QByteArray block;
  QDataStream s(&block, QIODevice::OpenModeFlag::ReadWrite);
  QString h="hello";
  s<<h;
  qDebug() << "h:        " << data;
  qDebug() << "block:    " << QString(block); // equivalent to s >> h on receiving end
  qDebug() << "block[0]: " << int(block[0]);
}

h:         "hello"
block:     ""
block[0]:  0

一开始我收到了一次"hello",但之后我只收到了""qint32 也是如此。客户端和服务器都显示 QByteArray 大小为 14 字节,因此 QDataStream 将数据写入该数组,但它使它们成为 0 (当我使用 [= 时显示 "" 23=] 然后使用 qDebug() << h)

这里的问题是将 QString 直接写入需要 QByteArray 的流,请考虑以下

QByteArray block;
QDataStream s(&block, QIODevice::OpenModeFlag::ReadWrite);
QString h = "hello";
s << h;
qDebug() << block;

输出

"\x00\x00\x00\n\x00h\x00""e\x00l\x00l\x00o"

所以数据就在那里,只是不像人们所期望的那样。解决此问题的最简单方法是从使用 UTF8(或您选择的其他编码)编码的字符串创建 QByteArray。这可以轻松地即时完成,

QByteArray block;
QDataStream s(&block, QIODevice::OpenModeFlag::ReadWrite);
QString h = "hello";
QByteArray data(h.toUtf8(), 5);
s << data;
qDebug() << block;

输出

"\x00\x00\x00\x05hello"

因为当这个 QByteArray 通过 QDataStream 发送时,数组的长度和 3 个 NULL 字符被前置 - NULL 字符在那里以防万一缓冲区大于相对较小的 5(您可以通过传递一个更大的值来为自己测试 - 256 的小系数最能说明问题 - 作为 QByteArray 构造函数中的第二个参数,因为这是缓冲区长度)。但是,如果您尝试从 NULL-开始的 QByteArray 显式构造 QString(如 s >> h 所做的那样),它将创建一个空字符串。要纠正这个问题,您可以使用 QByteArray::remove() 删除前 4 个字节,例如

QByteArray block;
QDataStream s(&block, QIODevice::OpenModeFlag::ReadWrite);
QString h = "hello";
QByteArray data(h.toUtf8());
s << data;
qDebug() << QString::fromUtf8(block.remove(0, 4));

输出

"hello"

完整示例

#include <qbytearray.h>
#include <qdatastream.h>
#include <qdebug.h>

int main() {
  QByteArray block;
  QDataStream s(&block, QIODevice::OpenModeFlag::ReadWrite);
  QString h = "hello";
  QByteArray data(h.toUtf8());
  s << data;
  qDebug() << QString::fromUtf8(block.remove(0, 4));
}

好的,我已经弄明白了。 问题不在于 QByteArray 或套接字,因为正如 @William Miller 提到的那样,数据就在那里。 问题出在客户端的 QDataStream - 我决定在每次调用负责接收数据的插槽时创建一个新的 QDataStream 对象。这样我就可以轻松地将数据打包到 QByteArray 中,每次都发送和接收。 接收客户端函数:

void ClientTcpHelper::ReceivePacket(){

if(socket.waitForReadyRead(20)){

    //qDebug()<<"Packet: "<<socket.peek(30)<<endl;
    qDebug()<<"Receiving packet!"<<endl;

    Data=socket.readAll();
    emit DataReceived();


}
else{
    //qDebug()<<"Failed to receive packet!"<<endl;

}}

并将数据解包到变量:

void ClientTcpHelper::UnpackData(){

stream=new QDataStream (&this->Data,QIODevice::OpenModeFlag::ReadWrite);
*stream>>h>>a>>b;
Data.clear();
delete stream;}

h,a 和 b 是 a class.

的成员

不幸的是,我无法解释为什么 QDataStream 每次都需要销毁,以便从一开始就按照我的意愿处理数据。