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


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

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

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

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

В обсуждении "64 bit ntohl() in 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; 
} 

Библиографический список



Найдите ошибки в своем C, C++, C# и Java коде

Предлагаем попробовать проверить код вашего проекта с помощью анализатора кода PVS-Studio. Одна найденная в нём ошибка скажет вам о пользе методологии статического анализа кода больше, чем десяток статей.

goto PVS-Studio;



Найденные ошибки

Проверено проектов
367
Собрано ошибок
13 552

А ты совершаешь ошибки в коде?

Проверь с помощью
PVS-Studio

Статический анализ
кода для C, C++, C#
и Java

goto PVS-Studio;