Уильям Стивенс - UNIX: разработка сетевых приложений
- Название:UNIX: разработка сетевых приложений
- Автор:
- Жанр:
- Издательство:Питер
- Год:2007
- Город:Санкт-Петербург
- ISBN:5-94723-991-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Уильям Стивенс - UNIX: разработка сетевых приложений краткое содержание
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
UNIX: разработка сетевых приложений - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
Причина того, что sin_addr является структурой, а не просто целым числом без знака, носит исторический характер. В более ранних реализациях (например, 4.2BSD) структура in_addr определялась как объединение (union) различных структур, чтобы сделать возможным доступ к каждому из четырех байтов 32-разрядного IPv4-адреса, а также к обоим входящим в него 16-разрядным значениям. Эта возможность использовалась в адресах классов А, В и С для выборки соответствующих байтов адреса. Но с появлением подсетей и последующим исчезновением различных классов адресов (см. раздел А.4) и введением бесклассовой адресации (classless addressing) необходимость в объединении структур отпала. В настоящее время большинство систем отказались от использования объединения и просто определяют in_addr как структуру, содержащую один элемент типа in_addr_t.
■ Элемент sin_zero
не используется, но мы всегда устанавливаем его в нуль при заполнении одной из этих структур. Перед заполнением структуры мы всегда обнуляем все ее элементы, а не только sin_zero
.
В большинстве случаев при использовании этой структуры не требуется, чтобы элемент sin_zero был равен нулю, но, например, при привязке конкретного адреса IPv4 (а не произвольного интерфейса) этот элемент обязательно должен быть нулевым [128, с. 731-732].
■ Структуры адреса сокета используются только на данном узле: сама структура не передается между узлами, хотя определенные поля (например, поля IP-адреса и порта) используются для соединения.
Универсальная структура адреса сокета
Структуры адреса сокета всегда передаются по ссылке при передаче в качестве аргумента для любой функции сокета. Но функции сокета, принимающие один из этих указателей в качестве аргумента, должны работать со структурами адреса сокета из любого поддерживаемого семейства протоколов.
Проблема в том, как объявить тип передаваемого указателя. Для ANSI С решение простое: void*
является указателем на неопределенный (универсальный) тип (generic pointer type). Но функции сокетов существовали до появления ANSI С, и в 1982 году было принято решение определить универсальную структуру адреса сокета (generic socket address structure) в заголовочном файле , которая показана в листинге 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*, поскольку это избавило бы его от необходимости выполнять явное преобразование указателя.
Структура адреса сокета IPv6
Структура адреса сокета IPv6 задается при помощи включения заголовочного файла , как показано в листинге 3.3.
Листинг 3.3. Структура адреса сокета IPv6: sockaddr_in6
struct in6_addr {
uint8_t s6_addr[16]; /* 128-разрядный адрес IPv6 */
/* сетевой порядок байтов */
};
#define SIN6_LEN /* требуется для проверки во время компиляции */
struct sockaddr_in6 {
uint8_t sin_len; /* длина этой структуры (24) */
sa_family_t sin6_family; /* AF_INET6 */
in_port_t sin6_port; /* номер порта транспортного уровня */
/* сетевой порядок байтов */
uint32_t sin6_flowinfo; /* приоритет и метка потока */
/* сетевой порядок байтов */
struct in6_addr sin6_addr; /* IPv6-адрес */
/* сетевой порядок байтов */
uint32_t sin6_scope_id; /* набор интерфейсов */
};
Расширения API сокетов для IPv6 описаны в RFC 3493 [36].
Отметим следующие моменты относительно листинга 3.3:
■ Константа SIN6_LEN
должна быть задана, если система поддерживает поле длины для структур адреса сокета.
■ Семейством IPv6 является AF_INET6
, в то время как семейство IPv4 — AF_INET
.
■ Элементы в структуре упорядочены таким образом, что если структура sockaddr_in6
выровнена по 64 битам, то так же выровнен и 128-разрядный элемент sin6_addr
. На некоторых 64-разрядных процессорах доступ к данным с 64-разрядными значениями оптимизирован, если данные выровнены так, что их адрес кратен 64.
■ Элемент sin6_flowinfo
разделен на три поля:
□ 20 бит младшего порядка — это метка потока;
□ следующие 12 бит зарезервированы.
Поле метки потока и поле приоритета рассматриваются в описании рис. А.2. Отметим, что использование поля приоритета еще не определено.
■ Элемент sin6_scope_id
определяет контекст, в котором действует контекстный адрес (scoped address). Чаще всего это бывает индекс интерфейса для локальных адресов (см. раздел А.5).
Новая универсальная структура адреса сокета
Новая универсальная структура адреса сокета была определена как часть API сокетов IPv6 с целью преодолеть некоторые недостатки существующей структуры sockaddr
. В отличие от структуры sockaddr
, новая структура sockaddr_storage
достаточно велика для хранения адреса сокета любого типа, поддерживаемого системой. Новая структура задается подключением заголовочного файла , часть которого показана в листинге 3.4.
Листинг 3.4. Структура хранения адреса сокета sockaddr_storage
Читать дальшеИнтервал:
Закладка: