Сетевая упаковка данных - PullRequest
       8

Сетевая упаковка данных

1 голос
/ 11 сентября 2011

Я искал способ эффективно упаковать свои данные, чтобы отправить их по сети.Я нашел тему, которая предложила способ: http://www.sdltutorials.com/cpp-tip-packing-data

И я также видел, что он используется в коммерческих приложениях.Поэтому я решил попробовать, но результаты оказались не такими, как я ожидал.

  1. Прежде всего, весь смысл «упаковки» ваших данных заключается в сохранении байтов.Но я не думаю, что упомянутый выше алгоритм вообще экономит байты.Потому что без упаковки ... Сервер будет отправлять 4 байта (данных), после упаковки сервер отправляет массив символов длиной 4 байта ... Так что это бессмысленно.

  2. В сторонуИсходя из этого, зачем кому-то добавлять 0xFF, он вообще ничего не делает.

Фрагмент кода, найденный в упомянутом выше уроке:

    unsigned char Buffer[3];
    unsigned int Data = 1024;
    unsigned int UpackedData;
    Buffer[0] = (Data >> 24) & 0xFF;
    Buffer[1] = (Data >> 12) & 0xFF;
    Buffer[2] = (Data >> 8) & 0xFF;
    Buffer[3] = (Data ) & 0xFF;
    UnpackedData = (Buffer[0] << 24) | (Buffer[1] << 12) | (Buffer[2] << 8) | (Buffer[3] & 0xFF);

Результат: 0040 // Длина символа 4 байта 1024 // Длина 4 байта

Ответы [ 3 ]

3 голосов
/ 11 сентября 2011

& 0xFF - чтобы убедиться, что он находится между 0 и 255.

Я бы не стал слишком доверять этой публикации;Помимо вашего возражения, код содержит очевидную ошибку.Buffer имеет длину всего 3 элемента, но код хранит данные в 4 элементах.

3 голосов
/ 11 сентября 2011

Для целых чисел простой метод, который я нашел часто полезным, - это кодирование BER.В основном для целого числа без знака вы пишете 7 битов для каждого байта, используя 8-й бит, чтобы отметить, требуется ли еще один байт

void berPack(unsigned x, std::vector<unsigned char>& out)
{
    while (x >= 128)
    {
        out.push_back(128 + (x & 127)); // write 7 bits, 8th=1 -> more needed
        x >>= 7;
    }
    out.push_back(x); // Write last bits (8th=0 -> this ends the number)
}

для целого числа со знаком, вы кодируете знак в младшем значащем бите и используетета же кодировка, что и раньше

void berPack(int x, std::vector<unsigned char>& out)
{
    if (x < 0) berPack((unsigned(-x) << 1) + 1, out);
          else berPack((unsigned(x) << 1), out);
}

При таком подходе небольшие числа будут занимать меньше места.Другое преимущество состоит в том, что это кодирование уже не зависит от архитектуры (т. Е. Данные будут правильно пониматься независимо от порядкового номера системы) и что один и тот же формат может обрабатывать различные целочисленные размеры, и вы можете отправлять данные из 32-битной системы в64-битная система без проблем (при условии, конечно, что сами значения не переполняются).

Цена, которую нужно заплатить, это, например, значения без знака от 268435456 (1 << 28) до 4294967295 ((1 << 32)) - 1) потребуется 5 байтов вместо 4 байтов стандартной фиксированной 4-байтовой упаковки. </p>

2 голосов
/ 11 сентября 2011
  1. Другая причина упаковки заключается в обеспечении согласованной структуры, чтобы данные, записанные на одной машине, могли надежно считываться другой.

  2. Это не "добавление«;он выполняет побитовое И для того, чтобы замаскировать младший байт (младший байт).Но это не выглядит необходимым здесь.

...