14.5. Функции recvmsg и sendmsg

14.5. Функции recvmsg и sendmsg

Эти две функции являются наиболее общими для всех операций ввода-вывода. Действительно, мы можем заменить все вызовы функций ввода read, readv, recv и recvfrom вызовами функции recvmsg. Аналогично, все вызовы различных функций вывода можно заменить вызовами функции sendmsg.

#include <sys/socket.h>

ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

ssize_t sendmsg(int sockfd, struct msghdr *msg, int flags);

Обе функции возвращают: количество прочитанных или записанных байтов в случае успешного выполнения, -1 в случае ошибки

Большинство аргументов обеих функций скрыто в структуре msghdr:

struct msghdr {

 void         *msg_name;     /* адрес протокола */

 socklen_t    msg_namelen;   /* размер адреса протокола */

 struct iovec *msg_iov;      /* массив буферов */

 size_t       msg_iovlen;    /* количество элементов в массиве msg_iov */

 void         *msg_control;  /* вспомогательные данные: должны быть

                                выровнены для структуры cmsghdr */

 socklen_t    msg_controllen; /* размер вспомогательных данных */

 int          msg_flags;      /* флаги, возвращенные функцией recvmsg() */

};

ПРИМЕЧАНИЕ

Показанная нами структура msghdr восходит к 4.3BSD Reno и определяется POSIX. Некоторые системы (например, Solaris 2.5) используют более раннюю структуру msghdr, которая появилась в 4.2BSD. У более ранней структуры нет элемента msg_flags, а элементы msg_control и msg_controllen называются msg_accrights и msg_accrightslen. В этой системе поддерживается только одна форма вспомогательных данных — передача дескрипторов файлов (так называемые права доступа). При появлении протоколов OSI в 4.3BSD Reno были добавлены новые формы вспомогательных данных, вследствие чего были обобщены имена элементов структуры.

Элементы msg_name и msg_namelen используются, когда сокет не является присоединенным (например, неприсоединенный сокет UDP). Они аналогичны пятому и шестому аргументам функций recvfrom и sendto: msg_name указывает на структуру адреса сокета, в которой вызывающий процесс хранит адрес протокола получателя для функции sendmsg или функция recvmsg хранит адрес протокола отправителя. Если нет необходимости задавать адрес протокола (например, сокет TCP или присоединенный сокет UDP), элемент msg_name должен быть пустым указателем. Элемент msg_namelen является аргументом типа «значение» для функции sendmsg, но для функции recvmsg это аргумент типа «значение-результат».

Элементы msg_iov и msg_iovlen задают массив буферов ввода и вывода (массив структур iovec), аналогичный второму и третьему аргументам функций readv и writev.

Элементы msg_control и msg_controllen задают расположение и размер необязательных вспомогательных данных. Элемент msg_controllen — это аргумент типа «значение-результат» функции recvmsg. Вспомогательные данные мы рассматриваем в разделе 14.6.

Работая с функциями recvmsg и sendmsg, следует учитывать различие между двумя флаговыми переменными: это аргумент flags, который передается по значению, и элемент msg_flags структуры msghdr, который передается по ссылке (поскольку функции передается адрес этой структуры).

? Элемент msg_flags используется только функцией recvmsg. Когда вызывается функция recvmsg, аргумент flags копируется в элемент msg_flags [128, с. 502], и это значение используется ядром для управления приемом данных. Затем это значение обновляется в зависимости от результата функции recvmsg.

? Элемент msg_flags игнорируется функцией sendmsg, поскольку эта функция использует аргумент flags для управления выводом данных. Это значит, что если мы хотим установить флаг MSG_DONTWAIT при вызове функции sendmsg, то мы должны присвоить это значение аргументу flags, а присваивание значения MSG_DONTWAIT элементу msg_flags не имеет никакого эффекта.

В табл. 14.2 показано, какие флаги проверяются ядром для функций ввода и вывода и какие элементы msg_flags может возвращать функция recvmsg. Для элемента sendmsg.msg_flags нет колонки, потому что, как мы отмечали, он не используется.

Таблица 14.2. Флаги для различных функций ввода-вывода

Флаг Проверяются функциями send flags sendto flags sendmsg flags Проверяются функциями recv flags recvfrom flags recvmsg flags Возвращаются функцией recvmsg msg_flags
MSG_DONTROUTE
MSG_DONTWAIT
MSG_PEEK
MSG_WAITALL
MSG_EOR
MSG_OOB
MSG_BCAST
MSG_MCAST
MSG_TRUNC
MSG_CTRUNC

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

