Как обрабатывать поля внутри сетевых заголовков, длина которых не кратна 8 битам - PullRequest
0 голосов
/ 02 ноября 2019

Я только начал изучать программирование сокетов, и я пытаюсь реализовать протоколы TCP / UDP с использованием необработанных сокетов.

    IP Header
    0      7 8     15 16    23 24    31
    +--------+--------+--------+--------+
    |Ver.|IHL|DSCP|ECN|   Total length  |
    +--------+--------+--------+--------+
    |  Identification |Flags|   Offset  |
    +--------+--------+--------+--------+
    |   TTL  |Protocol| Header Checksum |
    +--------+--------+--------+--------+
    |         Source IP address         |
    +--------+--------+--------+--------+
    |       Destination IP address      |
    +--------+--------+--------+--------+

При записи заголовка IP, части Flags и Offset, длина Offset равнане кратно 8 бит. Поэтому я беру флаги и смещение вместе как единое целое.

uint8 flags = 0;
uint16 offset = htons(6000); // more than 1 byte, so we need to use htons

// in c, we can left(since it's in big endianness) shift offset 3 bit, 
// and then convert flags to uint16, and then merge them together

// in some other languages, for example, Haskell, 
// htons like functions may return a bytestring which is not an instance of Bit, 
// we need to unpack it back into a list of uint8 in order to use bitwise operations.

Этот метод не очень чистый, мне интересно, как обычно конструировать строку байтов, когда ее компоненты имеют длину более 1 байта, а ихПорядок байтов также необходимо учитывать.

1 Ответ

0 голосов
/ 02 ноября 2019

В C обычным способом было бы объявить временную переменную uint16_t, uint32_t или uint64_t, использовать побитовые операторы для сборки битов в этой переменной, а затем использовать htons() или htonl()чтобы преобразовать биты в сетевой (иначе-порядковый) порядок.

Например, поля Flags и Offset, взятые вместе, составляют 16-битное слово. Итак:

uint8_t flags   = /* some 3-bit value */;
uint16_t offset = /* some 13-bit value */;
uint16_t flagsAndOffsetBigEndian = htons(flags | (offset << 3));
memcpy(&header[16], &flagsAndOffsetBigEndian, sizeof(uint16_t));
...