QDataStream записывает неправильные значения в QByteArray - PullRequest
0 голосов
/ 29 декабря 2018

Я пишу простое сетевое приложение на основе 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 ]

0 голосов
/ 30 декабря 2018

Хорошо, я понял это.Проблема была не в 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 нужно каждый раз уничтожать здесь, чтобы обрабатывать данные, как я хотел с самого начала.

0 голосов
/ 29 декабря 2018

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