QTcpSocket - Как отправить два числа

Клиентское приложение отправляет на сервер через QTcpSocket два (укороченных) числа:

ushort MessageId = 4;
ushort MessageSize = 0;
socket->write((const char*) &MessageId, sizeof(ushort));
socket->write((const char*) &MessageSize, sizeof(ushort));
socket->waitForBytesWritten();

Сервер Приложение получает сообщение длиной 4 байта и помещает его в буфер QByteArray, а затем декодирует числа:

int bytes = socket->bytesAvailable();
QByteArray buffer = socket->read(bytes)

const char * messageIdBytes = buffer.mid(0, 2);
ushort messageId = (ushort)(*messageIdBytes);

const char * messageSizeBytes = buffer.mid(2, 4);
ushort messageSize = (ushort)(*messageSizeBytes );

qDebug() << QString("MessageId Bits: [%1], Value: [%2].").arg(QString::number(messageId, 2), QString::number(messageId));
qDebug() << QString("MessageSize Bits: [%1], Value: [%2].").arg(QString::number(messageSize, 2), QString::number(messageSize));

Это дает следующий вывод сервера: (я добавил пробелы для удобства чтения)

MessageId Bits: [1111 1111 1101 1101], Value: [65501].
MessageSize Bits: [1111 1111 1101 1101], Value: [65501].
  • Проблема: вывод сервера должен получить MessageId 4 и MessageSize 0.
  • Наблюдение: отправка разных значений от клиента даже не влияет на вывод сервера. Всегда этот странный номер 65501..
  • Интересно: однако это работает, если я напишу только один номер вместо двух!

Любая идея, что я делаю неправильно?


person Sora    schedule 18.12.2017    source источник
comment
каков результат, если вы qDebug() << buffer; после 'socket-›read(bytes)'? хотя я думаю, что недостающая доза ; не вызывает ошибки компиляции ;D.   -  person a.tabatabaei    schedule 18.12.2017


Ответы (2)


Отправка необработанных чисел никогда не является хорошей идеей. Причины, по которым это может пойти не так, следующие:

  • Десинхронизация
  • Endianess
  • Ошибки синтаксического анализа
  • ...

Лучшей практикой в ​​Qt является использование QDataStream для отправки и получения данных:

Код клиента:

QDataStream stream(socket);
stream << MessageId << MessageSize;

Код сервера:

QDataStream stream(socket);
ushort MessageId, MessageSize;
stream.startTransaction();
stream >> MessageId >> MessageSize;
if(stream.commitTransaction())
    qDebug() << "Worked:" << MessageId << MessageSize;
else
    qDebug() << "Error:" << stream.status();

Вы можете узнать больше о QDataStream и прочитать транзакции в Документация

person Felix    schedule 18.12.2017

Я думаю, что вы читаете ненужные данные, посмотрите на среднюю декларацию

QByteArray QByteArray::mid(int pos, int len = -1) const

он возвращает новый объект, и в этой строке

const char * messageIdBytes = buffer.mid(0, 2);

mid функция возвращает временный объект QByteArray, он преобразуется в const char* с помощью метода

QByteArray::operator const char *() const

когда временный объект удаляется, ваш указатель болтается. Тогда вы читаете ненужные данные.

Одно в этой строке

buffer.mid(2, 4); // should be 2 as second argument, this is not index but length
person rafix07    schedule 18.12.2017
comment
Спасибо за это подробное объяснение. Мне еще многому предстоит научиться. :D - person Sora; 18.12.2017