Russian Qt Forum

Qt => Вопросы новичков => Тема начата: Magnolia от Апрель 18, 2012, 14:20



Название: Как записать структуру в QByteArray
Отправлено: Magnolia от Апрель 18, 2012, 14:20
Всем привет! Впервые работаю с UDP сокетами, поэтому возникли проблемы. Пытаюсь записать в сокет структуру, для этого использую прототип функции qint64 QIODevice::write ( const QByteArray & byteArray ). Вот код:
Код:
 QByteArray buff;
            memmove(&buff, &tt, sizeof(tt));
            udp->write(buff);
(tt - это как раз структура (struct), udp - udpсокет).
В результате в масиив buff ничего не записывается. Подскажите как и что делать :)


Название: Re: Как записать структуру в QByteArray
Отправлено: mutineer от Апрель 18, 2012, 14:26
да ты крутой, однако, так делать...
Тебе надо сериализовать свою структуру в QByteArray


Название: Re: Как записать структуру в QByteArray
Отправлено: navrocky от Апрель 18, 2012, 14:33
Всем привет! Впервые работаю с UDP сокетами, поэтому возникли проблемы. Пытаюсь записать в сокет структуру, для этого использую прототип функции qint64 QIODevice::write ( const QByteArray & byteArray ). Вот код:
Код:
 QByteArray buff;
            memmove(&buff, &tt, sizeof(tt));
            udp->write(buff);
(tt - это как раз структура (struct), udp - udpсокет).
В результате в масиив buff ничего не записывается. Подскажите как и что делать :)


Можно с осторожностью передавать только упакованные стуктуры по сети и при отстутствии в них не-pod полей.
Важно учесть, что на архитектурах процессоров с обратным порядком байт в целых числах (PowerPC например) твою структуру не поймут.

Вот так правильней:
Код:
udp->write(&tt, sizeof(tt));

Для объявление упакованной структуры в разных компиляторах используются разные директивы. Так что гугли.


Название: Re: Как записать структуру в QByteArray
Отправлено: Пантер от Апрель 18, 2012, 14:41
memmove(&buff, &tt, sizeof(tt));
You make my day.


Название: Re: Как записать структуру в QByteArray
Отправлено: Magnolia от Апрель 18, 2012, 14:54
да ты крутой, однако, так делать...
Тебе надо сериализовать свою структуру в QByteArray
Можно поподробнее? И кстати, я девушка


Название: Re: Как записать структуру в QByteArray
Отправлено: Странник от Апрель 18, 2012, 17:06
если на другом конце тоже Qt-приложение болтается, проще использовать QDataStream.


Название: Re: Как записать структуру в QByteArray
Отправлено: Magnolia от Апрель 19, 2012, 15:32
На другом конце железка болтается.
Проблему решила
Код:
 
    QByteArray buff;
    buff.clear();
    buff.resize(56);
    unsigned char buffer[56] = {0};
    memmove(&buffer,(unsigned char *)&tt, 56);
    for(int i = 0; i <56; i++)
        buff[i] = buffer[i];
    udp->writeDatagram(buff.data(),56,QHostAddress("192.168.0.81"),9800);
Не знаю уж насколько это правильно но ... Работает, пыхтит :)
ЗЫ
Пакет всегда размером 56 байт


Название: Re: Как записать структуру в QByteArray
Отправлено: Igors от Апрель 19, 2012, 15:45
Не знаю уж насколько это правильно но ...
Ну вообще-то не очень  :) Лучше так
Код
C++ (Qt)
QByteArray buff;
buff.resize(sizeof(tt));
memmove(buff.data(), &tt, sizeof(tt));
 
А структура должна быть объявлена (на обеих сторонах) примерно так
Код
C++ (Qt)
#pragma pack(push, 4)
struct MyTT {
int  member1;
...
};
#pragma pack(pop)
 
Структура не может быть классом с виртуальными методами и не должна иметь никаких членов-указателей, т.к. адреса теряются при передаче

