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));
}