UNIX: разработка сетевых приложений
На сегодняшний день функция
является нерекомендуемой, или устаревшей, и в создаваемом коде вместо нее должна использоваться функцияinet_addr. Еще лучше использовать более новые функции, описанные в следующем разделе, работающие и с IPv4, и с IPv6.inet_atonФункция
преобразует 32-разрядный двоичный адрес IPv4, хранящийся в сетевом порядке байтов, в точечно-десятичную строку. Строка, на которую указывает возвращаемый функцией указатель, находится в статической памяти. Это означает, что функция не допускает повторного вхождения, то есть не является повторно входимой (reentrant), что мы обсудим в разделе 11.14. Наконец, отметим, что эта функция принимает в качестве аргумента структуру, а не указатель на структуру.inet_ntoaПРИМЕЧАНИЕФункции, принимающие структуры в качестве аргументов, встречаются редко. Более общим способом является передача указателя на структуру.
3.7. Функции inet_pton и inet_ntop
Эти функции появились с IPv6 и работают как с адресами IPv4, так и с адресами IPv6. Их мы и будем использовать в книге. Символы
иpобозначают соответственно формат представления и численный формат. Формат представления адреса часто является строкой ASCII, а численный формат — это двоичное значение, входящее в структуру адреса сокета. #include <arpa/inet.h>nint inet_pton(int <i>family</i>, const char *<i>strptr</i>, void *<i>addrptr</i>);<i>Возвращает: 1 в случае успешного выполнения функции: 0, если входная строка имела неверный формат представления; -1 в случае ошибки</i>const char *inet_ntop(int <i>family</i>, const void *<i>addrptr</i>,char *<i>strptr</i>, size_t <i>len</i>);<i>Возвращает: указатель на результат, если выполнение функции прошло успешно. NULL в случае ошибки</i>Значением аргумента
для обеих функций может быть либоfamily, либоAF_INET. ЕслиAF_INET6не поддерживается, обе функции возвращают ошибку со значением переменнойfamily, равнымerrno.EAFNOSUPPORTПервая функция пытается преобразовать строку, на которую указывает
, сохраняя двоичный результат с помощью указателяstrptr. При успешном выполнении ее возвращаемое значение равно 1. Если входная строка находится в неверном формате представления для заданного семейства (addrptr), возвращается нуль.familyФункция
выполняет обратное преобразование: из численного формата (inet_ntop) в формат представления (addrptr). Аргументstrptr— это размер принимающей строки, который передается, чтобы функция не переполнила буфер вызывающего процесса. Чтобы облегчить задание этого размера, в заголовочный файлlenвключаются следующие определения:<netinet/in.h>#define INET_ADDRSTRLEN 16 /* для точечно-десятичной записи IPv4-адреса */#define INET6_ADDRSTRLEN 46 /* для шестнадцатеричной записи IPv6-адреса */Если аргумент
слишком мал для хранения результирующего формата представления вместе с символом конца строки (terminating null), возвращается пустой указатель и переменнойlenприсваивается значениеerrno.ENOSPCАргумент
функцииstrptrне может быть пустым указателем. Вызывающий процесс должен выделить память для хранения преобразованного значения и задать ее размер. При успешном выполнении функции возвращаемым значением является этот указатель.inet_ntopНа рис. 3.5 приведена схема действия пяти функций, описанных в этом и предыдущем разделах.
Рис. 3.5. Функции преобразования адресов
Пример
Даже если ваша система еще не поддерживает IPv6, вы можете использовать новые функции, заменив вызовы вида
foo.sin_addr.s_addr = inet_addr(cp);на
inet_pton(AF_INET, cp, &foo.sin_addr);а также заменив вызовы вида
ptr = inet_ntoa(foo.sin_addr);на
char str[INET_ADDRSTRLEN];ptr = inet_ntop(AF_INET, &foo.sin_addr, str, sizeof(str));В листинге 3.6 представлено простое определение функции
, поддерживающее только IPv4, а в листинге 3.7 — версияinet_pton, поддерживающая только IPv4.inet_ntopЛистинг 3.6. Простая версия функции inet_pton, поддерживающая только IPv4
//libfree/inet_pton_ipv4.c10 int11 inet_pton(int family, const char *strptr, void *addrptr)12 {13 if (family == AF_INET) {14 struct in_addr in_val;15 if (inet_aton(strptr, &in_val)) {16 memcpy(addrptr, &in_val, sizeof(struct in_addr));17 return (1);18 }19 return (0);20 }21 errno = EAFNOSUPPORT;22 return (-1);23 }Листинг 3.7. Простая версия функции inet_ntop, поддерживающая только IPv4
//libfree/inet_ntop_ipv4.c8 const char *9 inet_ntop(int family, const void *addrptr, char *strptr, size_t len)10 {11 const u_char *p = (const u_char*)addrptr;12 if (family == AF_INET) {13 char temp[INET_ADDRSTRLEN];14 snprintf(temp, sizeof(temp), "%d.%d.%d.%d",15 p[0], p[1], p[2], p[3]);