Даже при всем этом нельзя назвать такой подход "правильным". По-взрослому надо сериализоваться в QDataStream


Название: Re: Как записать структуру в QByteArray
Отправлено: bez_glaz от Апрель 19, 2012, 15:54
Аналогичная ситуация передачи у меня по UDP структуры.
Воспользовался
Код:
QByteArray buff;
buff.resize(sizeof(tt));
memmove(buff.data(), &tt, sizeof(tt));
Всё на ура.
А можно по подробнее с QDataStream?
Хотелось бы грамотно кодить приложение, а не чтоб работало.


Название: Re: Как записать структуру в QByteArray
Отправлено: LisandreL от Апрель 19, 2012, 19:44
Можно с осторожностью передавать только упакованные стуктуры по сети и при отстутствии в них не-pod полей.
Важно учесть, что на архитектурах процессоров с обратным порядком байт в целых числах (PowerPC например) твою структуру не поймут.
Ещё не все типы имеют гарантированно одинаковый размер на разных архитектурах.

А можно по подробнее с QDataStream?
Хотелось бы грамотно кодить приложение, а не чтоб работало.
Перегружаете опретароы << и >> для вашего типа. Внутри сериализуете/десериализуете по полям в одном порядке, приводя их к типам указанным в Serializing Qt Data Types (не long, а qint64 и т.п.).


Название: Re: Как записать структуру в QByteArray
Отправлено: navrocky от Апрель 20, 2012, 23:39
Аналогичная ситуация передачи у меня по UDP структуры.
Воспользовался
Код:
QByteArray buff;
buff.resize(sizeof(tt));
memmove(buff.data(), &tt, sizeof(tt));

В чем сакральный смысл копирования структуры сперва в QByteArray, а затем отсылки этого же в сокет? Зачем эти не нужные промежуточные шаги?


Название: Re: Как записать структуру в QByteArray
Отправлено: Igors от Апрель 21, 2012, 11:32
В чем сакральный смысл копирования структуры сперва в QByteArray, а затем отсылки этого же в сокет? Зачем эти не нужные промежуточные шаги?
Возможно нужна длина пакета


Название: Re: Как записать структуру в QByteArray
Отправлено: navrocky от Апрель 21, 2012, 13:04
В чем сакральный смысл копирования структуры сперва в QByteArray, а затем отсылки этого же в сокет? Зачем эти не нужные промежуточные шаги?
Возможно нужна длина пакета

Какая длина пакета? Каким образом QByteArray может помочь с длиной пакета?


Название: Re: Как записать структуру в QByteArray
Отправлено: Igors от Апрель 21, 2012, 13:28
Какая длина пакета? Каким образом QByteArray может помочь с длиной пакета?
Записали структуру в QByteArray. Отослали сначала QByteArray.size(), потом сами данные. Так часто приходится делать (и не только с сокетами), т.к. на приемник должен знать сколько читать.


Название: Re: Как записать структуру в QByteArray
Отправлено: navrocky от Апрель 21, 2012, 21:39
В приведенном выше коде я этого не видел. Да и size можно передавать без QByteArray.


Название: Re: Как записать структуру в QByteArray
Отправлено: Syveren от Апрель 24, 2012, 15:04
Зачем вообще записывать структуру сначала в QByteArray, а потом конвертить в char*.
Не легче ли сразу написать:
udp->writeDatagram(reinterpret_cast<char *>(&tt),56,QHostAddress("192.168.0.81"),9800);


Название: Re: Как записать структуру в QByteArray
Отправлено: Syveren от Апрель 24, 2012, 15:20
QByteArray вижу смысл использовать, если работать с QDataStream
Код
C++ (Qt)
QByteArray buff;
QDataStream stream(& buff, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
int len = stream.writeRawData(reinterpret_cast<char *>(&tt), sizeof(tt))
//Q_ASSERT(len  == sizeof(tt))
 
... и передавать buf.data();
П.С. как сказали выше, не забываем о выравнивании структур в памяти...