Литмир - Электронная Библиотека
Содержание  
A
A

14.6. Вспомогательные данные

Вспомогательные данные (ancillary data) можно отправлять и получать, используя элементы

msg_control
и
msg_controllen
структуры
msghdr
с функциями
sendmsg
и
recvmsg
. Другой термин, используемый для обозначения вспомогательных данных, — управляющая информация (control information). В этом разделе мы рассматриваем данное понятие и показываем структуру и макросы, используемые для создания и обработки вспомогательных данных. Примеры программ мы откладываем до следующих глав, в которых рассказывается о применении вспомогательных данных.

В табл. 14.4 приводится обобщение различных вариантов применения вспомогательных данных, рассматриваемых в этой книге.

Таблица 14.4. Использование вспомогательных данных

Протокол cmsg_level cmsg_type Описание
IPv4 IPPROTO_IP IP_RECVDSTADDR Получает адрес получателя с дейтаграммой UDP
IP_RECVIF Получает индекс интерфейса с дейтаграммой UDP
IPv6 IPPROTO_IPV6 IPV6_DSTOPTS Задает/получает параметры получателя
IPV6_HOPLIMIT Задает/получает предел количества транзитных узлов
IPV6_HOPOPTS Задает/получает параметры для транзитных узлов
IPV6_NEXTHOP Задает следующий транзитный адрес
IPV6_PKTINFO Задает/получает информацию о пакете
IPV6_RTHDR Задает/получает информацию о пакете
Домен Unix SOL_SOCKET SCM_RIGHTS Посылает/получает дескрипторы
SCM_CREDS Посылает/получает данные, идентифицирующие пользователя

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

Вспомогательные данные состоят из одного или более объектов вспомогательных данных (ancillary data objects), каждый из которых начинается со структуры

cmsghdr
, определяемой подключением заголовочного файла
<sys/socket.h>
:

struct cmsghdr {

 socklen_t cmsg_len;   /* длина структуры в байтах */

 int       cmsg_level; /* исходящий протокол */

 int       cmsg_type;  /* тип данных, специфичный для протокола */

 /* далее следует массив символов без знака cmsg_data[] */

};

Мы уже видели эту структуру на рис. 14.2, когда она использовалась с параметром сокета

IP_RECVDSTADDR
для возвращения IP-адреса получателя полученной дейтаграммы UDP. Вспомогательные данные, на которые указывает элемент
msg_control
, должны быть соответствующим образом выровнены для структуры
cmsghdr
. Один из способов выравнивания мы показываем в листинге 15.7.

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

UNIX: разработка сетевых приложений - img_98.png

Рис. 14.3. Два объекта вспомогательных данных

Элемент

msg_control
указывает на первый объект вспомогательных данных, а общая длина вспомогательных данных задается элементом
msg_controllen
. Каждому объекту предшествует структура
cmsghdr
, которая описывает объект. Между элементом
cmsg_type
и фактическими данными может существовать заполнение, а также заполнение может быть в конце данных, перед следующим объектом вспомогательных данных. Пять макросов
CMSG_xxx
, которые мы описываем далее, учитывают это возможное заполнение.

ПРИМЕЧАНИЕ

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

На рис. 14.4 приводится формат структуры

cmsghdr
при ее использовании с доменным сокетом Unix для передачи дескрипторов (см. раздел 15.7) или передачи данных, идентифицирующих пользователя (см. раздел 15.8).

UNIX: разработка сетевых приложений - img_99.png

Рис. 14.4. Структура cmsghdr при использовании с доменными сокетами Unix

Предполагается, что каждый из трех элементов структуры

cmsghdr
занимает 4 байта и между структурой
cmsghdr
и данными нет заполнения. При передаче дескрипторов содержимое массива
cmsg_data
— это фактические значения дескрипторов. На этом рисунке мы показываем только один передаваемый дескриптор, но в общем может передаваться и более одного дескриптора (тогда значение элемента
cmsg_len
будет равно 12 плюс число дескрипторов, умноженное на 4, если считать, что каждый дескриптор занимает 4 байта).

Вспомогательные данные, возвращаемые функцией

recvmsg
, могут содержать любое число объектов вспомогательных данных. Чтобы скрыть возможное заполнение от приложения, для упрощения обработки вспомогательных данных определены следующие пять макросов (что требует включения заголовочного файла
<sys/socket.h>
).

#include <sys/socket.h>

#include <sys/param.h> /* для макроса ALIGN во многих реализациях */

struct cmsghdr *CMSG_FIRSTHDR(struct msghdr *<i>mhdrptr</i>);

<i>Возвращает: указатель на первую структуру cmsghdr или NULL, если нет вспомогательных данных</i>

struct cmsghdr *CMSG_NXTHDR(struct msghdr *<i>mhdrptr</i>, struct cmsghdr *<i>cmsgptr</i>);

<i>Возвращает: указатель на структуру cmsghdr или NULL, если нет больше объектов вспомогательных данных</i>

160
{"b":"225366","o":1}