diff options
Diffstat (limited to '')
-rw-r--r-- | man2/recvmmsg.2 | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/man2/recvmmsg.2 b/man2/recvmmsg.2 new file mode 100644 index 0000000..d5b0f5a --- /dev/null +++ b/man2/recvmmsg.2 @@ -0,0 +1,276 @@ +.\" Copyright (C) 2011 by Andi Kleen <andi@firstfloor.org> +.\" and Copyright (c) 2011 by Michael Kerrisk <mtk.manpages@gmail.com> +.\" +.\" SPDX-License-Identifier: Linux-man-pages-copyleft +.\" +.\" Syscall added in following commit +.\" commit a2e2725541fad72416326798c2d7fa4dafb7d337 +.\" Author: Arnaldo Carvalho de Melo <acme@redhat.com> +.\" Date: Mon Oct 12 23:40:10 2009 -0700 +.\" +.TH recvmmsg 2 2023-05-03 "Linux man-pages 6.05.01" +.SH NAME +recvmmsg \- receive multiple messages on a socket +.SH LIBRARY +Standard C library +.RI ( libc ", " \-lc ) +.SH SYNOPSIS +.nf +.BR "#define _GNU_SOURCE" " /* See feature_test_macros(7) */" +.B #include <sys/socket.h> +.PP +.BI "int recvmmsg(int " sockfd ", struct mmsghdr *" msgvec \ +", unsigned int " vlen "," +.BI " int " flags ", struct timespec *" timeout ");" +.fi +.SH DESCRIPTION +The +.BR recvmmsg () +system call is an extension of +.BR recvmsg (2) +that allows the caller to receive multiple messages from a socket +using a single system call. +(This has performance benefits for some applications.) +A further extension over +.BR recvmsg (2) +is support for a timeout on the receive operation. +.PP +The +.I sockfd +argument is the file descriptor of the socket to receive data from. +.PP +The +.I msgvec +argument is a pointer to an array of +.I mmsghdr +structures. +The size of this array is specified in +.IR vlen . +.PP +The +.I mmsghdr +structure is defined in +.I <sys/socket.h> +as: +.PP +.in +4n +.EX +struct mmsghdr { + struct msghdr msg_hdr; /* Message header */ + unsigned int msg_len; /* Number of received bytes for header */ +}; +.EE +.in +.PP +The +.I msg_hdr +field is a +.I msghdr +structure, as described in +.BR recvmsg (2). +The +.I msg_len +field is the number of bytes returned for the message in the entry. +This field has the same value as the return value of a single +.BR recvmsg (2) +on the header. +.PP +The +.I flags +argument contains flags ORed together. +The flags are the same as documented for +.BR recvmsg (2), +with the following addition: +.TP +.BR MSG_WAITFORONE " (since Linux 2.6.34)" +Turns on +.B MSG_DONTWAIT +after the first message has been received. +.PP +The +.I timeout +argument points to a +.I struct timespec +(see +.BR clock_gettime (2)) +defining a timeout (seconds plus nanoseconds) for the receive operation +.RI ( "but see BUGS!" ). +(This interval will be rounded up to the system clock granularity, +and kernel scheduling delays mean that the blocking interval +may overrun by a small amount.) +If +.I timeout +is NULL, then the operation blocks indefinitely. +.PP +A blocking +.BR recvmmsg () +call blocks until +.I vlen +messages have been received +or until the timeout expires. +A nonblocking call reads as many messages as are available +(up to the limit specified by +.IR vlen ) +and returns immediately. +.PP +On return from +.BR recvmmsg (), +successive elements of +.I msgvec +are updated to contain information about each received message: +.I msg_len +contains the size of the received message; +the subfields of +.I msg_hdr +are updated as described in +.BR recvmsg (2). +The return value of the call indicates the number of elements of +.I msgvec +that have been updated. +.SH RETURN VALUE +On success, +.BR recvmmsg () +returns the number of messages received in +.IR msgvec ; +on error, \-1 is returned, and +.I errno +is set to indicate the error. +.SH ERRORS +Errors are as for +.BR recvmsg (2). +In addition, the following error can occur: +.TP +.B EINVAL +.I timeout +is invalid. +.PP +See also BUGS. +.SH STANDARDS +Linux. +.SH HISTORY +Linux 2.6.33, +glibc 2.12. +.SH BUGS +The +.I timeout +argument does not work as intended. +.\" FIXME . https://bugzilla.kernel.org/show_bug.cgi?id=75371 +.\" http://thread.gmane.org/gmane.linux.man/5677 +The timeout is checked only after the receipt of each datagram, +so that if up to +.I vlen\-1 +datagrams are received before the timeout expires, +but then no further datagrams are received, the call will block forever. +.PP +If an error occurs after at least one message has been received, +the call succeeds, and returns the number of messages received. +The error code is expected to be returned on a subsequent call to +.BR recvmmsg (). +In the current implementation, however, the error code can be overwritten +in the meantime by an unrelated network event on a socket, +for example an incoming ICMP packet. +.SH EXAMPLES +The following program uses +.BR recvmmsg () +to receive multiple messages on a socket and stores +them in multiple buffers. +The call returns if all buffers are filled or if the +timeout specified has expired. +.PP +The following snippet periodically generates UDP datagrams +containing a random number: +.PP +.in +4n +.EX +.RB "$" " while true; do echo $RANDOM > /dev/udp/127.0.0.1/1234;" +.B " sleep 0.25; done" +.EE +.in +.PP +These datagrams are read by the example application, which +can give the following output: +.PP +.in +4n +.EX +.RB "$" " ./a.out" +5 messages received +1 11782 +2 11345 +3 304 +4 13514 +5 28421 +.EE +.in +.SS Program source +\& +.\" SRC BEGIN (recvmmsg.c) +.EX +#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 <time.h> +\& +int +main(void) +{ +#define VLEN 10 +#define BUFSIZE 200 +#define TIMEOUT 1 + int sockfd, retval; + char bufs[VLEN][BUFSIZE+1]; + struct iovec iovecs[VLEN]; + struct mmsghdr msgs[VLEN]; + struct timespec timeout; + 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 (bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)) == \-1) { + perror("bind()"); + exit(EXIT_FAILURE); + } +\& + memset(msgs, 0, sizeof(msgs)); + for (size_t 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\en", retval); + for (size_t i = 0; i < retval; i++) { + bufs[i][msgs[i].msg_len] = 0; + printf("%zu %s", i+1, bufs[i]); + } + exit(EXIT_SUCCESS); +} +.EE +.\" SRC END +.SH SEE ALSO +.BR clock_gettime (2), +.BR recvmsg (2), +.BR sendmmsg (2), +.BR sendmsg (2), +.BR socket (2), +.BR socket (7) |