Russian Qt Forum

Qt => Вопросы новичков => Тема начата: Vladimir от Сентябрь 07, 2011, 16:05



Название: Выравнивание полей структуры
Отправлено: Vladimir от Сентябрь 07, 2011, 16:05
Добрый день! Подскажите пожалуйста каким образом можно выровнять структуру, чтобы корректно ее передать по сети..

Код:
struct head
{
  quint32 size;
  quint32 tit;
  char name[1024];
}


И непонятно почему нормально работает, если name до 28 символов, а потом только 32, 36, 40 и т.д. ?? :-\


Название: Re: Выравнивание полей структуры
Отправлено: kambala от Сентябрь 07, 2011, 22:37
попробуй объявить структуру так:
Код
C++ (Qt)
#pragma pack(1)
struct head
{
 quint32 size;
 quint32 tit;
 char name[1024];
}
#pragma pack()


Название: Re: Выравнивание полей структуры
Отправлено: Igors от Сентябрь 08, 2011, 01:56
В данном конкретном случае все выравнивания дадут один и тот же результат (такой же как и без всякого выравнивания)

И непонятно почему нормально работает, если name до 28 символов, а потом только 32, 36, 40 и т.д. ?? :-\
Другая ошибка (никак не связанная с выравниванием)

Этот этап проходят все, и вначале всем кажется что стоит немного повозиться чтобы потом записать одной строкой напр так
Код
C++ (Qt)
file.write(&theHead, sizeof(head));
 
Но рано или поздно все равно приходится писать/передавать каждый член структуры. Поэтому лучше рано  :)


Название: Re: Выравнивание полей структуры
Отправлено: Vladimir от Сентябрь 08, 2011, 09:23
попробуй объявить структуру так:
Код
C++ (Qt)
#pragma pack(1)
struct head
{
 quint32 size;
 quint32 tit;
 char name[1024];
}
#pragma pack()

Что-то похожее делал - не помогло  :-[ и так тоже не работает..


Название: Re: Выравнивание полей структуры
Отправлено: brankovic от Сентябрь 08, 2011, 09:32
Igors может выразился непонятно.. Не надо передавать структуру целиком, не надо ломать выравнивание (из-за этого сегфолты бывают). Это всё равно ничего не даст, поскольку порядок байт в quint32 и прочих типах зависит от архитектуры.

А надо нормально сериализовать её по одному полю, size, tit, name. Вместо массива лучше использовать QString.


Название: Re: Выравнивание полей структуры
Отправлено: Vladimir от Сентябрь 08, 2011, 09:33
В данном конкретном случае все выравнивания дадут один и тот же результат (такой же как и без всякого выравнивания)

И непонятно почему нормально работает, если name до 28 символов, а потом только 32, 36, 40 и т.д. ?? :-\
Другая ошибка (никак не связанная с выравниванием)

Этот этап проходят все, и вначале всем кажется что стоит немного повозиться чтобы потом записать одной строкой напр так
Код
C++ (Qt)
file.write(&theHead, sizeof(head));
 
Но рано или поздно все равно приходится писать/передавать каждый член структуры. Поэтому лучше рано  :)

Если другая ошибка, то какая?!А если большая структура, то наверное не очень рационально передавать отдельно каждое поле..Действитеьно, передаю похожим образом, только предварительно записываю в QByteArray:

Код:
head objHead;
QByteArray arrBl;

arrBl.append((const char*)&objHead,sizeof(objHead));
m_pTcpSocket->write(arrBl);
 


Название: Re: Выравнивание полей структуры
Отправлено: ddrtn от Сентябрь 08, 2011, 09:49
И непонятно почему нормально работает, если name до 28 символов, а потом только 32, 36, 40 и т.д. ?? :-\

Как заполняете name?


Название: Re: Выравнивание полей структуры
Отправлено: brankovic от Сентябрь 08, 2011, 09:55
Если другая ошибка, то какая?!

