Provided by: manpages-ja-dev_0.5.0.0.20140515+dfsg-2_all bug

名前

       recvmmsg - 複数のメッセージをソケットから受信する

書式

       #define _GNU_SOURCE
       #include <sys/socket.h>

       int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
                    unsigned int flags, struct timespec *timeout);

説明

       recvmmsg() システムコールは recvmsg(2) の拡張で、 このシステムコールを使うと一度の呼び出し
       でソケットから複数のメッセージを受信することができる (アプリケーションによっては性能上のメ
       リットがある)。 他に recvmsg(2) から拡張されている点としては、受信操作におけるタイムアウト
       のサポートがある。

       sockfd 引き数は、データを受信するソケットのファイルディスクリプタである。

       msgvec 引き数は mmsghdr 構造体の配列である。 この配列の大きさは vlen で指定する。

       mmsghdr 構造体は <sys/socket.h> で次のように定義されている。

           struct mmsghdr {
               struct msghdr msg_hdr;  /* メッセージヘッダ */
               unsigned int  msg_len;  /* このヘッダで受信されたバイト数 */
           };

       msg_hdr フィールドは、 recvmsg(2) で説明されている msghdr 構造体である。 msg_len  フィール
       ドは、 このエントリで返されるメッセージのバイト数で、 このヘッダに対して recvmsg(2) を呼び
       出した場合の返り値と同じ値が入る。

       flags 引き数には複数のフラグを論理和 (OR) で指定できる。 フラグは、 recvmsg(2)  で説明され
       ているものに加えて、以下が使用できる。

       MSG_WAITFORONE (Linux 2.6.34 以降)
              最初のメッセージを受信後に MSG_DONTWAIT を有効にする。

       timeout 引き数は struct timespec (clock_gettime(2) 参照) へのポインタで、 この構造体で受信
       操作のタイムアウト (秒とナノ秒)  を指定する  (待ち時間はシステムクロックの粒度に切り上げら
       れ、カーネルのスケジューリング遅延により少しだけ長くなる可能性がある)。  timeoutが NULL の
       場合、 受信操作は無期限に停止 (block) する。

       停止 (blocking) モードの recvmmsg() の呼び出しは、 vlen 個のメッセージを受信するか、タイム
       アウトが満了するまで停止する。  非停止 (nonblocking) モードの呼び出しでは、 読み出し可能な
       メッセージ (最大で vlen 個) を読み出し、 すぐに返る。

       recvmmsg()  が返った際には、  msgvec  のうちデータが受信された要素には、受信したそれぞれの
       メッセージの情報が格納されている。  また、  msg_len には受信したメッセージの大きさが入り、
       msg_hdr  の各フィールドは  recvmsg(2)  に書かれている通りに更新される。   呼び出しの返り値
       は、更新された msgvec の要素数である。

返り値

       成功すると、  recvmmsg() は msgvec に受信されたメッセージ数を返す。 エラーの場合、 -1 を返
       し、 errno にエラーを示す値を設定する。

エラー

       エラーは recvmsg(2) と同じである。 これに加えて、以下のエラーが起こる場合がある。

       EINVAL timeout が無効である。

バージョン

       recvmmsg() システムコールは Linux  2.6.33  で追加された。  glibc  でのサポートはバージョン
       2.12 以降で利用可能である。

準拠

       recvmmsg() は Linux 固有である。

       以下のプログラムは、 recvmmsg() を使って複数のメッセージをソケットから受信し、それらを複数
       のバッファに格納する。 呼び出しは、すべてのバッファにメッセージが格納されるか、 指定したタ
       イムアウト時間が経過すると返る。

       以下のコマンドは、 ランダムな数字が入った UDP データグラムを定期的に生成する。

           $ while true; do echo $RANDOM > /dev/udp/127.0.0.1/1234;
           sleep 0.25; done

       生成されたデータグラムをサンプルアプリケーションが読み出し、以下のような出力が得られる。

           $ ./a.out
           5 messages received
           1 11782
           2 11345
           3 304
           4 13514
           5 28421

   プログラムのソース

       #define _GNU_SOURCE
       #include <netinet/ip.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <string.h>
       #include <sys/socket.h>

       int
       main(void)
       {
       #define VLEN 10
       #define BUFSIZE 200
       #define TIMEOUT 1
           int sockfd, retval, i;
           struct sockaddr_in sa;
           struct mmsghdr msgs[VLEN];
           struct iovec iovecs[VLEN];
           char bufs[VLEN][BUFSIZE+1];
           struct timespec timeout;

           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 (bind(sockfd, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
               perror("bind()");
               exit(EXIT_FAILURE);
           }

           memset(msgs, 0, sizeof(msgs));
           for (i = 0; i < VLEN; i++) {
               iovecs[i].iov_base         = bufs[i];
               iovecs[i].iov_len          = BUFSIZE;
               msgs[i].msg_hdr.msg_iov    = &iovecs[i];
               msgs[i].msg_hdr.msg_iovlen = 1;
           }

           timeout.tv_sec = TIMEOUT;
           timeout.tv_nsec = 0;

           retval = recvmmsg(sockfd, msgs, VLEN, 0, &timeout);
           if (retval == -1) {
               perror("recvmmsg()");
               exit(EXIT_FAILURE);
           }

           printf("%d messages received\n", retval);
           for (i = 0; i < retval; i++) {
               bufs[i][msgs[i].msg_len] = 0;
               printf("%d %s", i+1, bufs[i]);
           }
           exit(EXIT_SUCCESS);
       }

関連項目

       clock_gettime(2), recvmsg(2), sendmmsg(2), sendmsg(2), socket(2), socket(7)

この文書について

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