recvmmsg(2) System Calls Manual recvmmsg(2) NOM recvmmsg - Recevoir plusieurs message sur un socket BIBLIOTHEQUE Bibliotheque C standard (libc, -lc) SYNOPSIS #define _GNU_SOURCE /* Consultez feature_test_macros(7) */ #include int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout); DESCRIPTION L'appel systeme recvmmsg() est une extension de recvmsg(2) qui permet a l'appelant de recevoir plusieurs messages d'un socket en utilisant un seul appel systeme. (Cela ameliore les performances pour certaines applications.) Une autre propriete de ce cette extension de recvmsg(2) est la gestion d'une temporisation pour l'operation de reception. Le parametre sockfd est le descripteur de fichier de le socket emetteur. L'argument msgvec est un pointeur vers un tableau de structures mmsghdr. La taille de ce tableau est precisee dans vlen. La structure mmsghdr est definie dans comme ceci : struct mmsghdr { struct msghdr msg_hdr; /* En-tete du message */ unsigned int msg_len; /* Nombre d'octets recus pour l'en-tete */ }; Le champ msg_hdr est une structure msghdr, conformement a recvmsg(2). Le champ msg_len est le nombre d'octets retourne par le message dans l'entree. Ce champ a la meme valeur que la valeur de retour de la simple commande recvmsg(2) sur l'en-tete. L'argument flags contient le OU binaire de la collection des attributs. Les attributs sont ceux documentes pour recvmsg(2), plus : MSG_WAITFORONE (depuis Linux 2.6.34) Activer MSG_DONTWAIT apres le premier message recu. L'argument timeout est un pointeur vers une struct timespec (consultez clock_gettime(2)) definissant la temporisation (en secondes et nanosecondes) pour l'operation de reception (mais consultez la section BOGUES !). Cet intervalle sera arrondi a la granularite de l'horloge systeme, et peut etre legerement modifie a cause des delais d'ordonnancement du noyau. Si timeout est le pointeur nul, l'operation se bloque indefiniment. Un appel bloquant recvmmsg() bloque jusqu'a la reception de vlsen messages ou l'expiration de la temporisation. Un appel non bloquant lit autant de messages que disponibles (jusqu'a la limite indiquee par vlen) et retourne immediatement. Au retour de recvmmsg(), les elements successifs de msgvec sont mis a jour pour contenir l'information concernant chaque message recu : les champs secondaires de msg_hdr sont mis a jour conformement a recmsg(2). La valeur de retour de l'appel indique le nombre d'elements de msgvec mis a jour. VALEUR RENVOYEE En cas du succes, recvmmsg() retourne le nombre de messages recus dans msgvec ; Dans le cas contraire, il renvoie -1 et remplit errno avec le code d'erreur. ERREURS Les erreurs sont les memes que pour recvmsg(2), plus l'erreur suivante : EINVAL timeout n'est pas valable. Voir aussi BOGUES. STANDARDS Linux. HISTORIQUE Linux 2.6.33, glibc 2.12. BOGUES L'argument timeout n'a pas l'effet que l'on pourrait attendre. La non-expiration du timeout est verifiee apres la reception de chaque datagramme, de sorte que si moins de vlen-1 datagrammes sont recus avant l'expiration du timeout, mais qu'aucun datagramme n'est recu ensuite, l'appel restera bloque indefiniment. Si une erreur survient apres qu'au moins un message ait ete recu, l'appel reussit et renvoie le nombre de messages recus. Le code d'erreur est prevu pour etre renvoye lors de l'appel suivant a recvmmsg(). Cependant, dans l'implementation actuelle, le code d'erreur peut etre emis en meme temps par un evenement reseau non lie sur un socket, comme un paquet ICMP entrant. EXEMPLES Le programme suivant utilise recvmmsg() pour recevoir plusieurs messages sur un socket et les stocker dans plusieurs tampons. L'appel termine si tous les tampons sont remplis ou si le delai indique est depasse. Le morceau de code suivant engendre periodiquement des datagrammes UDP contenant un nombre aleatoire : $ while true; do echo $RANDOM > /dev/udp/127.0.0.1/1234; sleep 0.25; done Ces datagrammes sont lus par le programme ci-dessous, qui peut par exemple afficher la sortie suivante : $ ./a.out 5 messages recus 1 11782 2 11345 3 304 4 13514 5 28421 Source du programme #define _GNU_SOURCE #include #include #include #include #include #include #include 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 recus\n", 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); } VOIR AUSSI clock_gettime(2), recvmsg(2), sendmmsg(2), sendmsg(2), socket(2), socket(7) TRADUCTION La traduction francaise de cette page de manuel a ete creee par Christophe Blaess , Stephan Rafin , Thierry Vignaud , Francois Micaux, Alain Portal , Jean-Philippe Guerard , Jean-Luc Coulon (f5ibh) , Julien Cristau , Thomas Huriaux , Nicolas Francois , Florentin Duneau , Simon Paillard , Denis Barbier , David Prevot , Cedric Boutillier , Frederic Hantrais et Jean-Philippe MENGUAL Cette traduction est une documentation libre ; veuillez vous reporter a la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITE LEGALE. Si vous decouvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message a . Pages du manuel de Linux 6.06 31 octobre 2023 recvmmsg(2)