KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программное обеспечение » Уильям Стивенс - UNIX: разработка сетевых приложений

Уильям Стивенс - UNIX: разработка сетевых приложений

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Уильям Стивенс, "UNIX: разработка сетевых приложений" бесплатно, без регистрации.
Перейти на страницу:

■ Это утверждение POSIX также подразумевает, что если флаг AI_PASSIVE задан без имени узла, то должен быть возвращен универсальный адрес IPv6 (IN6ADDR_ANY_INIT или 0::0) в структуре sockaddr_in6 вместе с универсальным адресом IPv4 (INADDR_ANY или 0.0.0.0) в структуре sockaddr_in. Также нет смысла возвращать сначала универсальный адрес IPv4, поскольку мы увидим в разделе 12.2, что на узле с двойным стеком сокет сервера IPv6 может обрабатывать и клиенты IPv4, и клиенты IPv6.

■ Семейство адресов, указанное в поле ai_family структуры hint вместе с флагами AI_V4MAPPED и AI_ALL поля ai_flags, задают тип записей, поиск которых ведется в DNS (тип А или тип AAAA), и тип возвращаемых адресов (IPv4, IPv6 или IPv4, преобразованные к виду IPv6). Мы обобщили это в табл. 11.3.

■ Имя узла может также быть либо шестнадцатеричной строкой IPv6, либо строкой в точечно-десятичной записи IPv4. Допустимость этой строки зависит от семейства адресов, заданного вызывающим процессом. Шестнадцатеричная строка IPv6 неприемлема, если задано семейство AF_INET, а строка в точечно-десятичной записи IPv4 неприемлема, если задано семейство AF_INET6. Но если задано семейство AF_UNSPEC, то допустимы оба варианта, и при этом возвращается соответствующий тип структуры адреса сокета.

ПРИМЕЧАНИЕ

Можно возразить, что если в качестве семейства протоколов задано AF_INET6, строка в точечно-десятичной записи должна возвращаться как адрес IPv4, преобразованный к виду IPv6 в структуре sockaddr_in6. Но другим способом получения этого результата является установка префикса строки с десятичной точкой 0::ffff:.

В табл. 11.3 показано, как будут обрабатываться адреса IPv4 и IPv6 функцией getaddrinfo. Колонка «Результат» отражает то, что мы хотим возвратить вызывающему процессу, если входные переменные таковы, как показано в первых трех колонках. Колонка «Действия» — то, каким образом мы получаем этот результат.


Таблица 11.3. Функция getaddrinfo: ее действия и результаты

Имя узла, указанное вызывающим процессом Семейство адресов, указанное вызывающим процессом Строка с именем узла содержит Результат Действия Ненулевая строка с именем узла; активное или пассивное открытие AF_UNSPEC Имя узла Все записи AAAA возвращаются как структуры sockaddr_in6{} и все записи А возвращаются как структуры sockaddr_in{} Поиск по записям AAAA и поиск по записям A Шестнадцатеричная строка Одна структура sockaddr_in6{} inet_pton(AF_INET6) Строка в точечно- десятичной записи Одна структура sockaddr_in{} inet_pton(AF_INET) AF_INET6 Имя узла Все записи AAAA возвращаются как структуры sockaddr_in6{} либо все записи А возвращаются как структуры sockaddr_in6{} с адресами IPv4, преобразованными к виду IPv6 Поиск по записям AAAA Шестнадцатеричная строка Одна структура sockaddr_in6{} inet_pton(AF_INET6) Строка в точечно-десятичной записи Ищется как имя узла AF_INET Имя узла Все записи А возвращаются как структуры sockaddr_in{} Поиск по записям типа A Шестнадцатеричная строка Ошибка: EAI_ADDRFAMILY Строка в точечно-десятичной записи Одна структура sockaddr_in{} inet_pton(AF_INET) Пустая строка с именем узла; пассивное открытие AF_UNSPEC Неявный адрес 0::0 Неявный адрес 0.0.0.0 Одна структура sockaddr_in6{} и одна структура sockaddr_in{} inet_pton(AF_INET6) inet_pton(AF_INET) AF_INET6 Неявный адрес 0::0 Одна структура sockaddr_in6{} inet_pton(AF_INET6) AF_INET Неявный адрес 0.0.0.0 Одна структура sockaddr_in{} inet_pton(AF_INET) Пустая строка с именем узла; активное открытие AF_UNSPEC Неявный адрес 0::1 Неявный адрес 127.0.0.1 Одна структура sockaddr_in6{} и одна структура sockaddr_in{} inet_pton(AF_INET6) inet_pton(AF_INET) AF_INET6 Неявный адрес 0::1 Одна структура sockaddr_in6{} inet_pton(AF_INET6) AF_INET Неявный адрес 127.0.0.1 Одна структура sockaddr_in{} inet_pton(AF_INET)