MSG_BCAST. Этот флаг введен в BSD/OS и возвращается, если дейтаграмма была получена как широковещательная дейтаграмма канального уровня или если ее IP-адрес получателя является широковещательным адресом. Этот флаг предоставляет более удачную возможность определить, что дейтаграмма UDP была отправлена на широковещательный адрес, чем параметр сокета IP_RECVDSTADDR.

MSG_MCAST. Этот флаг введен в BSD_OS и возвращается, если дейтаграмма была получена как дейтаграмма многоадресной передачи канального уровня.

MSG_TRUNC. Этот флаг возвращается, если дейтаграмма была усечена: у ядра имеется больше данных для возвращения, чем позволяет пространство в памяти, выделенное для них процессом (сумма всех элементов iov_len). Более подробно мы рассмотрим это в разделе 22.3.

MSG_CTRUNC. Этот флаг возвращается, если были усечены вспомогательные данные: у ядра имеется больше вспомогательных данных для возвращения, чем позволяет выделенное для них процессом пространство в памяти (msg_controllen).

MSG_EOR. Этот флаг означает конец записи. Он сбрасывается, если возвращаемые данные не заканчивают запись. Если же возвращаемые данные заканчивают логическую запись, этот флаг устанавливается. TCP не использует этот флаг, поскольку это потоковый протокол.

MSG_OOB. Этот флаг никогда не возвращается для внеполосных данных TCP. Он возвращается другими наборами протоколов (например, протоколами OSI).

Реализации могут возвращать некоторые из входных аргументов flags в элементе msg_flags, поэтому мы должны проверять только те значения флагов, которые нас интересуют (например, последние шесть в табл. 14.2).

На рис. 14.1 представлена структура msghdr и информация, на которую она указывает. На этом рисунке отражена ситуация, предшествующая вызову функции recvmsg для сокета UDP.

Рис. 14.1. Структуры данных в тот момент, когда функция recvmsg вызывается для сокета UDP

Для адреса протокола в памяти выделяется 16 байт, а для вспомогательных данных — 20 байт. Инициализируется массив из трех структур iovec: первая задает 100-байтовый буфер, вторая — 60-байтовый буфер, третья — 80-байтовый буфер. Мы также предполагаем, что был установлен параметр сокета IP_RECVDSTADDR для получения IP-адреса получателя из дейтаграммы UDP.

Затем будем считать, что с адреса 198.6.38.100, порт 2000, приходит 170-байтовая дейтаграмма UDP, предназначенная для нашего сокета UDP с IP-адресом получателя 206.168.112.96. На рис. 14.2 показана вся информация, содержащаяся в структуре msghdr в момент завершения функции recvmsg.

Рис. 14.2. Изменение рис. 14.1 при завершении функции

Затемненными показаны поля, изменяемые функцией recvmsg. По сравнению с рис. 14.1 на рис. 14.2 изменяется следующее:

? В буфер, на который указывает элемент msg_name, записывается структура адреса сокета Интернета, содержащая IP-адрес и UDP-порт отправителя, определенные по полученной дейтаграмме.

? Обновляется аргумент msg_namelen, имеющий тип «значение-результат». Его новым значением становится количество данных, хранящихся в msg_name. Но на самом деле его значение как перед вызовом функции recvmsg, так и при ее завершении равно 16.

? Первые 100 байт данных записываются в первый буфер, следующие 60 байт — во второй буфер и последние 10 байт — в третий буфер. Последние 70 байт третьего буфера не изменяются. Возвращаемое значение функции recvmsg — это размер дейтаграммы (170).

? Буфер, на который указывает msg_control, заполняется как структура cmsghdr. (Более подробно о вспомогательных данных мы поговорим в разделе 14.6, а об этом параметре сокета — в разделе 22.2.) Значение cmsg_len равно 16, cmsg_levelIPPROTO_IP, cmsg_typeIP_RECVDSTADDR, а следующие 4 байта 20-байтового буфера содержат IP-адрес получателя из полученной дейтаграммы UDP. Последние 4 байта 20-байтового буфера, которые мы предоставили для хранения вспомогательных данных, не изменяются.

? Обновляется элемент msg_controllen — его новым значением становится фактический размер записанных вспомогательных данных. Этот аргумент также является аргументом типа «значение-результат», и его результат по завершении функции равен 16.

? Элемент msg_flags изменяется функцией recvmsg, но процессу никакие флаги не возвращаются.

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

