| .\" Copyright (c) 2012 by Michael Kerrisk <mtk.manpages@gmail.com> |
| .\" with some material from a draft by |
| .\" Stephan Mueller <stephan.mueller@atsec.com> |
| .\" in turn based on Andi Kleen's recvmmsg.2 page. |
| .\" |
| .\" %%%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 |
| .\" |
| .TH SENDMMSG 2 2020-06-09 "Linux" "Linux Programmer's Manual" |
| .SH NAME |
| sendmmsg \- send 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 sendmmsg(int " sockfd ", struct mmsghdr *" msgvec \ |
| ", unsigned int " vlen "," |
| .BI " int " flags ");" |
| .fi |
| .SH DESCRIPTION |
| The |
| .BR sendmmsg () |
| system call is an extension of |
| .BR sendmsg (2) |
| that allows the caller to transmit multiple messages on a socket |
| using a single system call. |
| (This has performance benefits for some applications.) |
| .\" See commit 228e548e602061b08ee8e8966f567c12aa079682 |
| .PP |
| The |
| .I sockfd |
| argument is the file descriptor of the socket |
| on which data is to be transmitted. |
| .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 bytes transmitted */ |
| }; |
| .EE |
| .in |
| .PP |
| The |
| .I msg_hdr |
| field is a |
| .I msghdr |
| structure, as described in |
| .BR sendmsg (2). |
| The |
| .I msg_len |
| field is used to return the number of bytes sent from the message in |
| .IR msg_hdr |
| (i.e., the same as the return value from a single |
| .BR sendmsg (2) |
| call). |
| .PP |
| The |
| .I flags |
| argument contains flags ORed together. |
| The flags are the same as for |
| .BR sendmsg (2). |
| .PP |
| A blocking |
| .BR sendmmsg () |
| call blocks until |
| .I vlen |
| messages have been sent. |
| A nonblocking call sends as many messages as possible |
| (up to the limit specified by |
| .IR vlen ) |
| and returns immediately. |
| .PP |
| On return from |
| .BR sendmmsg (), |
| the |
| .I msg_len |
| fields of successive elements of |
| .IR msgvec |
| are updated to contain the number of bytes transmitted from the corresponding |
| .IR msg_hdr . |
| The return value of the call indicates the number of elements of |
| .I msgvec |
| that have been updated. |
| .SH RETURN VALUE |
| On success, |
| .BR sendmmsg () |
| returns the number of messages sent from |
| .IR msgvec ; |
| if this is less than |
| .IR vlen , |
| the caller can retry with a further |
| .BR sendmmsg () |
| call to send the remaining messages. |
| .PP |
| On error, \-1 is returned, and |
| .I errno |
| is set to indicate the error. |
| .SH ERRORS |
| Errors are as for |
| .BR sendmsg (2). |
| An error is returned only if no datagrams could be sent. |
| See also BUGS. |
| .\" commit 728ffb86f10873aaf4abd26dde691ee40ae731fe |
| .\" ... only return an error if no datagrams could be sent. |
| .\" If less than the requested number of messages were sent, the application |
| .\" must retry starting at the first failed one and if the problem is |
| .\" persistent the error will be returned. |
| .\" |
| .\" This matches the behavior of other syscalls like read/write - it |
| .\" is not an error if less than the requested number of elements are sent. |
| .SH VERSIONS |
| The |
| .BR sendmmsg () |
| system call was added in Linux 3.0. |
| Support in glibc was added in version 2.14. |
| .SH CONFORMING TO |
| .BR sendmmsg () |
| is Linux-specific. |
| .SH NOTES |
| The value specified in |
| .I vlen |
| is capped to |
| .B UIO_MAXIOV |
| (1024). |
| .\" commit 98382f419f32d2c12d021943b87dea555677144b |
| .\" net: Cap number of elements for sendmmsg |
| .\" |
| .\" To limit the amount of time we can spend in sendmmsg, cap the |
| .\" number of elements to UIO_MAXIOV (currently 1024). |
| .\" |
| .\" For error handling an application using sendmmsg needs to retry at |
| .\" the first unsent message, so capping is simpler and requires less |
| .\" application logic than returning EINVAL. |
| .SH BUGS |
| If an error occurs after at least one message has been sent, |
| the call succeeds, and returns the number of messages sent. |
| The error code is lost. |
| The caller can retry the transmission, |
| starting at the first failed message, but there is no guarantee that, |
| if an error is returned, it will be the same as the one that was lost |
| on the previous call. |
| .SH EXAMPLES |
| The example below uses |
| .BR sendmmsg () |
| to send |
| .I onetwo |
| and |
| .I three |
| in two distinct UDP datagrams using one system call. |
| The contents of the first datagram originates from a pair of buffers. |
| .PP |
| .EX |
| #define _GNU_SOURCE |
| #include <netinet/ip.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <sys/types.h> |
| #include <sys/socket.h> |
| |
| int |
| main(void) |
| { |
| int sockfd; |
| struct sockaddr_in addr; |
| struct mmsghdr msg[2]; |
| struct iovec msg1[2], msg2; |
| int retval; |
| |
| 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 (connect(sockfd, (struct sockaddr *) &addr, sizeof(addr)) == \-1) { |
| perror("connect()"); |
| exit(EXIT_FAILURE); |
| } |
| |
| memset(msg1, 0, sizeof(msg1)); |
| msg1[0].iov_base = "one"; |
| msg1[0].iov_len = 3; |
| msg1[1].iov_base = "two"; |
| msg1[1].iov_len = 3; |
| |
| memset(&msg2, 0, sizeof(msg2)); |
| msg2.iov_base = "three"; |
| msg2.iov_len = 5; |
| |
| memset(msg, 0, sizeof(msg)); |
| msg[0].msg_hdr.msg_iov = msg1; |
| msg[0].msg_hdr.msg_iovlen = 2; |
| |
| msg[1].msg_hdr.msg_iov = &msg2; |
| msg[1].msg_hdr.msg_iovlen = 1; |
| |
| retval = sendmmsg(sockfd, msg, 2, 0); |
| if (retval == \-1) |
| perror("sendmmsg()"); |
| else |
| printf("%d messages sent\en", retval); |
| |
| exit(0); |
| } |
| .EE |
| .SH SEE ALSO |
| .BR recvmmsg (2), |
| .BR sendmsg (2), |
| .BR socket (2), |
| .BR socket (7) |