Функции класса ntohl/htonl и 64-битные значения

Как известно, порядок байтов в целых числах, представленных более чем одним байтом, может быть разным на разных компьютерах. Существуют компьютерные системы, в которых старший байт числа имеет меньший адрес, чем младший байт (это так называемый порядок байтов с обратным порядком байтов), и есть компьютерные системы, в которых старший байт числа имеет более высокий адрес. чем младший байт (порядок байтов с прямым порядком байтов). При передаче целочисленных числовых данных от машины с одним порядком байтов к машине с другим порядком байтов мы можем ошибаться в интерпретации этой информации. Чтобы избежать этого, было введено понятие сетевого порядка байтов, т. е. порядка байтов, в котором должна быть представлена ​​числовая информация при передаче по сети (был выбран порядок байтов с обратным порядком байтов). Целочисленные числовые данные преобразуются из порядка байтов, принятого на компьютере-отправителе, в сетевой порядок байтов пользовательским процессом, затем они передаются по сети и преобразуются в порядок байтов, принятый на компьютере-получателе, процессом-получателем. . Для преобразования целых чисел из машинного порядка в сетевой и обратно используются четыре функции: htons(), htonl(), ntohs(), ntohl().

Описание функции:

  • Функция htonl преобразует целое число из порядка байтов, принятого на компьютере, в сетевой порядок байтов.
  • Функция htons преобразует целое короткое число из порядка байтов, принятого на компьютере, в сетевой порядок байтов.
  • Функция ntohl преобразует целое число из сетевого порядка байтов в порядок байтов, принятый на компьютере.
  • Функция ntohs преобразует целое короткое число из сетевого порядка байтов в порядок байтов, принятый на компьютере.

Перечисленные нами функции работают с 16-битными и 32-битными значениями. С появлением 64-битных систем возникла необходимость реализации функций для работы с 64-битными числами. В некоторых системах для этого существуют функции ntohll() и htonll(). Но в некоторых других системах таких функций нет. В этом случае вы можете реализовать этот механизм самостоятельно.

См. обсуждение 64-битный ntohl() в C++?, чтобы узнать о некоторых решениях преобразования 64-битных значений. Вот одно из таких решений.

#define TYP_INIT 0 
#define TYP_SMLE 1 
#define TYP_BIGE 2 
 
unsigned long long htonll(unsigned long long src) { 
  static int typ = TYP_INIT; 
  unsigned char c; 
  union { 
    unsigned long long ull; 
    unsigned char c[8]; 
  } x; 
  if (typ == TYP_INIT) { 
    x.ull = 0x01; 
    typ = (x.c[7] == 0x01ULL) ? TYP_BIGE : TYP_SMLE; 
  } 
  if (typ == TYP_BIGE) 
    return src; 
  x.ull = src; 
  c = x.c[0]; x.c[0] = x.c[7]; x.c[7] = c; 
  c = x.c[1]; x.c[1] = x.c[6]; x.c[6] = c; 
  c = x.c[2]; x.c[2] = x.c[5]; x.c[5] = c; 
  c = x.c[3]; x.c[3] = x.c[4]; x.c[4] = c; 
  return x.ull; 
}

использованная литература

Статья опубликована с разрешения автора.