struct hostent {
char *h_name; /* официальное (каноническое) имя узла */
char **h_alihases; /* указатель на массив указателей на псевдонимы */
int h_addrtype; /* тип адреса узла: AF_INET */
int h_length; /* длина адреса: 4 */
char **h_addr_list; /* указатель на массив указателей с адресами IPv4 или IPv6 */
};
В терминах DNS функция gethostbyname
выполняет запрос на запись типа А. Функция возвращает только адреса IPv4.
На рис. 11.2 представлено устройство структуры hostent
и содержащаяся в ней информация, в предположении, что искомое имя узла имеет два альтернативных имени и три адреса IPv4. Все имена узла представляют собой строки языка С.
Рис. 11.2. Структура hostent и ее одержимое
Возвращаемое имя h_name
называется каноническим именем узла. Например, с показанными в предыдущем разделе записями CNAME каноническое имя узла ftp://ftp.unpbook.com
будет иметь вид linux.unpbook.com
. Также если мы вызываем функцию gethostbyname
с узла aix
с неполным именем, например solaris
, то в качестве канонического имени возвращается полное доменное имя (FQDN) solaris.unpbook.com.
.
ПРИМЕЧАНИЕ
Некоторые версии функции gethostbyname допускают, что аргумент hostname может быть записан в виде строки десятичных чисел, разделенных точками. То есть вызов в форме hptr = gethostbyname("206.62.226.33"); будет работать. Этот код был добавлен, поскольку клиент Rlogin принимает только имя узла, вызывая функцию gethostbyname, и не принимает точечно-десятичную запись [127]. Стандарт POSIX допускает это, но не устанавливает такое поведение в качестве обязательного, поэтому переносимое приложение не может использовать указанную особенность.
Функция gethostbyname
отличается от других функций сокетов, описанных нами, тем, что она не задает значение переменной errno
, когда происходит ошибка. Вместо этого она присваивает глобальной целочисленной переменной h_errno
одну из следующих констант, определяемых в заголовке :
■ HOST_NOT_FOUND
;
■ TRY_AGAIN
;
■ NO_RECOVERY
;
■ NO_DATA
(идентично NO_ADDRESS
).
Ошибка NO_DATA
означает, что заданное имя действительно, но у него нет записи типа А. Примером может служить имя узла, имеющего только запись типа MX.
Самые современные распознаватели предоставляют функцию hstrerror
, которая в качестве единственного аргумента получает значение h_errno
и возвращает указатель типа const char*
на описание ошибки. Некоторые примеры строк, возвращаемых этой функцией, мы увидим в следующем примере.
В листинге 11.1 [1] Все исходные коды программ, опубликованные в этой книге, вы можете найти по адресу http://www.piter.com.
показана простая программа, вызывающая функцию gethostbyname
для любого числа аргументов командной строки и выводящая всю возвращаемую информацию.
Листинг 11.1. Вызов функции и вывод возвращаемой информации
//names/hostent.c
1 #include "unp.h"
2 int
3 main(int argc, char **argv)
4 {
5 char *ptr, **pptr;
6 char str[INET_ADDRSTRLEN];
7 struct hostent *hptr;
8 while (--argc > 0) {
9 ptr = *++argv;
10 if ((hptr = gethostbyname(ptr)) == NULL) {
11 err_msg("gethostbyname error for host, %s: %s",
12 ptr, hstrerror(h_errno));
13 continue;
14 }
15 printf("official hostname: %s\n", hptr->h_name);
16 for (pptr = hptr->h_aliases; *pptr != NULL; pptr++)
17 printf("\talias: %s\n", *pptr);
18 switch (hptr->h_addrtype) {
19 case AF_INET:
20 pptr = hptr->h_addr_list;
21 for (; *pptr != NULL; pptr++)
22 printf("\taddress: %s\n",
23 Inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str)));
24 break;
25 default:
26 err_ret("unknown address type");
27 break;
28 }
29 }
30 exit(0);
31 }
8-14
Функция gethostbyname
вызывается для каждого аргумента командной строки.
15-17
Выводится каноническое имя узла, за которым идет список альтернативных имен.
18-24
Переменная pptr
указывает на массив указателей на индивидуальные адреса. Для каждого адреса мы вызываем функцию inet_ntop
и выводим возвращаемую строку.
Сначала мы выполняем программу с именем нашего узла aix
, у которого имеется только один адрес IPv4:
freebsd % hostent aix
official hostname: aix.unpbook.com
address: 192.168 42.2
Обратите внимание, что официальное имя узла — это FQDN. Кроме того, хотя у узла имеется адрес IPv6, возвращается только адрес IPv4. Следующим будет веб-сервер с несколькими адресами IPv4:
Читать дальше
Конец ознакомительного отрывка
Купить книгу