UNIX: разработка сетевых приложений
#include <sys/socket.h>ssize_t recvmsg(int <i>sockfd</i>, struct msghdr *<i>msg</i>, int <i>flags</i>);ssize_t sendmsg(int <i>sockfd</i>, struct msghdr *<i>msg</i>, int <i>flags</i>);<i>Обе функции возвращают: количество прочитанных или записанных байтов в случае успешного выполнения, -1 в случае ошибки</i>Большинство аргументов обеих функций скрыто в структуре
:msghdrstruct 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используются, когда сокет не является присоединенным (например, неприсоединенный сокет UDP). Они аналогичны пятому и шестому аргументам функцийmsg_namelenиrecvfrom:sendtoуказывает на структуру адреса сокета, в которой вызывающий процесс хранит адрес протокола получателя для функцииmsg_nameили функцияsendmsgхранит адрес протокола отправителя. Если нет необходимости задавать адрес протокола (например, сокет TCP или присоединенный сокет UDP), элементrecvmsg_name должен быть пустым указателем. Элементmsgявляется аргументом типа «значение» для функцииmsg_namelen, но для функцииsendmsgэто аргумент типа «значение-результат».recvmsgЭлементы
иmsg_iovзадают массив буферов ввода и вывода (массив структурmsg_iovlen), аналогичный второму и третьему аргументам функцийiovecиreadv.writevЭлементы
иmsg_controlзадают расположение и размер необязательных вспомогательных данных. Элементmsg_controllen— это аргумент типа «значение-результат» функцииmsg_controllen. Вспомогательные данные мы рассматриваем в разделе 14.6.recvmsgРаботая с функциями
иrecvmsg, следует учитывать различие между двумя флаговыми переменными: это аргументsendmsg, который передается по значению, и элементflagsструктурыmsg_flags, который передается по ссылке (поскольку функции передается адрес этой структуры).msghdr■ Элемент
используется только функциейmsg_flags. Когда вызывается функцияrecvmsg, аргументrecvmsgкопируется в элементflags[128, с. 502], и это значение используется ядром для управления приемом данных. Затем это значение обновляется в зависимости от результата функцииmsg_flags.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 •