other versions
| RECVMMSG(2) | Linux Programmer's Manual | RECVMMSG(2) |
名前¶
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 を有効にする。
返り値¶
成功すると、 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/ に書かれている。| 2012-12-24 | Linux |