чтобы понять нужен код упаковки и распаковки

А если большая структура, то наверное не очень рационально передавать отдельно каждое поле..

практика показывает, что по-другому плохо


Название: Re: Выравнивание полей структуры
Отправлено: Vladimir от Сентябрь 08, 2011, 10:01

Как заполняете name?
[/quote]

Наверое не очень правильно..:
QString str;
for(...)
{
   objHead.name[k] = str.at(i).toAscii();
}
Желательно использовать наверное strcpy(), но что-то не получается у меня впихнуть туда и массив и QString..
Хотя, если пишу банально
for(int  k=0; k < 29; k++)
{
   objHead.name[k] = 'e';
}
тоже не работает... а если 27, то нормально..


Название: Re: Выравнивание полей структуры
Отправлено: ddrtn от Сентябрь 08, 2011, 10:25
Код:
QString str;
//......................................
strcpy(objHead.name, str.toLocal8Bit().data());

Но, действительно, лучше воспользоваться сериализацией. если неохота в столбик запихивать в датастрим все поля по-очереди, то можно воспользоваться сериализацией наследников QObject или данные хранить в QVariantMap.


Название: Re: Выравнивание полей структуры
Отправлено: Vladimir от Сентябрь 08, 2011, 10:25
Если другая ошибка, то какая?!

чтобы понять нужен код упаковки и распаковки

Киент передает

Код:
void FormCl::slotSendToServerFile()
{
QFile file(wayFile);
QByteArray  arrBlock, arrBlockText, arrBlockNameFile;

headl objHead;
objHead.titMsg = 2;

int pos, k, i;

for(int i = wayFile.size()-1, j = 0; wayFile.at(i) != '/'; i--, j++)
{
pos = j;
objHead.nameFile[i] = NULL;
}
for(i = wayFile.size()-1 - pos, k = 0; k < pos + 1; i++, k++)
    objHead.nameFile[k] = wayFile.at(i).toAscii();
   
// чтение из файла
if(file.open(QIODevice::ReadOnly))
{
            objHead.sizeData = file.size();
            arrBlockText = file.read(objHead.sizeData);
            arrBlock.append((const char*)&objHead, sizeof(objHead));
            arrBlock.append(arrBlockText);
   
    m_pTcpSocket->write(arrBlock);

            file.close();
}
}

Сервер принимает

Код:

......

 while(true)
{
if(tcpSocket->state() == QAbstractSocket::ClosingState)
break;

if(tcpSocket->waitForReadyRead(3000))  // bytesAvailable()
{
  if(!flag) // false
  {  // читаем переданную стуктуру!                               
     retrRead = tcpSocket->read((char*)&objHead,sizeof(objHead));
if( retrRead == -1) 
     break;
if( retrRead == 0)
break;
   }
 
  switch(objHead.titMsg)
  {
case 1: // передается сообщение
             {
  .....
  break;
     }
case 2: // передается файл
     {
          // запись в файл
      QFile file(objHead.nameFile);
  if(file.open(QIODevice::WriteOnly))
               {
       if(tcpSocket->bytesAvailable() != objHead.sizeData)
   {
     flag = true;
     continue;
   }

   arrBlockText = tcpSocket->read(objHead.sizeData);

   file.write(arrBlockText);
   emit MessageClient(tcpSocket, "<b>\nSize file: </b>"  + QString().setNum(objHead.sizeData) + " Byte", 2);
   emit msgToGUI(QTime::currentTime().toString()+" <b>File is sent</b>",2);
                           flag = false;
   file.close();
   }
  else {
      if(tcpSocket->bytesAvailable() != objHead.sizeData)
       {
     flag = true;
             continue;
       }

  tcpSocket->read(objHead.sizeData);
  flag = false;
  msgToGUI("<b>Error</b> of the determination of the file!",4);
       }
  break;
}
default:
{
    continue;
     }
  } // switch()
} // waitForReadyRead()
} // while()



