17.8.2. Преобразование имен хостов

17.8.2. Преобразование имен хостов

Функции getaddrinfo(), getnameinfo(), позволяющие легко создавать программы, которые поддерживают и IPv4, и IPv6, были введены именно с этой целью. Исходные функции имен хостов было сложно расширить на IPv6, их интерфейсы требовали, чтобы приложения учитывали множество особенностей версии в структурах, сохраняющих IP-адрес. Новые интерфейсы абстрактны, поэтому поддерживают IPv4 и IPv6 одинаково.

Вместо того чтобы возвращать связный список, как это делает getaddrinfo(), старые функции имен хостов используют struct hostent, которая может содержать все имена хостов и адреса для одного хоста.

#include <netdb.h>

struct hostent {

 char* h_name;       /* каноническое имя хоста */

 char** h_aliases;   /* псевдонимы (завершающиеся NULL) */

 int h_addrtype;     /* тип адреса хоста */

 int h_length;       /* длина адреса */

 char** h_addr_list; /* список адресов (завершающийся NULL) */

};

Здесь h_name — каноническое имя хоста. Массив h_aliases содержит все псевдонимы данного хоста. Последняя запись в h_aliases — это указатель NULL, сигнализирующий о конце массива.

Параметр h_addrtype сообщает тип адреса хоста. В данной главе будет применяться только AF_INET. Приложения, которые создавались для поддержки IPv6, получат и другие типы адресов[147]. Следующий член h_length указывает длину двоичных адресов для данного хоста. Для адресов AF_INET эта длина равна sizeof(struct in_addr). Последний элемент h_addr_list представляет собой массив указателей на адреса данного хоста, последний из которых равен NULL для обозначения конца списка. Если h_addrtype равен AF_INET, то каждый указатель в этом списке указывает на структуру struct in_addr.

Две библиотечные функции выполняют преобразования между IP-номерами и именами хостов. Первая из них gethostbyname() возвращает struct hostent для имени хоста. Вторая — gethostbyaddr() — возвращает информацию о машине с данным IP-адресом.

#include <netdb.h>

struct hostent * gethostbyname(const char * name);

struct hostent * gethostbyaddr(const char * addr, int len, int type);

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

Функция gethostbyname() принимает один параметр — строку, содержащую имя хоста. Функция gethostbyaddr() принимает три параметра, которые вместе определяют адрес. Первый из них addr указывает на struct in_addr. Следующий len устанавливает длину информации, на которую указывает параметр addr. Последний type излагает тип адреса, который нужно преобразовать в имя хоста (AF_INET для IPv4-адресов).

Если во время поиска имени хоста происходят ошибки, то код ошибки передается в h_errno. Вызов функции herror() распечатывает описание ошибки (данная функция почти идентична стандартной функции perror()).

Единственный код ошибки, на котором тестируется большинство программ, это NETDB_INTERNAL, который указывает на неудачный системный вызов. При возвращении этой ошибки параметр errno содержит описание той проблемы, которая привела к отказу.