addr.sin6_addr = in6addr_any;
addr.sin6_port = htons(SOME_PORT_NUM);
Для обозначения адреса, замкнутого на себя (::1), в IPv6 предусмотрены константа IN6ADDR_LOOPBACK_INIT и переменная in6addr_loopback.
В отличие от IPv4, протокол IPv6 обеспечивает сетевой порядок следования байтов в своих константах и инициализаторах переменных. Но, как видно в вышеприведенном коде, все равно необходимо проверять порядок следования байтов в номере порта.
При одновременном использовании протоколов IPv4 и IPv6 на одном и том же компьютере они имеют общее пространство номеров портов. Это значит, что если, к примеру, приложение привязывает IPv6-сокет к TCP-порту под номером 2000 (с помощью универсального адреса), то IPv4-сокет с протоколом TCP не может подключиться к тому же порту. (Реализация TCP/IP следит за тем, чтобы сокеты на других сетевых узлах могли подключаться к нашему сокету вне зависимости от того, в рамках какого протокола они действуют — IPv4 или IPv6.)
Вместе с выходом IPv6 в программном интерфейсе сокетов появилась новая обобщенная структура под названием sockaddr_storage. Она имеет размер, достаточный для хранения адреса любого вида сокетов (то есть к этому типу можно привести любую структуру для хранения адресов сокетов). В частности, данная структура позволяет прозрачно хранить адреса сокетов в форматах IPv4 и IPv6, что позволяет избавиться от проверки версии протокола IP в нашем коде. В Linux структура sockaddr_storage имеет следующее определение:
#define __ss_aligntype uint32_t /* В 32-разрядных архитектурах */
struct sockaddr_storage {
sa_family_t ss_family;
__ss_aligntype __ss_align; /* Автоматическое выравнивание */
char __ss_padding[SS_PADSIZE]; /* Программные данные размером 128 байт */
};
Как мы уже говорили, компьютеры представляют IP-адреса и номера портов в двоичном виде, однако человеку легче запоминать имена, а не числа. К тому же символьное имя позволяет обеспечить косвенное обращение к сетевому узлу: изменение исходного числового значения не помешает использовать то же самое имя.
Адрес узла может быть представлен в виде двоичного значения, символьного имени или IP-формата (в IPv4 это десятичные числа, разделенные точками, а в IPv6 — шестнадцатеричная строка).
Номер порта можно представить в двоичном виде или с помощью символьного имени службы.
Для преобразования этих форматов существуют различные библиотечные функции. В данном разделе приводится их краткий обзор, а в следующем вы детально познакомитесь с современными программными интерфейсами (inet_ntop(), inet_pton(), getaddrinfo(), getnameinfo() и т. д.). В разделе 55.13 мы затронем устаревшие интерфейсы (inet_aton(), inet_ntoa(), gethostbyname(), getservbyname() и т. д.).
Функции inet_aton() и inet_ntoa() приводят IPv4-адрес, записанный в виде разделенных точками десятичных чисел, в двоичный формат (и наоборот). Мы упоминаем их потому, что они встречаются в старом коде. На сегодняшний день они считаются устаревшими. Функции для выполнения аналогичных преобразований, которые следует использовать в современных программах, описаны ниже.
Функции inet_pton() и inet_ntop() аналогичны функциям inet_aton() и inet_ntoa(), но поддерживают работу с IPv6-адресами. Они позволяют переводить IPv4- и IPv6-адреса в
Людям привычнее иметь дело с именами, чем с числами, в связи с чем данные функции используются в программах лишь изредка. Одно из применений inet_ntop() состоит в создании версии IP-адреса, которую можно записать в журнал. Иногда это является более подходящим вариантом, чем конвертация IP-адреса в имя узла, поскольку:
• преобразование IP-адреса в имя сетевого узла требует обращения к DNS-серверу, на что может уйти некоторое время;
• в ряде случаев в DNS-сервере может отсутствовать PTR-запись, связывающая IP-адрес с соответствующим именем узла.
Данные функции обладают куда более простым программным интерфейсом по сравнению с getaddrinfo() и getnameinfo() (выполняющими преобразование между двоичным представлением и соответствующими символьными именами), поэтому мы опишем их в первую очередь (в разделе 55.6). Это позволит сразу же продемонстрировать некоторые рабочие примеры использования сокетов в интернет-домене.