Название: Re: Выравнивание полей структуры
Отправлено: Vladimir от Сентябрь 08, 2011, 10:30
Код:
QString str;
//......................................
strcpy(objHead.name, str.toLocal8Bit().data());

Но, действительно, лучше воспользоваться сериализацией. если неохота в столбик запихивать в датастрим все поля по-очереди, то можно воспользоваться сериализацией наследников QObject или данные хранить в QVariantMap.

В общем здесь много говорилось про сериализацию - надо почитать  :) а то я смутно представляю что это такое, помню когда-то сериализовали элементы интерфейса на Java, но это было давно..Как это делается на Qt пока не представляю  :-\


Название: Re: Выравнивание полей структуры
Отправлено: BRE от Сентябрь 08, 2011, 10:33
А все через тот же QDataStream. ;)


Название: Re: Выравнивание полей структуры
Отправлено: Vladimir от Сентябрь 08, 2011, 10:55
Надо без QDataStream.. Подскажите, где можно почитать про сериализацию в Qt, что-то не могу ничего толкового найти :'(


Название: Re: Выравнивание полей структуры
Отправлено: BRE от Сентябрь 08, 2011, 11:04
http://doc.qt.nokia.com/4.7/datastreamformat.html
Но первое же предложение тебя удивит.


Название: Re: Выравнивание полей структуры
Отправлено: Vladimir от Сентябрь 08, 2011, 11:16
http://doc.qt.nokia.com/4.7/datastreamformat.html
Но первое же предложение тебя удивит.


Ну да) значит, сериализация в Qt - это и есть сохранение объектов в QDataStream?


Название: Re: Выравнивание полей структуры
Отправлено: ddrtn от Сентябрь 08, 2011, 11:27
Кстати, кто будет принимать данные на той стороне? какие ограничения на формат передаваемых данных накладывает приемник?
а то можно воспользоваться более обобщенным транспортом. например JSON или XML.. даже если принимающая сторона требует только бинарные данные, то все равно должен быть договор о структуре: порядок байт, размеры типов и пр. в любом случае пересылать структуру как есть нецелесообразно.



Название: Re: Выравнивание полей структуры
Отправлено: BRE от Сентябрь 08, 2011, 11:45
сериализация в Qt - это и есть сохранение объектов в QDataStream?
Эээ, а ты правильно понимаешь сам процесс?
В QDataStream ничего сохранить нельзя, он по сути сам "сохраняльшик в...".
С его помощью можно сохранять данные в разные контейнеры, будь то файл, QByteArray, QBuffer...


Название: Re: Выравнивание полей структуры
Отправлено: Vladimir от Сентябрь 08, 2011, 12:35
Кстати, кто будет принимать данные на той стороне? какие ограничения на формат передаваемых данных накладывает приемник?
а то можно воспользоваться более обобщенным транспортом. например JSON или XML.. даже если принимающая сторона требует только бинарные данные, то все равно должен быть договор о структуре: порядок байт, размеры типов и пр. в любом случае пересылать структуру как есть нецелесообразно.



Ура))
strcpy(objHead.name, str.toLocal8Bit().data());
решила все мои проблемы... пока!  :D СПАСИБО! С toLocal8Bit().data() пробовал делать, но не так ((

Что касается формата, то должно передаваться все: от .txt до mp3! В общем все) остальные предложения учту..


Название: Re: Выравнивание полей структуры
Отправлено: Vladimir от Сентябрь 08, 2011, 12:48
сериализация в Qt - это и есть сохранение объектов в QDataStream?
Эээ, а ты правильно понимаешь сам процесс?
В QDataStream ничего сохранить нельзя, он по сути сам "сохраняльшик в...".
С его помощью можно сохранять данные в разные контейнеры, будь то файл, QByteArray, QBuffer...

Мг..Понятно..А если скажем по-другому: "сериализация в Qt - это и есть сохранение объектов при помощи QDataStream?"