Две библиотечные функции выполняют преобразования между IP-номерами и именами хостов. Первая из них gethostbyname()
возвращает struct hostent
для имени хоста. Вторая — gethostbyaddr()
— возвращает информацию о машине с данным IP-адресом.
#include
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 содержит описание той проблемы, которая привела к отказу.
17.8.3. Пример поиска информации хоста с использованием унаследованных функций
Ниже приводится пример программы, использующей inet_aton()
, inet_ntoa()
, gethostbyname()
, gethostbyaddr()
. Она принимает единственный аргумент, который может быть либо именем хоста, либо IP-адресом в десятичном представлении с точками. Она отыскивает хост и распечатывает все имена хоста и IP-адреса, ассоциированные с ним.
Любой аргумент, который является действительным десятичным адресом, считается IP-номером, а не именем хоста.
1: /* lookup.с */
2:
3: /* Получает либо имя хоста, либо IP-адрес в командной строке, выводит
4: каноническое имя хоста для данного хоста и все IP-номера и имена
5: хостов, ассоциированные с ним. */
6:
7: #include /* для gethostby* */
8: #include
9: #include /* для адресных структур */
10: #include /* для inet_ntoa() */
11: #include
12:
13: int main(int argc, const char ** argv) {
14: struct hostent * answer;
15: struct in_addr address, ** addrptr;
16: char ** next;
17:
18: if (argc != 2) {
19: fprintf(stderr, "поддерживается только одиночный аргумент\n");
20: return 1;
21: }
22:
23: /* Если аргумент выглядит как IP, то принимаем его как таковой
24: и выполняет обратный поиск имени */
25: if (inet_aton(argv[1], &address))
26: answer = gethostbyaddr((char *)&address, sizeof(address),
27: AF_INET);
28: else
29: answer = gethostbyname(argv[1])
30:
31: /* поиск имени хоста не удался */
32: if (!answer) {
33: herror("ошибка поиска хоста");
34: return 1;
35: }
36:
37: printf("Каноническое имя хоста: %s\n", answer->h_name);
38:
39: /* если есть псевдонимы, все они выводятся на печать */
40: if (answer->h_aliases[0]) {
41: printf("Псевдонимы:");
42: for(next = answer->h_aliases; *next; next++)
43: printf(" %s", *next);
44: printf("\n");
45: }
46:
47: /* отобразить все IP-адреса для данной машины */
48: printf("Адреса:");
49: for (addrptr = (structin_addr **) answer->h_addr_list;
50: *addrptr; addrptr++)
51: printf (" %s", inet_ntoa(**addrptr));
52: printf("\n");
53:
54: return 0;
55: }
Ниже показан пример вывода этой программы.
$ ./lookup ftp.netscape.com
Каноническое имя хоста: ftp25.netscape.com
Псевдонимы: ftp.netscape.com anonftp10.netscape.com
Адреса: 207.200.74.21
17.8.4. Поиск номеров портов
Новые функции getaddrinfo()
и getnameinfo()
предлагают простое выполнение преобразований имен служб в номера портов с одновременным определением имени хоста. В старых реализациях поиск имен служб проводился абсолютно независимо от поиска имен хостов. Доступ к именам служб можно получить через функцию getservbyname()
.
#include
struct servent * getservbyname(const char * name,
const char * protocol);
Первый параметр name
представляет собой имя службы, о которой в приложении требуется информация. Параметр protocol
указывает протокол для использования. База данных служб содержит информацию о других протоколах (особенно UDP); конкретное определение протокола позволяет функции игнорировать информацию по другим протоколам. Параметр protocol
обычно является строкой "tcp"
, хотя могут использоваться и другие имена протоколов, например, "udp"
.
Читать дальше