Функция gethostbyname() (предшественница getaddrinfo()) получала IP-адрес на основе этого файла, находя совпадение для либо канонического имени узла (то есть официального и первичного имени компьютера), либо одного из псевдонимов (которые опционально могут быть перечислены через пробел).
Однако такой подход плохо масштабируется и является непригодным, если в сети большое количество узлов (как в Интернете с его миллиардами компьютеров).
Для решения данной проблемы была разработана служба DNS. Ее ключевые идеи заключаются в следующем.
• Имена сетевых узлов организованы иерархически (рис. 55.2). Каждый
• Ни одна организация или система не управляет всей иерархией целиком. Вместо этого существует иерархия DNS-серверов, каждый из которых отвечает за какую-то ее часть (
Рис. 55.2.
Реализация DNS-сервера named(8), которая используется в Linux, основана на проекте BIND (Berkeley Internet Name Domain) и поддерживается организацией Internet Systems Consortium (http://www.isc.org/). Управление этим демоном осуществляется из файла /etc/named.conf (см. страницу named.conf(5) руководства). Основным источником информации о DNS и BIND можно считать книгу [Albitz & Liu, 2006]. Сведения о DNS также можно найти в главе 14 [Stevens, 1994], главе 11 [Stevens et al., 2004] и главе 24 [Comer, 2000].
• Функция getaddrinfo(), которую вызывают для получения IP-адреса для доменного имени, использует набор библиотечных функций, взаимодействующих с локальным DNS-сервером. Если этот сервер не может предоставить необходимую информацию, то getaddrinfo() обращается к другим DNS-серверам в рамках той же иерархии. Иногда данный процесс может длиться довольного долго, поэтому DNS-серверы применяют кэширование, чтобы избежать лишнего сетевого взаимодействия в случае с часто запрашиваемыми доменными именами.
Применение подхода, описанного выше, позволяет службе DNS оперировать огромными пространствами имен, для управления которыми не требуется централизованный механизм.
DNS-запросы делятся на две категории:
Для того чтобы объяснить принцип работы итеративного запроса, рассмотрим пример. Допустим, локальному DNS-серверу поступил запрос на разрешение имени www.otago.ac.nz. Тот первым делом свяжется с одним из немногочисленных корневых серверов, о которых (как и любой другой DNS-сервер) обязан знать. (Список этих серверов можно получить с помощью команды dig. NS или на веб-странице www.root-servers.org.) В случае с именем www.otago.ac.nz корневой сервер обратится к одному из локальных DNS-серверов в зоне nz, а тот уже попытается найти сервер с именем www.otago.ac.nz. Он будет направлен к серверу ac.nz. Затем локальный сервер выполнит запрос к ac.nz и будет направлен к серверу otago.ac.nz, который, наконец, вернет IP-адрес, связанный с именем www.otago.ac.nz.
При передаче функции gethostbyname() неполного доменного имени она сначала попытается его дополнить. Правила дополнения определяются в файле /etc/resolv.conf (см. страницу resolv.conf(5) руководства). По умолчанию gethostbyname() попытается как минимум использовать доменное имя локальной системы. Например, если ввести команду ssh octavo в системе с именем oghma.otago.ac.nz, итоговый DNS-запрос будет выполнен для имени octavo.otago.ac.nz.