summaryrefslogtreecommitdiffstats
path: root/man2/recvmmsg.2
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--man2/recvmmsg.2276
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)