Предположим, мы писали сетевое приложение на C ++ с использованием сокетов UDP. Нам нужно было передать небольшой пакет данных, поэтому мы использовали такую структуру, чтобы убедиться, что порядок байтов является сетевым:
struct [[gnu::packed]] datagram {
uint64_t timestamp;
uint8_t type;
uint32_t temperatures[60]; // whatever, just an example
uint8_t raw_data[];
};
Мы использовали GNU GCC, поэтому мы воспользовались нестандартными функциями C ++, такими как
Нам нужна упакованная структура, так как мы не хотим, чтобы между ними было заполнение, поскольку это может зависеть от архитектуры, и наша сетевая программа может работать на разных архитектурах.
Затем, через год, может получиться, что нам нужно поддерживать компилятор без GCC, который их не поддерживает.
Возможно ли это сделать в стандартном C ++?
Конечно, я знаю, что мы могли бы просто использовать uint8_t buffer[SOME_SIZE]
и memcpy для каждой части дейтаграммы, но это звучит как отличный способ создать ужасный, действительно уродливый код.
[[gnu::packed]]
это ужасный способ сделать сериализацию между произвольными архитектурами. Есть еще машины с прямым порядком байтов.
Правильный способ сделать это — определить формат сериализации в виде октетов, а затем выполнить преобразование между потоком октетов (в или из сокета UDP) и хорошо организованной структурой.
Есть много библиотек, которые делают это просто. Мы используем protobuf
на работе; у предыдущего работодателя было домашнее решение. (Обратите внимание, что запрос рекомендации для такой библиотеки явно не по теме для переполнения стека.)
Других решений пока нет …