LINUX.ORG.RU

QTcpSocket: неверный размер переданных данных

 


0

1

Имеется клиент-серверное приложение, взаимодействующее через QTcpSocket.

С сервера QJsonObject передается следующим образом:

void TransceiverProvider::sendMessage(const QJsonObject &jsonObject)
{
    QByteArray data = QJsonDocument(jsonObject).toBinaryData();

    QByteArray  block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_2);
    out << (quint16)0;
    out << data;
    out.device()->seek(0);
    out << (quint16)(block.size() - sizeof(quint16));

    qDebug() << "Data size:" << data.size();
    qDebug() << "Block size:" << block.size() - sizeof(quint16);
    qDebug() << "Data:" << data.toHex();
    qDebug() << "Block:" << block.toHex();

    m_tcpSocket->write(block);
}

Во время выполнения выводится следующее:

Data size: 76 
Block size: 80 
Data: "71626a73010000004400000003000000400000009b0300000700636f6d6d616e6400000022006765745f73796e635f706172616d65746572732021212121212121212121212121210c000000" 
Block: "00500000004c71626a73010000004400000003000000400000009b0300000700636f6d6d616e6400000022006765745f73796e635f706172616d65746572732021212121212121212121212121210c000000"

Клиент принимает сообщение таким образом:

void TransceiverProvider::readyRead()
{
    QDataStream in(m_tcpSocket);
    in.setVersion(QDataStream::Qt_4_2);
    for (;;)
    {
        if (m_blockSize == 0)
        {
            if (m_tcpSocket->bytesAvailable() < (int)sizeof(quint16))
            {
                return;
            }
            in >> m_blockSize;
        }

        if (m_tcpSocket->bytesAvailable() < m_blockSize)
        {
            return;
        }

        char * buf = new char[m_blockSize];
        in.readRawData(buf, m_blockSize);
        QByteArray data(buf, m_blockSize);
        delete buf;

        qDebug() << "block size:" << m_blockSize;
        qDebug() << "size:" << data.size();
        qDebug() << "data:" << data.toHex();

        emit receivedMessage(QJsonDocument::fromBinaryData(data).object());

        m_blockSize = 0;
    }
}

Вывод:

block size: 80 
size: 80 
data: "0000004c71626a73010000004400000003000000400000009b0300000700636f6d6d616e6400000022006765745f73796e635f706172616d65746572732021212121212121212121212121210c000000"

Естественно построить исходный json объект не удается. Как видно data на клиенте не равна data на сервере. А захватывает часть исходного сообщения (block).

Чем это вызвано?


Если при приеме данных выводить в консоль m_tcpSocket->readAll().toHex(), то строка будет полностью соответствовать отправленному block.

Есть у меня где-то неверно читается block, либо последующее сообщение.

m_blockSize у меня quint16. В block размер записывается тоже как quint16.

Не понимаю где ошибка.

totik
() автор топика

потому что ты отправляешь размер блока минус 2 байта на длину, а надо просто размер данных, т.е.

out << (quint16)(block.size() - sizeof(quint16));

->

out << (quint16)data.size();

dib2 ★★★★★
()
Ответ на: комментарий от dib2

block != data

Если отправляемый block формировать как out << data.size() << data тоже выходит ерунда. Ну а block.size() - sizeof(quint16) теоретически равно data.size.

totik
() автор топика

Выяснила, что между первыми двумя байтами размера данных и самими данными затесались три байта нулей.

Как это выходит?

Данные: «71626a73010000004400000003000000400000009b0300000700636f6d6d616e6400000022006765745f73796e635f706172616d65746572732021212121212121212121212121210c000000»

Блок: «004c0000004c71626a73010000004400000003000000400000009b0300000700636f6d6d616e6400000022006765745f73796e635f706172616d65746572732021212121212121212121212121210c000000»

004c - размер данных - 76. Между ним и данными лишние 000000.

wtf?

totik
() автор топика
Ответ на: комментарий от totik

Еще уточнение: если на принимающей стороне просто выводить все, что приходит, а на клиенте отправлять данные как есть, без указания размера, то выходит что лишние лидирующие три байта появляются на клиенте при приеме, а не формируются на стороне сервера.

totik
() автор топика

Почитай, как QDataStream сериализует QByteArray и все сразу станет понятно. Hint: велосипед с передачей и чтением длины блока как quint16 в данном случае вообще не нужен.

Deleted
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.