sendmmsg(2) 複数のメッセージをソケットへ送信する

書式

#define _GNU_SOURCE
#include <sys/socket.h>
int sendmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
unsigned 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 フィールドは、 sendmsg(2) で説明されている msghdr 構造体である。 msg_len フィールドは msg_hdr から送信されたメッセージのバイト数を返すのに使用される。 この値は sendmsg(2) をこのヘッダに対して呼び出した場合の返り値と同じである。

flags 引き数には複数のフラグを論理和 (OR) で指定できる。フラグは sendmsg(2) と同じである。

停止 (blocking) モードの sendmmsg() の呼び出しは、 vlen 個のメッセージが送信されるまで停止する。 非停止 (nonblocking) モードの呼び出しでは、 送信できるだけのメッセージ (最大で vlen 個) を送信し、 すぐに返る。

sendmmsg() が返った際には、 msgvec の送信が行われた要素の msg_len フィールドは、対応する msg_hdr から送信されたバイト数が入っている。 呼び出しの返り値は、更新された msgvec の要素数である。

返り値

成功すると、 sendmmsg() は msgvec から送信されたメッセージ数を返す。 返り値が vlen よりも小さい場合、 呼び出した側では再度 sendmmsg を呼び出して残りのメッセージを送信することができる。

エラーの場合、 -1 を返し、 errno にエラーを示す値を設定する。

エラー

エラーは sendmsg(2) と同じである。 エラーが返されるのは、 データグラムが全く送信できなかった場合のみである。

バージョン

sendmmsg() システムコールは Linux 3.0 で追加された。 glibc でのサポートはバージョン 2.14 で追加された。

準拠

sendmmsg() は Linux 固有である。

注意

vlen に指定できる値の最大値は UIO_MAXIOV (1024) である。

以下の例では、 sendmmsg() を使って、 一度のシステムコールで、 onetwothree を二つの別々の UDP データグラムで送信する。 一つ目のデータグラムの内容は、二つのバッファから取得される。

#define _GNU_SOURCE
#include <netinet/ip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
int
main(void)
{
    int sockfd;
    struct sockaddr_in sa;
    struct mmsghdr msg[2];
    struct iovec msg1[2], msg2;
    int retval;
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1) {
        perror("socket()");
        exit(EXIT_FAILURE);
    }
    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    sa.sin_port = htons(1234);
    if (connect(sockfd, (struct sockaddr *) &sa, sizeof(sa)) == -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 messages sent\n", retval);
    exit(0);
}

この文書について

この man ページは Linux man-pages プロジェクトのリリース 3.65 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。