Привет, сетевой друг! Сегодня покажу, как можно сжимать IPv4-заголовки вручную на C++🟣В чём смысл: IPv4-заголовок - это всегда 20 байт (если без опций), и большая часть полей там почти не меняется. Вместо того чтобы передавать их каждый раз, мы сохраняем один эталон, а потом передаём только изменения. Это и есть дельта-сжатие.
🟣Как работает: Первый пакет метим как эталон
[0x00][ID][20 байт заголовка]
Все следующие — как дельта:
[0x01][ID][кол-во изменений][смещение_1][значение_1]...[смещение_N][значение_N]
На приёме просто восстанавливаем полный заголовок, применяя патчи к эталону
🟣Пример на C++: Условно, у нас есть два заголовка (вектор std::vector<uint8_t> по 20 байт). Второй отличается только TTL и длиной пакета. В этом случае дельта будет содержать всего пару байт отличий.
std::vector<uint8_t> baseHeader = ...; // эталон
std::vector<uint8_t> newHeader = ...; // новый
std::vector<uint8_t> delta = {0x01, 0x01}; // тип и ID
for (size_t i = 0; i < 20; ++i) {
if (baseHeader[i] != newHeader[i]) {
delta.push_back(i); // смещение
delta.push_back(newHeader[i]); // новое значение
}
}
delta.insert(delta.begin() + 2, delta.size() - 2); // количество изменений
🟣Восстановление на приёмнике:
std::vector<uint8_t> restored = baseHeader;
size_t count = delta[2];
for (size_t i = 0; i < count; ++i) {
size_t offset = delta[3 + i * 2];
uint8_t value = delta[3 + i * 2 + 1];
restored[offset] = value;
}
🟣Чем хорош подход: Это почти ничего не весит, легко дебажится и не требует сторонних библиотек. Работает хорошо, если трафик однотипный, например: ping, DNS или custom RPC.
🟣И да, не забываем следить за числом эталонов и временем жизни. Добавьте в дельту контрольную сумму, если боитесь ошибок. А ещё можно сделать автоудаление редко используемых шаблонов.
Серверная Админа | #Cplusplus