Russian Qt Forum
Май 03, 2024, 07:45 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Выравнивание полей структуры  (Прочитано 15320 раз)
Vladimir
Крякер
****
Offline Offline

Сообщений: 305



Просмотр профиля
« : Сентябрь 07, 2011, 16:05 »

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

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


И непонятно почему нормально работает, если name до 28 символов, а потом только 32, 36, 40 и т.д. ?? В замешательстве
« Последнее редактирование: Сентябрь 07, 2011, 16:27 от Vladimir » Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4727



Просмотр профиля WWW
« Ответ #1 : Сентябрь 07, 2011, 22:37 »

попробуй объявить структуру так:
Код
C++ (Qt)
#pragma pack(1)
struct head
{
 quint32 size;
 quint32 tit;
 char name[1024];
}
#pragma pack()
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Сентябрь 08, 2011, 01:56 »

В данном конкретном случае все выравнивания дадут один и тот же результат (такой же как и без всякого выравнивания)

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

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

Сообщений: 305



Просмотр профиля
« Ответ #3 : Сентябрь 08, 2011, 09:23 »

попробуй объявить структуру так:
Код
C++ (Qt)
#pragma pack(1)
struct head
{
 quint32 size;
 quint32 tit;
 char name[1024];
}
#pragma pack()

Что-то похожее делал - не помогло  Обеспокоенный и так тоже не работает..
Записан
brankovic
Гость
« Ответ #4 : Сентябрь 08, 2011, 09:32 »

Igors может выразился непонятно.. Не надо передавать структуру целиком, не надо ломать выравнивание (из-за этого сегфолты бывают). Это всё равно ничего не даст, поскольку порядок байт в quint32 и прочих типах зависит от архитектуры.

А надо нормально сериализовать её по одному полю, size, tit, name. Вместо массива лучше использовать QString.
« Последнее редактирование: Сентябрь 08, 2011, 12:07 от brankovic » Записан
Vladimir
Крякер
****
Offline Offline

Сообщений: 305



Просмотр профиля
« Ответ #5 : Сентябрь 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);
 
Записан
ddrtn
Гость
« Ответ #6 : Сентябрь 08, 2011, 09:49 »

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

Как заполняете name?
Записан
brankovic
Гость
« Ответ #7 : Сентябрь 08, 2011, 09:55 »

Если другая ошибка, то какая?!

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

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

практика показывает, что по-другому плохо
Записан
Vladimir
Крякер
****
Offline Offline

Сообщений: 305



Просмотр профиля
« Ответ #8 : Сентябрь 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, то нормально..
Записан
ddrtn
Гость
« Ответ #9 : Сентябрь 08, 2011, 10:25 »

Код:
QString str;
//......................................
strcpy(objHead.name, str.toLocal8Bit().data());

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

Сообщений: 305



Просмотр профиля
« Ответ #10 : Сентябрь 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()

Записан
Vladimir
Крякер
****
Offline Offline

Сообщений: 305



Просмотр профиля
« Ответ #11 : Сентябрь 08, 2011, 10:30 »

Код:
QString str;
//......................................
strcpy(objHead.name, str.toLocal8Bit().data());

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

В общем здесь много говорилось про сериализацию - надо почитать  Улыбающийся а то я смутно представляю что это такое, помню когда-то сериализовали элементы интерфейса на Java, но это было давно..Как это делается на Qt пока не представляю  В замешательстве
Записан
BRE
Гость
« Ответ #12 : Сентябрь 08, 2011, 10:33 »

А все через тот же QDataStream. Подмигивающий
Записан
Vladimir
Крякер
****
Offline Offline

Сообщений: 305



Просмотр профиля
« Ответ #13 : Сентябрь 08, 2011, 10:55 »

Надо без QDataStream.. Подскажите, где можно почитать про сериализацию в Qt, что-то не могу ничего толкового найти Плачущий
Записан
BRE
Гость
« Ответ #14 : Сентябрь 08, 2011, 11:04 »

http://doc.qt.nokia.com/4.7/datastreamformat.html
Но первое же предложение тебя удивит.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.123 секунд. Запросов: 22.