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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Вопрос по работе с QDataStream?  (Прочитано 11851 раз)
studert
Гость
« : Декабрь 08, 2008, 13:49 »

Получаю данные с сокета в QbyteArray, далее необходимо эти данные "разложить по полочкам", то есть по разным переменным:

QByteArray datagramOut,datagramIn;
QDataStream datagramOutStream(&datagramOut, QIODevice::WriteOnly);
QDataStream datagramInStream(&datagramIn, QIODevice::ReadOnly);
читаю данные:
udpSocket.readDatagram(datagramIn.data(),datagramIn.size());
раскладываю по полочкам:
datagramInStream>>temp>>ReceivedFrameType>>ReceivedCommand>>ReceivedOperationMode
    >>ReceivedPacketNumber>>ReceivedWindowWidth>>ReceivedWindowHeight>>ReceivedFirstRow
    >>ReceivedLastRow;
потом читаю новые данные в datagramIn, далее необходимо снова разложить по полочкам данные, но как я понял qdataInStream указывает на ту позицию в которой закончили читать предыдущие данные. Можно ли сбросить поток к началу новых данных? Или придется "ручками" побайтно разбирать QbyteArray и "раскладывать по полочкам".
Записан
Rcus
Гость
« Ответ #1 : Декабрь 08, 2008, 14:05 »

Код
C++ (Qt)
bool QIODevice::reset ()   [virtual]
bool QIODevice::seek ( qint64 pos )   [virtual]

А еще можно каждый раз создавать QDataStream заново Улыбающийся
Записан
studert
Гость
« Ответ #2 : Декабрь 09, 2008, 09:29 »

Не пинайте сильно за тупые вопросы, но что-то я не понимаю как использовать функцию reset() или seek(), она же применима к объекту QIODevice, а я использую QDataStream и QbyteArray.
По поводу второго совета, мне тоже приходила идея создавать каждый раз заново QDataStream, но я собираюсь многократно (483 раза) его использовать. Как заменять объект новым не меняя имени? Нужно сначала убить старый?
Записан
BRE
Гость
« Ответ #3 : Декабрь 09, 2008, 09:46 »

По поводу второго совета, мне тоже приходила идея создавать каждый раз заново QDataStream, но я собираюсь многократно (483 раза) его использовать. Как заменять объект новым не меняя имени? Нужно сначала убить старый?
Код:
for( int i= 0; i < 483; ++i )
{
QDataStream ds;
...
}
Записан
studert
Гость
« Ответ #4 : Декабрь 09, 2008, 10:50 »

Но тогда объект будет существовать только внутри цикла, не писать же мне циклы до одного только ради того чтобы объект при завершинии одного действия уничтожился. Хотелось бы все же понять как обойтись без этого. Как все же сбросить его, не создавая заново.
Записан
BRE
Гость
« Ответ #5 : Декабрь 09, 2008, 11:43 »

Но тогда объект будет существовать только внутри цикла, не писать же мне циклы до одного только ради того чтобы объект при завершинии одного действия уничтожился. Хотелось бы все же понять как обойтись без этого. Как все же сбросить его, не создавая заново.
Код:
QByteArray datagramIn;
QList<Data> saveData;

for( int i = 0; i < 483; ++i )
{
    QDataStream datagramInStream(&datagramIn, QIODevice::ReadOnly);
    udpSocket.readDatagram(datagramIn.data(),datagramIn.size());
    // ... обработали данные
    data = ...
    // Сохранили
    saveData.append( data );
}

Но лучше делай все асинхронно (readyRead).  Улыбающийся
Записан
studert
Гость
« Ответ #6 : Декабрь 09, 2008, 13:36 »

Похоже я неясно выразился. Сейчас я сделал вот так:
QDataStream InStream1(&data, QIODevice::ReadOnly);
получил первый пакет
udpSock.readDatagram(data.data(),data.size());
QDataStream InStream1(&data, QIODevice::ReadOnly);
InStream1>>......
получил второй пакет
udpSock.readDatagram(data.data(),data.size());
QDataStream InStream2(&data, QIODevice::ReadOnly);
InStream2>>......
получил еще пакет
udpSock.readDatagram(data.data(),data.size());
QDataStream InStreamN(&data, QIODevice::ReadOnly);
InStreamN>>......
Поскольку идет последовательная обработка нескольких пакетов разного вида их не засунешь в цикл, и пришлось наплодить переменных. Хотел обойтись одной, только не знаю как ее возвращать в начало.
Записан
BRE
Гость
« Ответ #7 : Декабрь 09, 2008, 14:18 »

Поскольку идет последовательная обработка нескольких пакетов разного вида их не засунешь в цикл, и пришлось наплодить переменных. Хотел обойтись одной, только не знаю как ее возвращать в начало.
Так может ты немного про протокол расскажешь, хотя бы примерно.
Типа: 1 пакет - управляющий, в зависимости от типа, необходимо получить еще несколько пакетов (для одного типа - три, для другого - пять)...
Записан
Rcus
Гость
« Ответ #8 : Декабрь 09, 2008, 14:22 »

