Рудофф Эндрю М. - UNIX: разработка сетевых приложений. 3-е изд. стр 31.

Шрифт
Фон

Возвращает: 1 в случае успешного выполнения функции: 0, если входная строка имела неверный формат представления; -1 в случае ошибки

const char *inet_ntop(int family , const void * addrptr ,

char * strptr , size_t len );

Возвращает: указатель на результат, если выполнение функции прошло успешно. NULL в случае ошибки

Значением аргумента familyдля обеих функций может быть либо AF_INET, либо AF_INET6. Если familyне поддерживается, обе функции возвращают ошибку со значением переменной errno, равным EAFNOSUPPORT.

Первая функция пытается преобразовать строку, на которую указывает strptr, сохраняя двоичный результат с помощью указателя addrptr. При успешном выполнении ее возвращаемое значение равно 1. Если входная строка находится в неверном формате представления для заданного семейства ( family), возвращается нуль.

Функция inet_ntopвыполняет обратное преобразование: из численного формата ( addrptr) в формат представления ( strptr). Аргумент len это размер принимающей строки, который передается, чтобы функция не переполнила буфер вызывающего процесса. Чтобы облегчить задание этого размера, в заголовочный файл <netinet/in.h>включаются следующие определения:

#define INET_ADDRSTRLEN 16 /* для точечно-десятичной записи IPv4-адреса */

#define INET6_ADDRSTRLEN 46 /* для шестнадцатеричной записи IPv6-адреса */

Если аргумент lenслишком мал для хранения результирующего формата представления вместе с символом конца строки (terminating null), возвращается пустой указатель и переменной errnoприсваивается значение ENOSPC.

Аргумент strptrфункции inet_ntopне может быть пустым указателем. Вызывающий процесс должен выделить память для хранения преобразованного значения и задать ее размер. При успешном выполнении функции возвращаемым значением является этот указатель.

На рис. 3.5 приведена схема действия пяти функций, описанных в этом и предыдущем разделах.

Рис. 3.5. Функции преобразования адресов

Пример

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 представлено простое определение функции inet_pton, поддерживающее только IPv4, а в листинге 3.7 версия inet_ntop, поддерживающая только IPv4.

Листинг 3.6. Простая версия функции inet_pton, поддерживающая только IPv4

//libfree/inet_pton_ipv4.c

10 int

11 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.c

8 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]);

16 if (strlen(temp) >= len) {

17 errno = ENOSPC;

18 return (NULL);

19 }

20 strcpy(strptr, temp);

21 return (strptr);

22 }

23 errno = EAFNOSUPPORT;

24 return (NULL);

25 }

3.8. Функция sock_ntop и связанные с ней функции

struct sockaddr_in addr;

inet_ntop(AF_INET, &addr.sin_addr, str, sizeof(str));

или для IPv6 такого вида:

struct sockaddr_in6 addr6:

inet_ntop(AF_INET6, &addr6.sin6_addr, str, sizeof(str));

Как видите, код становится зависящим от протокола.

Чтобы решить эту проблему, напишем собственную функцию и назовем ее sock_ntop. Она получает указатель на структуру адреса сокета, исследует эту структуру и вызывает соответствующую функцию для того, чтобы возвратить формат представления адреса.

#include "unp.h"

char *sock_ntop(const struct sockaddr * sockaddr , socklen_t addrlen );

Возвращает: непустой указатель, если функция выполнена успешно, NULL в случае ошибки

sockaddrуказывает на структуру адреса сокета, длина которой равна значению addrlen. Функция sock_ntopиспользует свой собственный статический буфер для хранения результата и возвращает указатель на этот буфер.

Формат представления либо точечно-десятичная форма записи адреса IPv4, либо шестнадцатеричная форма записи адреса IPv6, за которой следует завершающий символ (мы используем точку, как в программе netstat), затем десятичный номер порта, а затем завершающий нуль. Следовательно, размер буфера должен быть равен как минимум INET_ADDRSTRLENплюс 6 байт для IPv4 (16 + 6 - 22) либо INET6_ADDRSTRLENплюс 6 байт для IPv6 (46 + 6 - 52).

ПРИМЕЧАНИЕ
Обратите внимание, что при статическом хранении результата функция не допускает повторного вхождения (не является повторно входимой) и не может быть использована несколькими программными потоками (не является безопасной в многопоточной среде thread-safe). Более подробно мы поговорим об этом в разделе 11.18. Мы допустили такое решение для этой функции, чтобы ее было легче вызывать из простых программ, приведенных в книге.

Ваша оценка очень важна

0
Шрифт
Фон

Помогите Вашим друзьям узнать о библиотеке