Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Передать объект через TCP
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Ввод/Вывод, Сеть. Межпроцессное взаимодействие
Norrius
Добрый день. Я пишу небольшой проект, содержащийсервер

Добрый день. Я пишу небольшой проект, содержащий серверную и клиентскую часть. В частности, мне нужно, чтобы клиент имел копию некоторого класса, имеющегося на сервере. Собственно, вопрос - как передать объект класса через TCP сокет? Нужно ли мне вручную создавать QByteArray, содержащий закодированную информацию об объекте (а он может содержать другие классы и структуры), или есть более простые способы?
ViGOur
В Qt connection points нет насколько я знаю.

Нужно только руками. Для примера два способа:

1 способ и самый простой - это использование стандартных С++ типов, вроде int, char и ...
Ничего тебе не мешает имея такую структуру:
struct sClass
{
  int n;
  double d;
  char s[1024];
};

отправить её:
sClass sc;
char *pBuff = new char[sizeof(sClass)];
// заполняем sc
memcpy( sc, pBuff, sizeof( sClass));
send( sock, pBuff, sizeof(sClass), 0 );


2 способ - реализация реализация своего operator char*() для класса, для последуюшей отправки по сети.
Алексей1153
сериализация в XML - универсальное в данном случае средство :)

(со структурами тоже можно, но всё это будет удобно ровно до первого изменения структур. Опять же, динамически выделенную память передавать без трудностей так невыйдет)
Norrius
Использовать memcpy() у меня не получается (хотя, может, я просто не понял документацию), я получаю мусор в клиенте. Сервер:

p tmp = pList[i];
char buff[sizeof(p)];
memcpy(&buff, &tmp, sizeof(p));
connections[i]->write(buff);

Где QList<QTcpSocket *> connections содержит все подключения. Клиент:

char buff[sizeof(p)];
tcpSocket->read(buff, sizeof(p));
p tmp;
memcpy(&tmp, &buff, sizeof(p));
*cashe = tmp;


Цитата(ViGOur @ 24.7.2012, 19:58) *
реализация своего operator char*()

А что это есть и где про это можно узнать подробнее?

Цитата(Алексей1153 @ 24.7.2012, 20:41) *
сериализация в XML - универсальное в данном случае средство

Не будет ли это заворотом в лишнюю обертку? :mellow: Мне нужно просто синхронизировать данные о классе p.
ViGOur
сервер
memcpy(buff, &tmp, sizeof(p));

клиент
memcpy(&tmp, buff, sizeof(p));


Цитата(Norrius @ 25.7.2012, 0:16) *
А что это есть и где про это можно узнать подробнее?
В принципе любой из книжек по С++.
Смотри в сторону переопределения операторов, там объясняется как переопределять operator int, operator char и т.д. и т.п.


Например можешь почитать: C++ : библиотека программиста (Автор: Джефф Элджер)
У него точно есть подробное описание этого оператора, на примере класса String...
Iron Bug
процедура передачи класса - даже не сериализация, а маршалинг. если интересует эта тема - читать про маршалинг (marshaling) в С++.
Алексей1153
Цитата(Norrius @ 25.7.2012, 2:16) *
е будет ли это заворотом в лишнюю обертку? Мне нужно просто синхронизировать данные о классе p.

я не предлагаю обёртку, я предлагаю гибкий способ передачи
ssoft
Цитата(ViGOur @ 25.7.2012, 9:46) *
сервер
memcpy(buff, &tmp, sizeof(p));
Language: cpp

клиент
memcpy(&tmp, buff, sizeof(p));


Это работает, если класс содержит только простые типы.
Если класс содержит аля QByteArray, QString или любой указатель, то только сериализация или маршалинг.

Цитата(Norrius @ 25.7.2012, 0:16) *
Не будет ли это заворотом в лишнюю обертку? Мне нужно просто синхронизировать данные о классе p.


В общем случае проще ничего не придумали.
ViGOur
Цитата(ssoft @ 26.7.2012, 7:52) *
Это работает, если класс содержит только простые типы.

Цитата(ViGOur @ 24.7.2012, 19:58) *
это использование стандартных С++ типов, вроде int, char и ...
;)
Алексей1153
Цитата(ssoft @ 26.7.2012, 9:52) *
Если класс содержит аля QByteArray, QString или любой указатель,


или хотя бы одну виртуальную функцию :) К слову, визард очень любит делать деструктор виртуальным
Norrius
Спасибо всем за ответы, буду изучать сериализацию и маршалинг.
Norrius
Хм, похоже, был откат форума. Что ж, нужно все-таки написать решение) Я использовал QDataStream и переопределенные операторы ввода и вывода вида
QDataStream &operator>>(QDataStream & s, tile &t);
QDataStream &operator<<(QDataStream & s, const tile &t);
ViGOur
Угумс, снова посыпалась БД.
Norrius
Еще один небольшой вопрос: если когда испускается сигнал readyRead() сделать вот так:
    QDataStream stream(tcpSocket);
    stream.setVersion(QDataStream::Qt_4_8);
    stream >> some_data;

То будет ли получена из потока вся информация, которая была отправлена с другой стороны? Или только та, что уже пришла? Иначе говоря, будет ли readyRead() вызван, когда данные начинают приходить или когда заканчивают? Из нескольких мегабайт, что я пытаюсь переслать, доходит и обрабатывается только первый кусок неопределнной длины, и я не уверен, в чем тут прикол.
iReset
Цитата(Norrius @ 10.8.2012, 17:25) *
...будет ли получена из потока вся информация, которая была отправлена с другой стороны? Или только та, что уже пришла? Иначе говоря, будет ли readyRead() вызван, когда данные начинают приходить или когда заканчивают?

Сигнал посылается, как только появляется новая порция данных. QIODevice ничего не знает о том объёме данных, которые нужны принимающей стороне. Новая порция - один сигнал. Информацию о доступном количестве байт можно получить функцией bytesAvailable(). Если данных недостаточно, можно просто их не читать и дождаться ещё одного сигнала. Прочитать порцию нужного размера можно, когда она полностью попадёт в буфер.
Norrius
Цитата(iReset @ 10.8.2012, 18:10) *
Информацию о доступном количестве байт можно получить функцией bytesAvailable(). Если данных недостаточно, можно просто их не читать и дождаться ещё одного сигнала.

Ага, хорошо. Но что если есть разные пакеты? Есть пакет, начинающийся с (byte)0x01, длиной 45 байт, а пакет, что начинается с (byte)0x02, имеет длину 3145737 байт (или 2621448, никак точно не измерю). Плюс планируются пакеты, длина которых будет варьироваться... Может быть, это в принципе неправильный способ передачи для такой ситуации?)
Norrius
Спасибо, вроде бы получилось.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.