Интересно... я думал сообщения протокола UDP называются датаграммами не просто так: UDP не дает гарантию доставки, даже гарантии очередности получения нет
Записан
BRE
Гость
« Ответ #9 : Декабрь 09, 2008, 14:31 »

Ну чего-то человеку нужно получать/обрабатывать, поэтому самому интересно, что там эта железка шлет.
Записан
studert
Гость
« Ответ #10 : Декабрь 09, 2008, 14:56 »

Железка - фотокамера. Она принимает каманду запрос на съемку, затем команду на отправку кадра в ПК и отправляет нужное (прописано в команде) количество пакетов (один пакет строка изображения). Самая медленная операция в ПК - перерисовка изображения, поэтому сначала принимаю весь кадр (принимаю в течение 50 мсек), затем отрисовываю и перехожу к обработке пользовательских кнопок.
Записан
BRE
Гость
« Ответ #11 : Декабрь 09, 2008, 15:06 »

Железка - фотокамера. Она принимает каманду запрос на съемку, затем команду на отправку кадра в ПК и отправляет нужное (прописано в команде) количество пакетов (один пакет строка изображения). Самая медленная операция в ПК - перерисовка изображения, поэтому сначала принимаю весь кадр (принимаю в течение 50 мсек), затем отрисовываю и перехожу к обработке пользовательских кнопок.
Так ты от камеры принимаешь строки кадра. Почему их прием нельзя засунуть в цикл?
Записан
studert
Гость
« Ответ #12 : Декабрь 09, 2008, 20:19 »

Тут даже считать не надо Улыбающийся каждый пакет содержит номер строки. Логичным было бы дожидаться пока не получишь последнюю строку и выходить, в том то и проблема, что строки теряются, как написать правильно, чтобы этого не было не знаю.
Записан
BRE
Гость
« Ответ #13 : Декабрь 09, 2008, 20:35 »

Тут даже считать не надо Улыбающийся каждый пакет содержит номер строки. Логичным было бы дожидаться пока не получишь последнюю строку и выходить, в том то и проблема, что строки теряются, как написать правильно, чтобы этого не было не знаю.
Ну а если попробовать получать и сохранять пакеты "сырыми" данными, а после разбирать то что принял.
Количество строк известно. Что-то типа:
Код:
QList<QByteArray*> frame;
for( int line = 0; line < lineCount; ++line )
{
    QByteArray *dataIn = new QByteArray( pendingDatagramSize, 0 );
    udpSocket.readDatagram( dataIn->data(), dataIn->size() );
    frame.append( dataIn );
}
А потом спокойно разобрать все строки.
« Последнее редактирование: Декабрь 09, 2008, 20:37 от BRE » Записан
studert
Гость
« Ответ #14 : Декабрь 10, 2008, 11:54 »

Ну а если попробовать получать и сохранять пакеты "сырыми" данными, а после разбирать то что принял.
Количество строк известно. Что-то типа:
Код:
QList<QByteArray*> frame;
for( int line = 0; line < lineCount; ++line )
{
    QByteArray *dataIn = new QByteArray( pendingDatagramSize, 0 );
    udpSocket.readDatagram( dataIn->data(), dataIn->size() );
    frame.append( dataIn );
}
А потом спокойно разобрать все строки.
У меня сделано так:

           
Код
C++ (Qt)
FrameReceiveTime.start();
while(FrameReceiveTime.elapsed() <= 100){
if(udpSocket.hasPendingDatagrams()){
QDataStream datagramInStream3(&datagramIn, QIODevice::ReadOnly);
datagramIn.resize(udpSocket.pendingDatagramSize());
udpSocket.readDatagram(datagramIn.data(),datagramIn.size());
datagramInStream3>>temp>>ReceivedFrameType>>RowNumber;
if(ReceivedFrameType == 0x44415441){
for(quint32 i=RowNumber*(WindowWidth->value()/3 + (WindowWidth->value()%3 != 0));
i<(RowNumber+1)*(WindowWidth->value()/3 + (WindowWidth->value()%3 != 0));i++)
    datagramInStream3>>monitor->Data[i];
  }
}
}
           Внутри цикла я только проверяю поле ReceivedFrameType (подходят полько пакеты с 0х44415441) и переписываю строки в соответствующие элементы массива monitor, после завершения цикла отрисовываю.
           Я попробую так как предложили вы, только внутри цикла for необходимо добавить waitForReadyRead(1), чтобы читать только при наличии пакета, но мне кажется что особого эффекта это не даст, поскольку обработка строк у меня минимальная, зато потом полученный массив снова обрабатывать (выкинуть "левые" пакеты, поменять местами согласно номерам строк) перед отрисовкой. Перепишу и сравню.
« Последнее редактирование: Декабрь 10, 2008, 11:57 от pastor » Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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