Таблица 14.3. Сравнение пяти групп функций ввода-вывода

Функция Произвольный дескриптор Только дескриптор сокета Один буфер для чтения и записи Распределяющее чтение, объединяющая запись Наличие флагов Указание адреса собеседника Управляющая информация
read, write
readv, writev
recv, send
recvfrom, sendto
recvmsg, sendsg
Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

5.8.7 Функции

Из книги Linux для пользователя автора Костромин Виктор Алексеевич

5.8.7 Функции СинтаксисОболочка bash позволяет пользователю создавать собственные функции. Функции ведут себя и используются точно так же, как обычные команды оболочки, т. е. мы можем сами создавать новые команды. Функции конструируются следующим образом: function name () {list}Причем


Функции

Из книги Эффективное делопроизводство автора Пташинский Владимир Сергеевич

Функции Excel – серьезная программа для вычислений, одним из главных достоинств которой является множество встроенных функций. Это обширная тема, достойная если не книги, то главы в многотомном руководстве. Рассмотрим ее кратко – ровно настолько, чтобы вы могли далее


19.7.8. Функции

Из книги Linux-сервер своими руками автора Колисниченко Денис Николаевич

19.7.8. Функции Описание функции выглядит так: имя() { список; }Пример:cdir(){ # изменяем каталог cd / }При выполнении функция не создает нового процесса, а выполняется в среде процесса, содержащего эту функцию. Аргументы функции можно передать ей как обыкновенные параметры при


6.12. Функции

Из книги Феномен науки. Кибернетический подход к эволюции автора Турчин Валентин Фёдорович


4.5.3. Функции, которые создают новые конфигурации из существующих 4.5.3.1. Функции геометрии, которые производят новые конфигурации

Из книги MySQL: руководство профессионала автора Паутов Алексей В

4.5.3. Функции, которые создают новые конфигурации из существующих 4.5.3.1. Функции геометрии, которые производят новые конфигурации Раздел "4.5.2. Функции Geometry" обсуждает несколько функций, которые создают новые конфигурации из


10.16 Функции TCP

Из книги TCP/IP Архитектура, протоколы, реализация (включая IP версии 6 и IP Security) автора Фейт Сидни М

10.16 Функции TCP Данная глава посвящена многочисленным функциям TCP. Ниже перечислены основные из них:? Связывание портов с соединениями? Инициализация соединений посредством трехшагового подтверждения? Выполнение медленного старта, исключающего перегрузку


Функции GMP

Из книги Справочник по PHP автора

Функции GMP ПодразделыФункции Введение Функции этого вида позволяют работать с целыми числами повышенной точности определенного формата используя библиотеку GNU MP.Эта библиотека не входит в стандартный пакет PHP. Загрузить коды библиотеки и документацию по ней можно на


Функции URL

Из книги HTML 5, CSS 3 и Web 2.0. Разработка современных Web-сайтов. автора Дронов Владимир


Функции

Из книги Технология XSLT автора Валиков Алексей Николаевич

Функции Функция — это особым образом написанный и оформленный фрагмент кода JavaScript, который можно вызвать из любого Web-сценария на данной Web- странице (повторно используемый код, как его часто называют). Так что, если ка- кой-то фрагмент кода встречается в нескольких местах


Функции

Из книги C++ для начинающих автора Липпман Стенли

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


Функции

Из книги Интернет для ржавых чайников автора Левина Любовь Трофимовна


Функции

Из книги Конец холивара. Pascal vs C автора Кривцов М. А.

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


Функции

Из книги автора

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


3.1. Функции

Из книги автора

3.1. Функции Пример 1.7: Функция вычисляющая факториал.VAR A, Y : INTEGER;FUNCTION FAKTORIAL (N : INTEGER) : INTEGER; VAR F, K : INTEGER; BEGIN F := 1; FOR K := 1 TO N DO F := F * K; FAKTORIAL := F END; BEGINWRITELN (‘ВВЕДИТЕ ЦЕЛОЕ ПОЛОЖИТЕЛЬНОЕ ЧИСЛО’);READLN (A);Y := FAKTORIAL (A);WRITELN (‘N!=’, Y);READLN;READLNEND.Обратите внимание на то, что в описании функции


3. Функции

Из книги автора

3. Функции В C есть только функции, а процедур нет.Тело функции не может содержать в себе определения других функций.Функцию можно вызвать из другой функции.Оператор return возвращает выполнение программы в точку вызова функции.При использовании return; функция