Упаковка и распаковка данных из IP-пакетов - такая же старая проблема, как и сам Интернет (на самом деле, более старый).
Различные архитектуры компьютеров имеют разные схемы представления целых чисел, что может вызвать проблемы при обмене данными между компьютерами.
По этой причине стек IP стандартизируется для кодирования целых чисел в «порядке байтов сети» (что в основном означает самый старший байт первым).
Существуют стандартные функции для преобразования значений в порядке байтов сети внативные типы и наоборот.Я настоятельно рекомендую вам использовать их, так как ваш код будет более переносимым.
Кроме того, имеет смысл абстрагировать представления данных с точки зрения программы.Компиляторы c ++ могут выполнять преобразования очень эффективно.
Пример:
#include <arpa/inet.h>
#include <cstring>
#include <cstdint>
typedef struct WEATHER_STRUCT
{
std::int8_t packetID;
std::uint16_t packetSize;
std::uint8_t subPacketID;
std::uint16_t subPacketOffset;
} weather_struct;
const std::int8_t* populate(weather_struct& target, const std::int8_t* source)
{
auto get16 = [&source]
{
std::uint16_t buf16;
std::memcpy(&buf16, source, 2);
source += 2;
return ntohs(buf16);
};
target.packetID = *source++;
target.packetSize = get16();
target.subPacketID = *source++;
target.subPacketOffset = get16();
return source;
}
uint8_t* serialise(uint8_t* target, weather_struct const& source)
{
auto write16 = [&target](std::uint16_t val)
{
val = ntohs(val);
std::memcpy(target, &val, 2);
target += 2;
};
*target++ = source.packetID;
write16(source.packetSize);
*target++ = source.subPacketID;
write16(source.subPacketOffset);
return target;
}
https://linux.die.net/man/3/htons
вот ссылка на версию C ++ 17 выше:
https://godbolt.org/z/oRASjI
Еще одно примечание о стоимости преобразования:
Данные, поступающие в вашу программу или покидающие ее, - это событие, которое происходит один раз для каждой полезной нагрузки.Принятие затрат на конвертацию здесь влечет за собой незначительное наказание.
Как только данные поступили в вашу программу или до того, как они ушли, они могут многократно манипулироваться вашим кодом.
Некоторые архитектуры процессоров страдаютогромные потери производительности при доступе к данным, если данные не выровнены по естественным границам слова.Вот почему существуют такие атрибуты, как packed
- компилятор делает все возможное, чтобы избежать смещения данных.Использование упакованного атрибута равносильно преднамеренному указанию компилятору создавать очень неоптимальный код.
По этой причине я бы рекомендовал не использовать упакованные структуры (например, __attribute__((packed))
и т. Д.) Для данных, на которые ссылается программалогика.
По сравнению с ОЗУ сети на много порядков медленнее.Незначительное снижение производительности (буквально наносекунды) в точке кодирования или декодирования сетевого пакета несущественно по сравнению со стоимостью его фактической передачи.
Структуры упаковки могут вызвать ужасные проблемы с производительностью в программном коде и часто приводят к переносимостиголовные боли.