Provided by: manpages-ja-dev_0.5.0.0.20131015+dfsg-2_all
名前
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.54 の一部 である。プロジェクト の説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。