Вход/Регистрация
UNIX: разработка сетевых приложений
вернуться

Стивенс Уильям Ричард

Шрифт:

//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 и связанные с ней функции

Основная проблема, связанная с функцией

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

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. Мы допустили такое решение для этой функции, чтобы ее было легче вызывать из простых программ, приведенных в книге.

В листинге 3.8 представлена часть исходного кода, обрабатывающая семейство

AF_INET
.

Листинг 3.8. Наша функция sock_ntop

//lib/sock_ntop.c

5 char *

6 sock_ntop(const struct sockaddr *sa, socklen_t salen)

7 {

8 char portstr[7];

9 static char str[128]; /* макс. длина для доменного сокета Unix */

  • Читать дальше
  • 1
  • ...
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: