| .\" Copyright (C) 2011 by Andi Kleen <andi@firstfloor.org> |
| .\" and Copyright (c) 2011 by Michael Kerrisk <mtk.manpages@gmail.com> |
| .\" |
| .\" %%%LICENSE_START(VERBATIM) |
| .\" Permission is granted to make and distribute verbatim copies of this |
| .\" manual provided the copyright notice and this permission notice are |
| .\" preserved on all copies. |
| .\" |
| .\" Permission is granted to copy and distribute modified versions of this |
| .\" manual under the conditions for verbatim copying, provided that the |
| .\" entire resulting derived work is distributed under the terms of a |
| .\" permission notice identical to this one. |
| .\" |
| .\" Since the Linux kernel and libraries are constantly changing, this |
| .\" manual page may be incorrect or out-of-date. The author(s) assume no |
| .\" responsibility for errors or omissions, or for damages resulting from |
| .\" the use of the information contained herein. The author(s) may not |
| .\" have taken the same level of care in the production of this manual, |
| .\" which is licensed free of charge, as they might when working |
| .\" professionally. |
| .\" |
| .\" Formatted or processed versions of this manual, if unaccompanied by |
| .\" the source, must acknowledge the copyright and authors of this work. |
| .\" %%%LICENSE_END |
| .\" |
| .\" 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 2019-03-06 "Linux" "Linux Programmer's Manual" |
| .SH NAME |
| recvmmsg \- receive multiple messages on a socket |
| .SH SYNOPSIS |
| .nf |
| .BR "#define _GNU_SOURCE" " /* See feature_test_macros(7) */" |
| .BI "#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 |
| .IR 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 VERSIONS |
| The |
| .BR recvmmsg () |
| system call was added in Linux 2.6.33. |
| Support in glibc was added in version 2.12. |
| .SH CONFORMING TO |
| .BR recvmmsg () |
| is Linux-specific. |
| .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 EXAMPLE |
| .PP |
| 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 |
| \& |
| .EX |
| #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 addr; |
| 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); |
| } |
| |
| 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 (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 (i = 0; i < retval; i++) { |
| bufs[i][msgs[i].msg_len] = 0; |
| printf("%d %s", i+1, bufs[i]); |
| } |
| exit(EXIT_SUCCESS); |
| } |
| .EE |
| .SH SEE ALSO |
| .BR clock_gettime (2), |
| .BR recvmsg (2), |
| .BR sendmmsg (2), |
| .BR sendmsg (2), |
| .BR socket (2), |
| .BR socket (7) |