Чтение онлайн

ЖАНРЫ

Разработка приложений в среде Linux. Второе издание

Троан Эрик В.

Шрифт:

#include <arpa/inet.h>

const char * inet_ntop(int family, const void * address, char * dest,

 int size);

Здесь

family
— это адресное семейство того адреса, который передается во втором параметре; поддерживаются только
AF_INET
и
AF_INET6
. Следующий параметр указывает на
struct in_addr
или
struct in6_addr6
в зависимости от первого параметра. Значение
dest
представляет массив символов, состоящий из
size
элементов, в котором хранится адрес, удобочитаемый для человека. Если форматирование адреса прошло успешно,
то функция
inet_ntop
возвращает
dest
, в противном случае возвращается
NULL
. Существуют только две причины, по которым
inet_ntop
может не выполнить свою работу: если буфер назначения недостаточно велик для хранения форматированного адреса (переменной errno присваивается значение
ENOSPC
) или если параметр
family
задан неверно (errno содержит
EAFNOSUPPORT
).

INET_ADDRSTRLEN
является константой, определяющей наибольший размер
dest
, необходимый для хранения любого IPv4-адреса. Соответственно,
INET6_ADDRSTRLEN
определяет максимальный размер массива для IPv6-адреса.

Программа-пример

netlookup.с
демонстрирует использование
inet_ntop
; полная программа представлена далее в этой главе.

120: if (addr->ai_family == PF_INET) {

121: struct sockaddr_in * inetaddr = (void*)addr->ai_addr;

122: char nameBuf[INET_ADDRSTRLEN];

123:

124: if (serviceName)

125: printf("\tport %d", ntohs(inetaddr->sin_port));

126:

127: if (hostName)

128: printf("\thost %s",

129: inet_ntop(AF_INET, &inetaddr->sin_addr,

130: nameBuf, sizeof(nameBuf)));

131: } else if (addr->ai_family == PF_INET6) {

132: struct sockaddr_in6 *inetaddr =

133: (void *) addr->ai_addr;

134: char nameBuf[INET6_ADDRSTRLEN];

135:

136: if (serviceName)

137: printf("\tport %d", ntohs(inetaddr->sin6_port));

138:

139: if (hostName)

140: printf("\thost %s",

141: inet_ntop(AF_INET6, &inetaddr->sin6_addr,

142: nameBuf, sizeof(nameBuf)));

143: }

Обратное преобразование строки, содержащей адрес с точками или двоеточиями, в двоичный IP-адрес выполняет функция

inet_pton
.

#include <arpa/inet.h>

int inet_pton(int family, const char * address, void * dest);

Параметр

family
определяет тип преобразуемого адреса (либо
AF_INET
, либо
AF_INET6
), a
address
указывает на строку, в которой содержится символьное представление адреса. Если используется
AF_INET
, то десятичная строка с точками преобразуется в двоичный адрес, хранящийся в переменной, на которую указывает параметр
dest
структуры
struct in_addr
. Для
AF_INET6
строка с двоеточиями преобразуется и сохраняется в переменной, на которую указывает
dest
структуры
struct in6_addr
. В отличие от большинства библиотечных функций,
inet_pton
возвращает
1
, если преобразование прошло успешно,
0
, если
dest
не содержит соответствующий адрес, и
– 1
, если параметр
family
не совпадает с
AF_INET
или
AF_INET6
.

Программа-пример

reverselookup
, код которой представлен далее в главе, использует функцию
inet_pton
для преобразования IPv4- и IPv6-адресов, передаваемых пользователем, в структуры
struct sockaddr
. Ниже приводится раздел кода, выполняющий преобразования IP-адреса, на который указывает
hostAddress
. В конце данного кода
struct sockaddr * addr
указывает на структуру, содержащую преобразованный адрес.

 79: if (!hostAddress) {

 80: addr4.sin_family = AF_INET;

 81: addr4.sin_port = portNum;

 82: } else if (! strchr(hostAddress, ':')) {

 83: /* Если в hostAddress появляется двоеточие, то принимаем версию IPv6.

 84: В противном случае это IPv4-адрес */

 85:

 86: if (inet_pton(AF_INET, hostAddress,

 87: &addr4.sin_addr) <= 0) {

 88: fprintf(stderr, "ошибка преобразования IPv4-адреса %s\n",

 89: hostAddress);

 90: return 1;

 91: }

 92:

 93: addr4.sin_family = AF_INET;

 94: addr4.sin_port = portNum;

 95: } else {

 96:

 97: memset(&addr6, 0, sizeof(addr6));

 98:

 99: if (inet_pton(AF_INET6, hostAddress,

100: &addr6.sin6_addr) <= 0) {

101: fprintf(stderr, "ошибка преобразования IPv6-адреса %s\n",

102: hostAddress);

103: return 1;

104: }

105:

106: addr6.sin6_family = AF_INET6;

107: addr6.sin6_port = portNum;

108: addr = (struct sockaddr *) &addr6;

109: addrLen = sizeof(addr6);

110: }

17.5.5. Преобразование имен в адреса

Длинные последовательности чисел являются отлично подходящим методом идентификации для компьютеров, позволяющим им однозначно узнавать друг друга. Однако большинство людей охватывает ужас при мысли о том, что придется иметь дело с большим количеством цифр. Для того чтобы разрешить людям применять текстовые названия для компьютеров вместо числовых, в состав протоколов TCP/IP входит распределенная база данных для взаимных преобразований имен хостов и IP-адресов. Эта база данных называется DNS (Domain Name System — служба имен доменов), она подробно рассматривается в [34] и [1].

Служба DNS предлагает много функций, но сейчас нас интересует одна — возможность преобразования IP-адресов в имена хостов и наоборот. Несмотря на то что это преобразование должно выполняться как однозначное соответствие, на самом деле оно представляет собой отношение типа "многие ко многим". Другими словами, каждый IP-адрес может соответствовать нулю или более именам хостов, а каждое имя хоста соответствует нулю или более IP-адресам.

Использование неоднозначного соответствия между именами хостов и IP-адресами может показаться странным. Однако многие Internet-сайты применяют одну и ту же машину для ftp-сайта и Web-сайта. При этом адреса

www.some.org
и
ftp.some.org
должны ссылаться на одну и ту же машину, а для одной машины не нужны два IP-адреса. Таким образом, два имени хостов сводятся к одному IP-адресу. Каждый IP-адрес имеет одно первичное, или каноническое имя хоста, которое используется, если IP-адрес требуется преобразовать в единственное имя хоста во время обратного поиска имен.

Поделиться с друзьями: