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

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 */

10  switch (sa->sa_family) {

11  case AF_INET: {

12    struct sockaddr_in *sin = (struct sockaddr_in*)sa;

13    if (inet_ntop(AF_INET, &sin->sin_addr. str, sizeof(str)) == NULL)

14     return (NULL);

15    if (ntohs(sin->sin_port) != 0) {

16     snprintf(portstr, sizeof(portstr), ntohs(sin->sin_port));

17     strcat(str, portstr);

18    }

19    return (str);

20   }

Для работы со структурами адресов сокетов мы определяем еще несколько функций, которые упростят переносимость нашего кода между IPv4 и IPv6.

#include "unp.h"

int sock_bind_wild(int sockfd, int family);

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

int sock_cmp_addr(const struct sockaddr *sockaddr1,

 const struct sockaddr *sockaddr2, socklen_t addrlen);

Возвращает: 0, если адреса относятся к одному семейству и совпадают, ненулевое значение в противном случае

int sock_cmp_port(const struct sockaddr *sockaddr1,

 const struct sockaddr *sockaddr2, socklen_t addrlen);

Возвращает: 0, если адреса относятся к одному семейству и порты совпадают, ненулевое значение в противном случае

int sock_get_port(const struct sockaddr *sockaddr, socklen_t addrlen);

Возвращает: неотрицательный номер порта для адресов IPv4 или IPv6, иначе -1

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

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

void sock_set_addr(const struct sockaddr *sockaddr,

 socklen_t addrlen, void *ptr);

void sock_set_port(const struct sockaddr *sockaddr,

 socklen_t addrlen, int port);

void sock_set_wild(struct sockaddr *sockaddr, socklen_t addrlen);

Функция sock_bind_wild связывает универсальный адрес и динамически назначаемый порт с сокетом. Функция sock_cmp_addr сравнивает адресные части двух структур адреса сокета, а функция sock_cmp_port сравнивает номера их портов. Функция sock_get_port возвращает только номер порта, а функция sock_ntop_host преобразует к формату представления только ту часть структуры адреса сокета, которая относится к узлу (все, кроме порта, то есть IP-адрес узла). Функция sock_set_addr присваивает адресной части структуры значение, указанное аргументом ptr, а функция sock_set_port задает в структуре адреса сокета только номер порта. Функция sock_set_wild задает адресную часть структуры через символы подстановки. Как обычно, мы предоставляем для всех этих функций функции- обертки, которые возвращают значение, отличное от типа void, и в наших программах обычно вызываем именно обертки. Мы не приводим в данной книге исходный код для этих функций, так как он свободно доступен (см. предисловие).

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

Связанные документы

Из книги Реестр Windows автора Климов Александр

Связанные документы В последних версиях Windows появилось понятие сопоставленных файлов. Например, если вы собираетесь переместить или удалить html-документ, то будут также перемещены или удалены и сопоставленные с этим документом файлы, которые содержаться в папке


Связанные текстовые фреймы

Из книги Adobe InDesign CS3 автора Завгородний Владимир

Связанные текстовые фреймы При работе с большими фрагментами текста одного фрейма будет недостаточно. Во-первых, мы можем захотеть сверстать текст в несколько колонок. Это можно решить с помощью настроек собственно фрейма (об этом будет сказано в главе 13) или же создать


Связанные файлы

Из книги Человеческий фактор в программировании автора Константин Ларри Л

Связанные файлы В связи с тем что в профессиональной графике файлы изображений могут достигать большого размера – действительно большого, десятки и сотни мегабайт, – многие программы макетирования и верстки не включают файлы изображений в документ. Так поступает и


48 Связанные объекты

Из книги Основы объектно-ориентированного программирования автора Мейер Бертран

48 Связанные объекты Что делает тот или иной предмет легким для понимания? Что делает тот или иной предмет простым в использовании? Что превращает совокупность объектов — не отдельных, а представленных в определенном контексте — в набор рабочих инструментов? Возьмем


У15.5 Связанные стеки

Из книги TCP/IP Архитектура, протоколы, реализация (включая IP версии 6 и IP Security) автора Фейт Сидни М

У15.5 Связанные стеки Основываясь на классах STACK и LINKED_LIST, постройте класс LINKED_STACK, описывающий реализацию стека как связного


1.7.4 Связанные документы

Из книги Технология XSLT автора Валиков Алексей Николаевич

1.7.4 Связанные документы Серия RFC не содержит спецификаций протоколов и была опубликована как отдельный набор документов For Your Information (FYI — К вашему сведению). Например: RFC 1325 Answers to commonly asked "new Internet user" questions (Ответы на наиболее распространенные вопросы новых пользователей


6.4. Проблемы, связанные с блокировками

Из книги Справочник по параметрам BIOS автора Вонг Адриан

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


Неполадки, связанные с BIOS

Из книги Linux программирование в примерах автора Роббинс Арнольд

Неполадки, связанные с BIOS В этой книге мы расскажем, как оптимизировать BIOS, а не о том, насколько сильно вы можете «разгонять» систему. Существует огромное число различных конфигураций, и о них невозможно рассказать ни в этой книге, ни в любой другой.Если вы любите


10.6.2. Наборы сигналов: sigset_t и связанные функции

Из книги Linux и UNIX: программирование в shell. Руководство разработчика. автора Тейнсли Дэвид

10.6.2. Наборы сигналов: sigset_t и связанные функции Маска сигналов процесса является списком сигналов, которые процесс в настоящее время заблокировал. Сила POSIX API в том, что маской сигналов процесса можно манипулировать атомарно, как единым целым.Маска сигналов процесса


Тайм-аут для функции recvfrom (функция select)

Из книги Описание языка PascalABC.NET автора Коллектив РуБоард

Тайм-аут для функции recvfrom (функция select) Мы демонстрируем вторую технологию для установки тайм-аута (использование функции select) в листинге 14.3. Здесь показана наша функция readable_timeo, которая ждет, когда дескриптор станет готов для чтения, но не более заданного числа


21.7. Функция mcast_join и родственные функции

Из книги автора

21.7. Функция mcast_join и родственные функции Несмотря на то что параметры сокетов многоадресной передачи для IPv4 аналогичны параметрам сокетов многоадресной передачи для IPv6, есть достаточно много различий, из-за которых не зависящий от протокола код, использующий


Задания, связанные с ЕГЭ по информатике

Из книги автора

Задания, связанные с ЕГЭ по информатике Начиная с версии 4.10, задачник Programming Taskbook включает набор групп заданий, связанных с ЕГЭ по информатике и ИКТ. Эти группы начинаются с префикса Exam; они доступны для программных сред языков Pascal (в том числе PascalABC.NET) и C++.В базовый набор