sendmmsg(2)

ИМЯ
sendmmsg - отправляет несколько сообщений в сокет

LIBRARY
Standard C library (libc, -lc)

СИНТАКСИС
#define _GNU_SOURCE         /* Смотрите feature_test_macros(7) */
#include <sys/socket.h>

int sendmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
             int flags);

ОПИСАНИЕ
Системный вызов sendmmsg() является расширенной версией sendmsg(2), позволяя вызывающему передавать несколько сообщений из сокета, используя только один системный вызов (в некоторых приложениях это позволяет получить выигрыш в производительности).

Аргумент sockfd представляет собой файловый дескриптор сокета для отправки данных.

Аргумент msgvec является указателем на массив структур mmsghdr. Размер этого массива указывается в vlen.

Структура mmsghdr определена в <sys/socket.h> следующим образом:

    struct mmsghdr {
        struct msghdr msg_hdr;  /* заголовок сообщения */
        unsigned int  msg_len;  /* кол-во переданных байт */
    };

Поле msg_hdr представляет собой структуру msghdr, которая описана в sendmsg(2). Поле msg_len используется для возврата количества байт, посланных из сообщения в msg_hdr (т. е., такое же значение, что и возвращаемое значение одиночного вызова sendmsg(2)).

Аргумент flags содержит объединённые с помощью OR флаги. Флаги те же, что и у sendmsg(2).

Блокирование вызова sendmmsg() происходит до тех пор, пока не будет отправлено vlen сообщений. Неблокирующий вызов посылает столько сообщений сколько возможно (максимальное количество указано в vlen) и сразу завершает работу.

При возврате из sendmmsg(), поля msg_len последующих элементов msgvec обновляются и содержат количество байт, переданных из соответствующего msg_hdr. Возвращаемое вызовом значение равно количеству элементов msgvec, которые были обновлены.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении sendmmsg() возвращает количество сообщений, посланных из msgvec; если это значение меньше чем vlen, то вызывающий может повторить вызов sendmmsg() для отправки оставшихся сообщений.

В случае ошибки возвращается -1, а errno устанавливается в значение ошибки.

ОШИБКИ
Возникают те же ошибки что и для sendmsg(2). Ошибка возвращается только, если ни одной дейтаграммы не послано. Смотрите также ДЕФЕКТЫ.

ВЕРСИИ
The sendmmsg() system call was added in Linux 3.0. Support in glibc was added in Linux 2.14.

СТАНДАРТЫ
Вызов sendmmsg() есть только в Linux.

ЗАМЕЧАНИЯ
Значение, указанное в vlen, ограничено UIO_MAXIOV (1024).

ДЕФЕКТЫ
Если после отправки хотя бы одного сообщения произошла ошибка, то вызов завершается успешно и возвращается количество отправленных сообщений. Код ошибки теряется. Вызывающий может повторить передачу, начиная с первого ошибочного сообщения, но нет гарантии, что возвращаемый код ошибки будет совпадать с потерянным в предыдущем вызове.

ПРИМЕРЫ
В примере далее sendmmsg() используется для отправки onetwo и three в двух разных дейтаграммах UDP за один системный вызов. Содержимое первой дейтаграммы составляется из пары буферов.

    #define _GNU_SOURCE
    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    int
    main(void)
    {
        int                 retval;
        int                 sockfd;
        struct iovec        msg1[2], msg2;
        struct mmsghdr      msg[2];
        struct sockaddr_in  addr;
        sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (sockfd == -1) {
            perror("socket()");
            exit(EXIT_FAILURE);
        }
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
        addr.sin_port = htons(1234);
        if (connect(sockfd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
            perror("connect()");
            exit(EXIT_FAILURE);
        }
        memset(msg1, 0, sizeof(msg1));
        msg1[0].iov_base = "one";
        msg1[0].iov_len = 3;
        msg1[1].iov_base = "two";
        msg1[1].iov_len = 3;
        memset(&msg2, 0, sizeof(msg2));
        msg2.iov_base = "three";
        msg2.iov_len = 5;
        memset(msg, 0, sizeof(msg));
        msg[0].msg_hdr.msg_iov = msg1;
        msg[0].msg_hdr.msg_iovlen = 2;
        msg[1].msg_hdr.msg_iov = &msg2;
        msg[1].msg_hdr.msg_iovlen = 1;
        retval = sendmmsg(sockfd, msg, 2, 0);
        if (retval == -1)
            perror("sendmmsg()");
        else
            printf("%d сообщений послано\n", retval);
        exit(0);
    }

СМ. ТАКЖЕ
recvmmsg(2), sendmsg(2), socket(2), socket(7)

ПЕРЕВОД
Русский перевод этой страницы руководства был сделан Alexander Golubev <fatzer2@gmail.com>, Azamat Hackimov <azamat.hackimov@gmail.com>, Hotellook, Nikita <zxcvbnm3230@mail.ru>, Spiros Georgaras <sng@hellug.gr>, Vladislav <ivladislavefimov@gmail.com>, Yuri Kozlov <yuray@komyakino.ru> и Иван Павлов <pavia00@gmail.com>

Этот перевод является бесплатной документацией; прочитайте Стандартную общественную лицензию GNU версии 3 (https://www.gnu.org/licenses/gpl-3.0.html) или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.

Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на man-pages-ru-talks@lists.sourceforge.net.