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

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

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

Константа RES_USE_INET6

Поскольку функция gethostbyname не имеет аргумента для указания нужного семейства адресов (подобного hints.ai_family для getaddrinfo), в первом варианте API использовалась константа RES_USE_INET6, которая должна была добавляться к флагам распознавателя посредством внутреннего интерфейса. Этот API был недостаточно переносимым, поскольку системам, использовавшим альтернативные внутренние интерфейсы распознавателя, приходилось имитировать интерфейс BIND.

Включение RES_USE_INET6 приводило к тому, что функция gethostbyname начинала поиск с записей AAAA, а записи А возвращались только в случае отсутствия первых. Поскольку в структуре hostent есть только одно поле длины адреса, функция gethostbyname могла возвращать адреса только одного типа (либо IPv6, либо IPv4).

Кроме того, включение RES_USE_INET6 приводило к тому, что функция gethostbyname2 начинала возвращать адреса IPv4 в преобразованном к IPv6 виде.

Функция gethostbyname2

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

#include <netdb.h>


struct hostent *gethostbyname2(const char *hostname, int family);

Возвращает: непустой указатель в случае успешного выполнения, в случае ошибки возвращает NULL и задает значение переменной h_errno

Возвращаемое значение то же, что и у функции gethostbyname — указатель на структуру hostent, и сама эта структура устроена так же. Логика функции зависит от аргумента family и параметра распознавателя RES_USE_INET6 (который мы упомянули в конце предыдущего раздела).

Функция getipnodebyname

Документ RFC 2553 [38] запретил использование RES_USE_INET6 и gethostbyname2 из-за глобальности флага RES_USE_INET6 и желания предоставить больше возможностей по управлению возвращаемыми сведениями. Для решения перечисленных проблем была предложена функция getipnodebyname.

#include <sys/socket.h>

#include <netdb.h>


struct hostent *getipnodebyname(const char *name, int af,

 int flags, int *error_num);

Возвращает: ненулевой указатель в случае успешного завершения, нулевой в случае ошибки

Функция возвращает указатель на ту же структуру hostent, которая использовалась gethostbyname. Аргументы af и flags непосредственно соответствуют полям hints.ai_family и hints.ai_flags. Для обеспечения безопасности в многопоточной среде возвращаемое значение выделяется динамически, поэтому его приходится освобождать вызовом freehostent.

#include <netdb.h>


void freehostent(struct hostent *ptr);

Функции getipnodebyname и getipnodebyaddr были отменены в RFC 3493 [36], а вместо них было предложено использовать getaddrinfo и getnameinfo.

11.21. Другая информация о сетях

В этой главе мы сфокусировали внимание на именах узлов, IP-адресах, именах и номерах портов служб. Если же обобщить полученную информацию, мы увидим, что существует четыре типа данных (имеющих отношение к сетям), которые могут понадобиться приложению: узлы, сети, протоколы и службы. В большинстве случаев происходит поиск данных, относящихся к узлам (функции gethostbyname и gethostbyaddr), реже — к службам (функции getservbyname и getservbyaddr) и еще реже — к сетям и протоколам.

Все четыре типа данных могут храниться в файле, и для каждого из четырех типов определены три функции:

1. Функция getXXXent, читающая следующую запись в файле, при необходимости открывающая файл.

2. Функция setXXXent, которая открывает файл (если он еще не открыт) и переходит к началу файла.

3. Функция endXXXent, закрывающая файл.

Для каждого из четырех типов данных определяется его собственная структура (соответственно, структуры hostent, netent, protoent и servent), что требует включения заголовка <netdb.h>.

В дополнение к трем функциям get, set и end, которые допускают последовательную обработку файла, для каждого из четырех типов данных предоставляются функции ключевого поиска, или поиска по ключу (keyed lookup). Эти функции последовательно проходят файл (вызывая функцию getXXXent для чтения каждой строки файла), но вместо того чтобы возвращать каждую строку вызывающему процессу, эти функции ищут элемент, совпадающий с аргументом. Имена функций поиска по ключу имеют вид getXXXbyYYY. Например, две функции ключевого поиска для информации об узле — это функции gethostbyname (ищет элемент, совпадающий с именем узла) и gethostbyaddr (ищет элемент, совпадающий с IP-адресом). Таблица 11.5 обобщает эту информацию.


Таблица 11.5. Четыре типа данных, относящихся к сетям

Тип данных Файл Структура Функции поиска по ключу Узлы /etc/hosts Hostent gethostbyaddr, gethostbyname Сети /etc/networks Netent getnetbyaddr, getnetbyname Протоколы /etc/protocols Protoent getprotobyname, getprotobynumber Службы /etc/services Servent getservbyname, getservbyport

Как это применяется, если используется DNS? Прежде всего, с помощью DNS возможен доступ только к информации об узле и о сети. Информация о протоколе и службах всегда считывается из соответствующего файла. Ранее в этой главе мы отмечали (см. подраздел «Альтернативы DNS»), что в разных реализациях отличаются способы, с помощью которых администратор определяет, что именно использовать для получения информации об узле и сети — DNS или файл.

Далее, если DNS используется для получения информации об узле и о сети, имеют смысл только функции поиска по ключу. Используя, например, функцию gethostent, не стоит надеяться, что она выполнит последовательный перебор всех записей DNS! Если вызывается функция gethostent, она считывает только информацию об узлах и не использует DNS.

ПРИМЕЧАНИЕ

Хотя информацию о сети можно сделать доступной с помощью DNS, очень немногие пользуются этим. На с. 347-348 [1] рассказывается об этой возможности. Однако обычно администраторы создают и обслуживают файл /etc/networks, используемый вместо DNS. Программа netstat с параметром -i использует этот файл, если он есть, и выводит имя каждой сети. Однако бесклассовая адресация (см. раздел А.4) делает эти функции бесполезными, а поскольку они не поддерживают IPv6, новые приложения не должны использовать их.

11.22. Резюме

Набор функций, вызываемых приложением для преобразования имени узла в IP- адрес и обратно, называется распознавателем. Две функции, gethostbyname и gethostbyaddr, являются типичными точками входа. С переходом на IPv6 и многопоточное программирование полезными становятся getaddrinfo и getnameinfo, способные работать с адресами IPv6 и безопасные в многопоточной среде.

Для работы с именами служб и номерами портов широко используется функция getservbyname, принимающая имя службы и возвращающая структуру, содержащую номер порта. Преобразование чаще всего осуществляется на основании данных, содержащихся в некотором текстовом файле. Существует возможность сопоставления имен и номеров протоколов, а также имен и номеров сетей, но используется она реже.

Альтернативой DNS, которую мы не упомянули, является непосредственный вызов функций распознавателя вместо использования функций gethostbyname и gethostbyaddr. Таким способом пользуется, например, программа sendmail, предназначенная для поиска записи типа MX, чего не может сделать функция gethostbyXXX. У функций распознавателя имена начинаются с res_. Примером такой функции является функция res_init, которую мы описали в разделе 11.4. Описание этих функций и пример вызывающей их программы находятся в главе 15 книги [1]. При вводе в командной строке man resolver должны отобразиться страницы руководства для этих функций.

Упражнения

1. Измените программу, представленную в листинге 11.1, так, чтобы для каждого возвращаемого адреса вызывалась функция gethostbyaddr, а затем выведите возвращаемое имя h_name. Сначала запустите программу, задав имя узла только с одним IP-адресом, а затем — с несколькими IP-адресами. Что происходит?

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