сериализация с сетью QT и десериализация с Boost - PullRequest
1 голос
/ 21 ноября 2011

В первый раз я хочу поблагодарить HostileFork , чтобы помочь мне объяснить мою проблему.Спасибо вам!

Я пытаюсь создать клиент и сервер, которые отправляют свои данные через двоичный протокол.

Моя проблема в том, что я хочу отправить класс из клиента QT вBoost Server.Мой заголовок (одно целое число размером с мой класс) записывает в сокет.Когда я хочу прочитать заголовок на стороне сервера, я не могу получить хорошее целое число (вместо этого у меня есть большое число, например -13050660).Я думаю, что проблема заключается в десериализации на сервере, но я не уверен.

Это метод, который мой код клиента Qt использует для записи числа 10 в сокет:

QByteArray paquet;
QDataStream out(&paquet, QIODevice::WriteOnly);
out << (quint32) 0;
out.device()->seek(0);
out << (quint32) (10);
cout << "Writing " << sizeof(quint32) << " bytes to socket." << endl;

Затем я пытаюсь прочитать его на серверном процессе, который использует метод async_read ():

this->Iheader.resize(size, '\0'); // Iheader is a vector of char
async_read(
    this->socket,
    buffer(this->Iheader),
    bind(
        &Client::endRead,
        cli,
        placeholders::error,
        placeholders::bytes_transferred)
);

Вот функция, которая работает с результатом строки:

#ifdef WIN32
    #define MYINT INT32
    #include <Windows.h>
#else
    #define MYINT int
#endif

void Client::endRead(const error_code& error, size_t nbytes)
{
    if (!error && nbytes == sizeof(MYINT)) {
        cout << "Read " << sizeof(MYINT) << " bytes from a socket." << endl;
        istringstream stream(this->connection->getIheader(nbytes));
        stream >> this->Isize;
        cout << "Integer value read was " << this->Isize << endl;
    } else {
        cout << "Could not read " << sizeof(MYINT) << " bytes." << endl;
    }
}

Iполучить 32-разрядное целое число со знаком (4 байта), но это не десять, а что-то вроде -1163005939.Кто-нибудь есть и идеи, почему это не работает?

Сервер и клиент оба при запуске на Windows7 Pro, 64-разрядная.

Ответы [ 2 ]

1 голос
/ 22 ноября 2011

Не за что ... и спасибо за следование моим предложениям за редактирование вопроса и за выполнение необходимых усилий для более четкого определения проблемы.Так что теперь я могу сказать вам, что не так.:)

Поведение << и >> отличается на QDataStream от стандартного ввода-вывода C ++.В мире таких классов, как std::stringstream, эти операторы называются «вставками» / «экстракторами» и предназначены для работы с информацией, отформатированной как текст .Если вы хотите прочитать определенное количество байтов в адрес памяти, вам нужно:

http://www.cplusplus.com/reference/iostream/istream/read/

(Обратите внимание, что если вы хотите читать двоичные данныеиз чего-то, что не является строковым потоком, вы должны использовать ios :: binary , чтобы не мешать преобразованиям с окончанием строки)

QDataStream не следуетэто соглашение ... это хороший помощник для двоичных данных.В этом нет ничего плохого ... поскольку абстрактно операторы << и >> доступны на языке, который можно перегружать, чтобы делать все, что вы хотите в своих собственных иерархиях классов.Qt был свободен в определении собственной семантики для своих собственных потоков, и они это сделали.

Прислушайтесь к совету, данному @vitakot относительно (если возможно) использования одной и той же методологии для ввода и вывода.Также примите во внимание мое предупреждение о проблемах порядка следования байтов , которые начинают появляться, если вы не будете осторожны.

(Хорошая новость заключается в том, что, если вы используете QDataStream, это решает эту проблему заботясь об этом за вас .)

Имейте в виду, что в написанном вами коде ваш струнный поток создает копию буфера для чтения из него.У меня нет опыта с boost::asio или лучшими практиками async_read, но я уверен, что есть лучшие способы, которые вы могли бы найти и найти.

0 голосов
/ 22 ноября 2011

HostileFork прав, из имеющейся у нас информации невозможно выделить ошибку в вашем коде.

Однако я бы посоветовал вам также использовать сериализацию Boost в вашем Qt-клиенте.Нет причин не объединять библиотеки Boost и Qt.В противном случае вам придется столкнуться с множеством проблем при отправке более сложных классов по сети ...

...