Книга: UNIX: разработка сетевых приложений

Универсальная структура адреса сокета

Универсальная структура адреса сокета

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

Проблема в том, как объявить тип передаваемого указателя. Для ANSI С решение простое: void* является указателем на неопределенный (универсальный) тип (generic pointer type). Но функции сокетов существовали до появления ANSI С, и в 1982 году было принято решение определить универсальную структуру адреса сокета (generic socket address structure) в заголовочном файле <sys/socket.h>, которая показана в листинге 3.2.

Листинг 3.2. Универсальная структура адреса сокета: sockaddr

struct sockaddr {
 uint8_t sa_len;
 sa_family_t sa_family; /* семейство адресов: константа AF_xxx */
 char sa_data[14];      /* адрес, специфичный для протокола */
};

Функции сокетов определяются таким образом, что их аргументом является указатель на общую структуру адреса сокета, как показано в прототипе функции bind (ANSI С):

int bind(int, struct sockaddr*, socklen_t);

При этом требуется, чтобы для любых вызовов этих функций указатель на структуру адреса сокета, специфичную для протокола, был преобразован в указатель на универсальную структуру адреса сокета. Например:

struct sockaddr_in serv; /* структура адреса сокета IPv4 */
/* заполняем serv{} */
bind(sockfd, (struct sockaddr*)&serv, sizeof(serv));

Если мы не выполним преобразование (struct sockaddr*), компилятор С сгенерирует предупреждение в форме "Warning: passing arg 2 of 'bind' from incompatible pointer type" (Передается указатель несовместимого типа). Здесь мы предполагаем, что в системных заголовочных файлах имеется прототип ANSI С для функции bind.

С точки зрения разработчика приложений, универсальная структура адреса сокета используется только для преобразования указателей на структуры адресов конкретных протоколов.

ПРИМЕЧАНИЕ

Вспомните, что в нашем заголовочном файле unp.h (см. раздел 1.2) мы определили SA как строку "struct sockaddr", чтобы сократить код, который мы написали для преобразования этих указателей.

С точки зрения ядра основанием использовать в качестве аргументов указатели на универсальные структуры адреса сокетов является то, что ядро должно получать указатель вызывающей функции, преобразовывать его в struct sockaddr, а затем по значению элемента sa_family определять тип структуры. Но разработчику приложений было бы проще работать с указателем void*, поскольку это избавило бы его от необходимости выполнять явное преобразование указателя.

Оглавление книги


Генерация: 7.317. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз