1recvmmsg(2) System Calls Manual recvmmsg(2)
2
3
4
6 recvmmsg - receive multiple messages on a socket
7
9 Standard C library (libc, -lc)
10
12 #define _GNU_SOURCE /* See feature_test_macros(7) */
13 #include <sys/socket.h>
14
15 int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
16 int flags, struct timespec *timeout);
17
19 The recvmmsg() system call is an extension of recvmsg(2) that allows
20 the caller to receive multiple messages from a socket using a single
21 system call. (This has performance benefits for some applications.) A
22 further extension over recvmsg(2) is support for a timeout on the re‐
23 ceive operation.
24
25 The sockfd argument is the file descriptor of the socket to receive
26 data from.
27
28 The msgvec argument is a pointer to an array of mmsghdr structures.
29 The size of this array is specified in vlen.
30
31 The mmsghdr structure is defined in <sys/socket.h> as:
32
33 struct mmsghdr {
34 struct msghdr msg_hdr; /* Message header */
35 unsigned int msg_len; /* Number of received bytes for header */
36 };
37
38 The msg_hdr field is a msghdr structure, as described in recvmsg(2).
39 The msg_len field is the number of bytes returned for the message in
40 the entry. This field has the same value as the return value of a sin‐
41 gle recvmsg(2) on the header.
42
43 The flags argument contains flags ORed together. The flags are the
44 same as documented for recvmsg(2), with the following addition:
45
46 MSG_WAITFORONE (since Linux 2.6.34)
47 Turns on MSG_DONTWAIT after the first message has been received.
48
49 The timeout argument points to a struct timespec (see clock_gettime(2))
50 defining a timeout (seconds plus nanoseconds) for the receive operation
51 (but see BUGS!). (This interval will be rounded up to the system clock
52 granularity, and kernel scheduling delays mean that the blocking inter‐
53 val may overrun by a small amount.) If timeout is NULL, then the oper‐
54 ation blocks indefinitely.
55
56 A blocking recvmmsg() call blocks until vlen messages have been re‐
57 ceived or until the timeout expires. A nonblocking call reads as many
58 messages as are available (up to the limit specified by vlen) and re‐
59 turns immediately.
60
61 On return from recvmmsg(), successive elements of msgvec are updated to
62 contain information about each received message: msg_len contains the
63 size of the received message; the subfields of msg_hdr are updated as
64 described in recvmsg(2). The return value of the call indicates the
65 number of elements of msgvec that have been updated.
66
68 On success, recvmmsg() returns the number of messages received in ms‐
69 gvec; on error, -1 is returned, and errno is set to indicate the error.
70
72 Errors are as for recvmsg(2). In addition, the following error can oc‐
73 cur:
74
75 EINVAL timeout is invalid.
76
77 See also BUGS.
78
80 Linux.
81
83 Linux 2.6.33, glibc 2.12.
84
86 The timeout argument does not work as intended. The timeout is checked
87 only after the receipt of each datagram, so that if up to vlen-1 data‐
88 grams are received before the timeout expires, but then no further
89 datagrams are received, the call will block forever.
90
91 If an error occurs after at least one message has been received, the
92 call succeeds, and returns the number of messages received. The error
93 code is expected to be returned on a subsequent call to recvmmsg(). In
94 the current implementation, however, the error code can be overwritten
95 in the meantime by an unrelated network event on a socket, for example
96 an incoming ICMP packet.
97
99 The following program uses recvmmsg() to receive multiple messages on a
100 socket and stores them in multiple buffers. The call returns if all
101 buffers are filled or if the timeout specified has expired.
102
103 The following snippet periodically generates UDP datagrams containing a
104 random number:
105
106 $ while true; do echo $RANDOM > /dev/udp/127.0.0.1/1234;
107 sleep 0.25; done
108
109 These datagrams are read by the example application, which can give the
110 following output:
111
112 $ ./a.out
113 5 messages received
114 1 11782
115 2 11345
116 3 304
117 4 13514
118 5 28421
119
120 Program source
121
122 #define _GNU_SOURCE
123 #include <arpa/inet.h>
124 #include <netinet/in.h>
125 #include <stdio.h>
126 #include <stdlib.h>
127 #include <string.h>
128 #include <sys/socket.h>
129 #include <time.h>
130
131 int
132 main(void)
133 {
134 #define VLEN 10
135 #define BUFSIZE 200
136 #define TIMEOUT 1
137 int sockfd, retval;
138 char bufs[VLEN][BUFSIZE+1];
139 struct iovec iovecs[VLEN];
140 struct mmsghdr msgs[VLEN];
141 struct timespec timeout;
142 struct sockaddr_in addr;
143
144 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
145 if (sockfd == -1) {
146 perror("socket()");
147 exit(EXIT_FAILURE);
148 }
149
150 addr.sin_family = AF_INET;
151 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
152 addr.sin_port = htons(1234);
153 if (bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
154 perror("bind()");
155 exit(EXIT_FAILURE);
156 }
157
158 memset(msgs, 0, sizeof(msgs));
159 for (size_t i = 0; i < VLEN; i++) {
160 iovecs[i].iov_base = bufs[i];
161 iovecs[i].iov_len = BUFSIZE;
162 msgs[i].msg_hdr.msg_iov = &iovecs[i];
163 msgs[i].msg_hdr.msg_iovlen = 1;
164 }
165
166 timeout.tv_sec = TIMEOUT;
167 timeout.tv_nsec = 0;
168
169 retval = recvmmsg(sockfd, msgs, VLEN, 0, &timeout);
170 if (retval == -1) {
171 perror("recvmmsg()");
172 exit(EXIT_FAILURE);
173 }
174
175 printf("%d messages received\n", retval);
176 for (size_t i = 0; i < retval; i++) {
177 bufs[i][msgs[i].msg_len] = 0;
178 printf("%zu %s", i+1, bufs[i]);
179 }
180 exit(EXIT_SUCCESS);
181 }
182
184 clock_gettime(2), recvmsg(2), sendmmsg(2), sendmsg(2), socket(2),
185 socket(7)
186
187
188
189Linux man-pages 6.05 2023-05-03 recvmmsg(2)