Лучшая практика: как интерпретировать / обработать QDataStream?

Мне нужно обработать потоковые двоичные данные (QDataStream) определенной структуры, созданной другой не-Qt программой. Интересно, как лучше интерпретировать эти данные? Допустим, данные структурированы (дано определение структуры) в телеграммах следующим образом и не могут быть изменены мной самостоятельно:

4 байта заголовка | Порядковый номер 2 байта | 1 байтовая контрольная сумма | Данные 10 байтов

Я вижу следующие возможности для обработки данных в классе «Telegram»:

  1. Класс Telegram имеет приватную переменную-член QByteArray. Все данные (17 байт) считываются сразу из потока с помощью метода readRawData и сохраняются там. Переменные доступны и интерпретируются с помощью открытых методов, таких как return (array.at(4)<<8) + array.at(5) для порядкового номера, с не очень элегантно.
  2. Класс Telegram имеет открытую переменную-член char [17] в сочетании со структурой. Все данные читаются из потока с помощью readRawData и сохраняются там. При обращении к переменным после этого это делается только через структуру, например telegramstruct.squenceNumber Я вижу потенциальные проблемы с этим методом, такие как endianness и padding.
  3. Класс Telegram имеет закрытые переменные-члены для каждого из полей телеграммы, такие как QString strHeader, При чтении телеграмм из потока данные сохраняются непосредственно в этих переменных. Чтение осуществляется с помощью readRawData или с помощью оператора >> для основных типов.

Код должен быть максимально быстрым, так как для обработки требуется много данных. Я использую Qt 5.0.1 на Windows с MinGW.

Мои вопросы:

  • Какое из вышеперечисленных решений является наилучшим и быстрым, или есть лучший способ?
  • Читается ли все сразу как в 1 быстрее, чем чтение 4 байта, 2 байта, 1 байт, … как в 3?
  • С 1 и 3 я не могу использовать предоставленный заголовочный файл с определенной структурой, это будет плохой практикой?
  • Возможно ли как-то иметь «союз» с QByteArray и структурой?
  • Как бы я легко вычислил контрольную сумму с решением 3?

Большое спасибо за ваши мнения и советы.

Крис

1

Решение

Что ж, извините, у вас не так много времени для написания примеров кода, но я постараюсь дать краткие подсказки.
1) Проблема производительности. Как только у вас есть ограничения производительности, первое, что нужно оптимизировать, — это количество фактических чтений из потока, из которого поступают данные. Что бы это ни было File / Socket / etc, в любом случае это QIODevice. Поэтому первое, что нужно сделать, — это поддерживать некоторый QByteArray, в который вы добавляете все данные, доступные в QIODevice, при каждой попытке / обработке уведомления о получении данных. Поэтому ниже я предполагаю, что есть определенный QByteArray m_rawData, который содержит в настоящее время необработанные байты, которые могут быть некоторым количеством Telegrams + последняя телеграмма, которая может быть получена частично.

2) Я бы сделал класс, такой как Telegram, который содержит данные телеграммы, грубо говоря

class Telegram {
QString       header;
int           sequenceNumber;
unsigned char checkSum;
QByteArray    data;

...

bool          checkSumOK();  // check is checksum is OK for provided data

}

с конструкторами и операторами на ваш вкус (вы можете реализовать конструктор копирования / etc) ..
Тогда я бы расширил этот класс с ( <<>> операторы для поддержки QDataStream, который работает с временным буфером, упомянутым в части 1).

Таким образом, общая концепция заключается в том, что вы читаете данные из потока во временный буфер как можно скорее, а после того, как чтение завершено, вы извлекаете из полученного буфера как можно больше экземпляров Telegram. Затем вы работаете с QDataSteam, примененным к QByteArray, вы можете безопасно использовать вызовы чтения 4 байта, чтения 1 байта и т. Д., Не оказывая такого большого влияния на производительность, потому что в основном речь идет о смещении указателей.

3) Конечно, если вы говорите об экстремальных условиях … вы можете подумать о профсоюзах (как упоминалось в предыдущем ответе), чтобы сделать прямое копирование необработанных данных поверх выровненной структуры, но этот способ требует гораздо более тщательного программирования (особенно принимая во внимание рассмотрение арок x32 / x64, а также платформ с прямым и обратным порядком байтов)

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]