Что делает ntohs() в pcap?

Я прочитал документацию по одному из ответов:

Функция ntohs принимает 16-разрядное число в сетевом порядке байтов TCP/IP (семейство адресов AF_INET или AF_INET6) и возвращает 16-разрядное число в порядке байтов хоста.

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

Ответ 1

Число 1000 в двоичном формате 1111101000.

Если это в 16-битном двоичном номере, то 0000001111101000.

Если это разделено на два 8-битных байта, то два байта со значениями 00000011 и 11101000.

Эти два байта могут быть в двух разных порядках:

  • В байтовом порядке "big-endian" байт, содержащий верхние 8 бит, является первым, а байт с младшими 8 битами является вторым, поэтому первый байт равен 00000011, а второй байт равен 11101000.
  • В байтовом порядке "little-endian" байт, содержащий младшие 8 бит, является первым, а байт, содержащий верхние 8 бит, является вторым, поэтому первый байт равен 11101000, а второй байт равен 00000011.

В байт-адресуемой машине аппаратное обеспечение может быть "big-endian" или "little-endian", в зависимости от того, какой байт хранится на более низком адресе в памяти. Большинство персональных компьютеров малоподобны; более крупные компьютеры поставляются как с большими, так и с небольшими рядами, с несколькими более крупными компьютерами (например, мэйнфреймами IBM и компьютерами среднего уровня и серверами SPARC), которые являются большими.

Большинство сетей являются битовыми, поэтому биты передаются один за другим. Биты байта могут сначала передаваться с самым значительным или наименее значимым битом, но сетевое оборудование скрывает эти детали от процессора. Тем не менее, они будут передавать байты в том порядке, в котором они находятся в памяти хоста, поэтому, если машина маленького конца передает данные на машину большого конца, число, которое передается машиной маленького конца, будет выглядеть по-разному на получение крупноформатной машины; эти различия не скрываются сетевым оборудованием.

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

  • должен быть выбран "стандартный" порядок байтов, а машинам, использующим другой порядок байтов, нужно перемещать байты многобайтовых чисел, чтобы они не находились в стандартном байтовом порядке машины, прежде чем передавать данные, перемещайте их так, чтобы они находились в стандартном байтовом порядке машины после получения данных;
  • двум машинам необходимо согласовать конкретный порядок байтов для сеанса (например, для протокола окклюзии сети X11, начальное сообщение от клиента на сервер указывает порядок байтов для использования);
  • сообщения протокола должны указывать используемый порядок байтов (как это делается с DCE RPC, например, протокол, используемый для "Microsoft RPC" );
  • принимающей машине необходимо как-то правильно угадать порядок байтов (я не знаю ни одного из используемых в настоящее время протоколов, если это было сделано, но старый протокол "talk" BSD не использовал ни один из методов, описанных выше, и реализация на Sun386i должна была использовать его для обработки как мобильных компьютеров Motorola 68K, так и малоинтенсивных процессоров Intel x86).

Различные интернет-протоколы используют первую стратегию, указав big-endian как порядок байтов; он упоминается как "порядок сетевого байта" в различных RFC. (Протокол доступа к файлам Microsoft SMB также использует первую стратегию, но указывает на мало-endian.)

Таким образом, "порядок байтов сети" является большим. "Порядок байтов хоста" - это порядок байтов используемой вами машины; он может быть big-endian, и в этом случае ntohs() просто возвращает значение, которое вы ему дали, или оно может быть малозначным, и в этом случае ntohs() заменяет два байта значения, которое вы ему дали, и возвращает это значение. Например, на машине большого конца ntohs(1000) будет возвращать 1000, а на машине с маленьким порядком ntohs(1000) будет заменять байты верхнего и младшего порядка, давая 1110100000000011 в двоичном формате или 59395 в десятичном значении.