Литмир - Электронная Библиотека
Содержание  
A
A

Таблица 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, чего не может сделать функция
gethostby<i>XXX</i>
. У функций распознавателя имена начинаются с
res_
. Примером такой функции является функция
res_init
, которую мы описали в разделе 11.4. Описание этих функций и пример вызывающей их программы находятся в главе 15 книги [1]. При вводе в командной строке man
resolver
должны отобразиться страницы руководства для этих функций.

Упражнения

1. Измените программу, представленную в листинге 11.1, так, чтобы для каждого возвращаемого адреса вызывалась функция

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

2. Устраните проблему, показанную в предыдущем упражнении.

3. Запустите программу, показанную в листинге 11.4, задав имя службы

chargen
.

4. Запустите программу, показанную в листинге 11.4, задав IP-адрес в точечно- десятичной записи в качестве имени узла. Допускает ли это ваш распознаватель? Измените листинг 11.4, чтобы разрешить IP-адрес в виде строки десятичных чисел с точками в качестве имени узла и строку с десятичным номером порта в качестве имени службы. В каком порядке должно выполняться тестирование IP-адреса для строки в точечно-десятичной записи и для имени?

5. Измените программу в листинге 11.4 так, чтобы можно было работать либо с IPv4, либо с IPv6.

6. Измените программу в листинге 8.5 так, чтобы сделать запрос DNS, и сравните возвращаемый IP-адрес со всеми IP-адресами узла получателя, то есть вызовите функцию

gethostbyaddr
, используя IP-адрес, возвращаемый функцией
recvfrom
, а затем вызовите
gethostbyname
для поиска всех IP-адресов для узла.

7. Измените листинг 11.6, чтобы вызвать функцию

getnameinfo
вместо функции
sock_ntop
. Какие флаги вы должны передать функции
getnameinfo
?

8. В разделе 7.5 мы обсуждали завладение портом с помощью параметра сокета

SO_REUSEADDR
. Чтобы увидеть, как это происходит, создайте не зависящий от протокола сервер времени и даты UDP, показанный в листинге 11.13. Запустите один экземпляр сервера в одном окне, свяжите его с универсальным адресом и некоторым портом, который вы выберете. Запустите в другом окне клиент и убедитесь, что этот сервер выполняет обработку клиента (отметьте вызов функции
printf
на узле сервера). Затем запустите другой экземпляр сервера в другом окне, и на этот раз свяжите его с одним из адресов направленной передачи узла и тем же портом, что и первый сервер. С какой проблемой вы сразу же столкнетесь? Устраните эту проблему и перезапустите второй сервер. Запустите клиент, отправьте дейтаграмму и проверьте, что второй сервер захватил порт первого сервера. Если возможно, запустите второй сервер снова с учетной записью, отличной от учетной записи первого сервера, чтобы проверить, происходит ли по-прежнему захват порта, поскольку некоторые производители не допускают второго связывания, если идентификатор пользователя отличен от идентификатора процесса, уже связанного с портом.

9. В конце раздела 2.12 мы показали два примера Telnet: сервер времени и даты и эхо-сервер. Зная, что клиент проходит через два этапа — функцию

gethostbyname
и функцию connect, определите, к каким этапам относятся строки вывода клиента.

142
{"b":"225366","o":1}