Обратите внимание, что табл. 11.3 описывает только обработку адресов IPv4 и IPv6 функцией getaddrinfo, то есть количество и тип адресов, возвращаемых процессу в различных ситуациях. Реальное количество структур addrinfo зависит также от типа сокета и имени службы, о чем уже говорилось в связи с табл. 11.1.

11.10. Функция getaddrinfo: примеры

Теперь мы покажем некоторые примеры работы функции getaddrinfo, используя тестовую программу, которая позволяет нам вводить все параметры: имя узла, имя службы, семейство адресов, тип сокета и флаги AI_CANONNAME и AI_PASSIVE. (Мы не показываем эту тестовую программу, поскольку она содержит около 350 строк малоинтересного кода. Ее можно получить тем же способом, что и прочие исходные коды для этой книги.) Тестовая программа выдает информацию о переменном числе возвращаемых структур addrinfo, показывая аргументы вызова функции socket и адрес в каждой структуре адреса сокета. Сначала показываем тот же пример, что и на рис. 11.3:

freebsd % testga -f inet -c -h freebsd4 -s domain


socket(AF_INET, SOCK_DGRAM, 17) ai_canonname = freebsd4.unpbook.com

      address: 135.197.17.100:53

socket(AF_INET, SOCK_DGRAM, 17)

      address: 172:24.37.94:53

socket(AF_INET, SOCK_STREAM, 6) ai_canonname = freebsd4.unpbook.com

      address: 135.197.17.100:53

socket(AF_INET, SOCK_STREAM, 6)

      address: 172.24.37.94:53

Параметр -f inet задает семейство адресов, -с указывает, что нужно возвратить каноническое имя, -h freebsd4 задает имя узла, -s domain задает имя службы.

Типичный сценарий клиента — задать семейство адресов, тип сокета (параметр -t), имя узла и имя службы. Следующий пример показывает это для узла с несколькими сетевыми интерфейсами с шестью адресами Ipv4:

freebsd % testga -f inet -t stream -h gateway.tuc.noao.edu -s daytime

socket(AF_INET, SOCK_STREAM, 6)

      address: 140.252.108.1:13


socket(AF_INET, SOCK_STREAM, 6)

      address: 140.252.1.4:13


socket(AF_INET, SOCK_STREAM, 6)

      address: 140.252.104.1:13


socket(AF_INET, SOCK_STREAM, 0)

      address: 140.252.3.6.13


socket(AF_INET, SOCK_STREAM, 0)

      address: 140.252.4.100.13


socket(AF_INET, SOCK_STREAM, 0)

      address: 140.252.1.4.13

Затем мы задаем наш узел aix, у которого имеется и запись типа AAAA, и запись типа А, не указывая семейства адресов. Имя службы — ftp, которая предоставляется только TCP.

freebsd % testga -h aix -s ftp -t stream


socket(AF_NET6, SOCK_STREAM, 6)

      address: [3ffe:b80:1f8d:2:204:acff:fe17:bf38]:21


socket(AF_INET, SOCK_STREAM, 6)

      address: 192.168.42.2:21

Поскольку мы не задали семейство адресов и запустили этот пример на узле, который поддерживает и IPv4, и IPv6, возвращаются две структуры: одна для IPv6 и одна для IPv4.

Затем мы задаем флаг AI_PASSIVE (параметр -р), не указываем ни семейства адресов, ни имени узла (подразумевая универсальный адрес), задаем номер порта 8888 и не указываем тип сокета.

freebsd % testga -р -s 8888 -t stream


socket(AF_INET6, SOCK_STREAM, 6)

address: [::]:8888


socket(AF_INET, SOCK_STREAM, 6)

address: 0.0.0.0:8888

Возвращаются две структуры. Поскольку мы запустили эту программу на узле, поддерживающем и IPv4, и IPv6, не задав семейства адресов, функция getaddrinfo возвращает универсальный адрес IPv6 и универсальный адрес IPv4. Структура IPv6 возвращается перед структурой IPv4, поскольку, как мы увидим в главе 12, клиент или сервер IPv6 на узле с двойным стеком может взаимодействовать с собеседниками по IPv6 и по IPv4.

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*