QDataStream записывает неправильные значения в QByteArray

Я пишу простое сетевое приложение на основе TCP в Qt и хотел использовать QDataStream а также QByteArray отправить данные по сети. Проблема в том, что когда я помещаю данные в 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)

2 ответа

Решение

Хорошо, я понял это. Проблема была не в 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 являются членами класса.

К сожалению, я не могу объяснить, почему QDataStream нужно каждый раз уничтожать, чтобы обрабатывать данные так, как я хотел с самого начала.

Проблема здесь заключается в написании 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"

Итак, данные есть, их просто нет, как можно ожидать. Самый простой способ решить эту проблему - создать 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 конструктор, так как это длина буфера). Но если вы попытаетесь явно построить QString (как s >> h делает) из NULL-commenced QByteArray это создаст пустую строку. Чтобы исправить это, вы можете использовать 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));
}
Другие вопросы по тегам