Читать «UNIX: разработка сетевых приложений» онлайн - страница 56

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

■ Даже если поле длины присутствует, нам не придется устанавливать и проверять его значение, пока мы не имеем дела с маршрутизирующими сокетами (см. главу 18). Оно используется внутри ядра процедурами, работающими со структурами адресов сокетов из различных семейств протоколов (например, код таблицы маршрутизации).

ПРИМЕЧАНИЕ

Четыре функции, передающие структуру адреса сокета от процесса к ядру, — bind, connect, sendto и sendmsg — используют функцию sockargs в реализациях, ведущих происхождение от Беркли [128, с. 452]. Эта функция копирует структуру адреса сокета из процесса и затем явно присваивает элементу sin_len значение размера структуры, переданной в качестве аргумента этим четырем функциям. Пять функций, передающих структуру адреса сокета от ядра к процессу, — accept, recvfrom, recvmsg, getpeername и getsockname — устанавливают элемент sin_len перед возвращением управления процессу.

К сожалению, обычно не существует простого теста, выполняемого в процессе компиляции и определяющего, задает ли реализация поле длины для своих структур адреса сокета. В нашем коде мы тестируем собственную константу HAVE_SOCKADDR_SA_LEN (см. листинг Г.2), но для того чтобы определить, задавать эту константу или нет, требуется откомпилировать простую тестовую программу, использующую необязательный элемент структуры, и проверить, успешно ли выполнена компиляция. В листинге 3.3 мы увидим, что от реализаций IPv6 требуется задавать SIN6_LEN, если структура адреса сокета имеет поле длины. В некоторых реализациях IPv4 (например, Digital Unix) поле длины предоставляется для приложений, основанных на параметре времени компиляции (например, _SOCKADDR_LEN). Это свойство обеспечивает совместимость с другими, более ранними программами.

■ POSIX требует наличия только трех элементов структуры: sin_family, sin_addr и sin_port. POSIX-совместимая реализация может определять дополнительные элементы структуры, и это норма для структуры адреса сокета Интернета. Почти все реализации добавляют элемент sin_zero, так что все структуры адреса сокета имеют размер как минимум 16 байт.

■ Типы элементов s_addr, sin_family и sin_port мы указываем согласно POSIX. Тип данных in_addr_t соответствует целому числу без знака длиной как минимум 32 бита, in_port_t — целому числу без знака длиной как минимум 16 бит, a sa_family_t — это произвольное целое число без знака. Последнее обычно представляет собой 8-разрядное целое без знака, если реализация поддерживает поле длины, либо 16-разрядное целое без знака, если поле длины не поддерживается. В табл. 3.1 перечислены эти три типа данных POSIX вместе с некоторыми другими типами данных POSIX, с которыми мы встретимся.

Таблица 3.1. Типы данных, требуемые POSIX

Тип данных Описание Заголовочный файл
int8_t 8-разрядное целое со знаком <sys/types.h>
uint8_t 8-разрядное целое без знака <sys/types.h>
int16_t 16-разрядное целое со знаком <sys/types.h>
uint16_t 16-разрядное целое без знака <sys/types.h>
int32_t 32-разрядное целое со знаком <sys/types.h>
uint32_t 32-разрядное целое без знака <sys/types.h>
sa_family_t семейство адресов структуры адреса сокета <sys/socket.h>
socklen_t длина структуры адреса сокета, обычно типа uint32_t <sys/socket.h>
in_addr_t IPv4-адрес, обычно типа uint32_t <netinet/in.h>
in_port_t порт TCP или UDP, обычно типа uint16_t <netinet/in.h>