1

我正在 Qt 中编写一个简单的基于 TCP 的网络应用程序,并希望使用QDataStreamQByteArray通过网络发送数据。问题是当我将数据放入时QByteArray,它们被“归零”。例如(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""当我使用s >> h然后使用时显示qDebug() << h

4

2 回答 2

0

这里的问题是将 aQString直接写入期望 a 的流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"

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

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构造函数中的第二个参数,因为这是缓冲区长度)。但是,如果您尝试从-commenced显式构造一个QString(如所做的那样),它将创建一个空字符串。要纠正这一点,您可以使用像这样删除第一个字节s >> hNULLQByteArrayQByteArray::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));
}
于 2018-12-29T07:54:27.107 回答
0

好的,我已经想通了。问题不在于QByteArrayor 套接字,因为@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 是一个类的成员。

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

于 2018-12-30T02:28:07.663 回答