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

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

Часть 2

Элементарные сокеты

Глава 3

Введение в сокеты

3.1. Введение

Эта глава начинается с описания программного интерфейса приложения (API) сокетов. Мы начнем со структур адресов сокетов, которые будут встречаться почти в каждом примере на протяжении всей книги. Эти структуры можно передавать в двух направлениях: от процесса к ядру и от ядра к процессу. Последний случай — пример аргумента, через который передается возвращаемое значение, и далее в книге мы встретимся с другими примерами таких аргументов.

Перевод текстового представления адреса в двоичное значение, входящее в структуру адреса сокета, осуществляется функциями преобразования адресов. В большей части существующего кода IPv4 используются функции inet_addr и inet_ntoa, но две новых функции inet_pton и inet_ntop работают и с IPv4, и с IPv6.

Одной из проблем этих функций является то, что они зависят от протокола, так как для них имеет значение тип преобразуемого адреса — IPv4 или IPv6. Мы разработали набор функций, названия которых начинаются с sock_, работающих со структурами адресов сокетов независимо от протокола. Эти функции мы и будем использовать, чтобы сделать наш код не зависящим от протокола.

3.2. Структуры адреса сокетов

Большинство функций сокетов используют в качестве аргумента указатель на структуру адреса сокета. Каждый набор протоколов определяет свою собственную структуру адреса сокетов. Имена этих структур начинаются с sockaddr_ и заканчиваются уникальным суффиксом для каждого набора протоколов.

Структура адреса сокета IPv4

Структура адреса сокета IPv4, обычно называемая структурой адреса сокета Интернета, именуется sockaddr_in и определяется в заголовочном файле <netinet/in.h>. В листинге 3.1 представлено определение POSIX.

Листинг 3.1. Структура адреса сокета Интернета (IPv4): sockaddr_in

struct in_addr {

 in_addr_t s_addr; /* 32-разрядный адрес IPv4 */

                   /* сетевой порядок байтов */

};

struct sockaddr_in {

 uint8_t sin_len;         /* длина структуры (16) */

 sa_family_t sin_family;  /* AF_INET */

 in_port_t sin_port;      /* 16-разрядный номер порта TCP или UDP */

                          /* сетевой порядок байтов */

 struct in_addr sin_addr; /* 32-разрядный адрес IPv4 */

                          /* сетевой порядок байтов */

 char sin_zero[8];        /* не используется */

};

Есть несколько моментов, касающихся структур адреса сокета в целом, которые мы покажем на примере.

■ Элемент длины sin_len появился в версии 4.3BSD-Reno, когда была добавлена поддержка протоколов OSI (см. рис. 1.6). До этой реализации первым элементом был sin_family, который исторически имел тип unsigned short (целое без знака). Не все производители поддерживают поле длины для структур адреса сокета, и в POSIX, например, не требуется наличия этого элемента. Типы данных, подобные uint8_t, введены в POSIX (см. табл. 3.1). Наличие поля длины упрощает обработку структур адреса сокета с переменной длиной.