recv(2) | System Calls Manual | recv(2) |
recv, recvfrom, recvmsg - Recevoir un message d'un socket
Bibliothèque C standard (libc, -lc)
#include <sys/socket.h>
ssize_t recv(int sockfd, void buf[.len], size_t len, int flags); ssize_t recvfrom(int sockfd, void buf[restrict .len], size_t len, int flags, struct sockaddr *_Nullable restrict src_addr, socklen_t *_Nullable restrict addrlen); ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
Les appels système recv(), recvfrom() et recvmsg() sont utilisés pour recevoir des messages depuis un socket, et peuvent servir sur un socket orienté connexion ou non. Cette page décrit dans un premier temps les fonctionnalités communes de ces trois appels système, puis précise ensuite ce qui les différencie.
La seule différence entre recv() et read(2) est la présence de flags. Si l’argument flags est absent, recv() est généralement équivalent à read(2) (mais voir les NOTES). De plus, l'appel suivant
recv(sockfd, buf, len, flags);
est équivalent à :
recvfrom(sockfd, buf, len, flags, NULL, NULL);
Ces trois appels renvoient la longueur du message s'ils réussissent. Si un message est trop long pour tenir dans le tampon, les octets supplémentaires peuvent être abandonnés suivant le type de socket utilisé.
Si aucun message n'est disponible sur le socket, les appels à réception se mettent en attente, à moins que le socket soit non bloquant (voir fcntl(2)), auquel cas la valeur -1 est renvoyée et errno est positionnée à EAGAIN ou EWOULDBLOCK. Les appels à réception renvoient normalement les données disponibles, jusqu’au montant demandé, sans attendre d'avoir reçu le nombre exact réclamé.
Une application peut avoir recours à select(2), poll(2), ou epoll(7) pour savoir si des données supplémentaires arrivent dans le socket.
L'argument flags est constitué à partir d'un OU binaire entre une ou plusieurs des valeurs suivantes :
#define SO_EE_ORIGIN_NONE 0 #define SO_EE_ORIGIN_LOCAL 1 #define SO_EE_ORIGIN_ICMP 2 #define SO_EE_ORIGIN_ICMP6 3 struct sock_extended_err {
uint32_t ee_errno; /* numéro d'erreur */
uint8_t ee_origin; /* origine de l'erreur */
uint8_t ee_type; /* type */
uint8_t ee_code; /* code */
uint8_t ee_pad; /* remplissage */
uint32_t ee_info; /* données supplémentaires */
uint32_t ee_data; /* autres données */
/* Des données supplémentaires peuvent suivre */ }; struct sockaddr *SO_EE_OFFENDER(struct sock_extended_err *);
recvfrom() enregistre le message reçu dans le tampon buf. Le processus appelant doit préciser la taille de ce tampon dans len.
Si src_addr n'est pas NULL, et si le protocole sous-jacent fournit l'adresse de la source, celle-ci y est insérée dans le tampon désigné par src_addr. Dans ce cas, addrlen est un paramètre valeur-résultat. Avant l'appel, il doit être initialisé à la valeur de la taille du tampon associé à src_addr. En retour, addrlen est mis à jour avec la valeur réelle de l'adresse source. Cette adresse est tronquée si le tampon fourni n'a pas une taille suffisante ; dans ce cas addrlen renvoie un valeur supérieure à celle fournie lors de l'appel.
Si le processus appelant n'est pas intéressé par l'adresse de la source, src_addr et addrlen doivent avoir la valeur NULL.
L'appel recv() est normalement utilisé sur un socket connecté (voir connect(2)). Il est équivalent à l'appel :
recvfrom(fd, buf, len, flags, NULL, 0);
L'appel recvmsg() utilise une structure msghdr pour minimiser le nombre de paramètres à fournir directement. Cette structure est définie dans <sys/socket.h> comme ceci :
struct msghdr {
void *msg_name; /* Adresse optionnelle */
socklen_t msg_namelen; /* Taille de l'adresse */
struct iovec *msg_iov; /* Tableau scatter/gather */
size_t msg_iovlen; /* Nb. d’éléments dans msg_iov */
void *msg_control; /* Données annexes, voir ci‐dessous */
size_t msg_controllen; /* Taille du tampon de données annexe */
int msg_flags; /* Attributs du message reçu */ };
Le champ msg_name pointe vers un tampon alloué par l'appelant et qui est utilisé pour renvoyer l'adresse source lorsque le socket n'est pas connecté. L'appelant doit initialiser msg_namelen avec la taille de ce tampon avant l'appel ; si l'appel s'exécute avec succès, msg_name prend pour valeur la longueur de l'adresse renvoyée. Si l'application n'a pas besoin de connaître l'adresse source, on peut affecter la valeur NULL à msg_name.
Les champs msg_iov et msg_iovlen décrivent les emplacements de dispersion-regroupement (scatter-gather) tels qu'expliqués dans readv(2).
Le champ msg_control, de longueur msg_controllen, pointe sur un tampon utilisé pour les autres messages du protocole relatifs au contrôle, ou à d'autres données annexes. Lorsqu'on invoque recvmsg, msg_controllen doit contenir la longueur du tampon disponible dans msg_control ; lors du retour d’un appel réussi,il contiendra la longueur de la séquence du message de contrôle.
Les messages ont la forme
struct cmsghdr {
size_t cmsg_len; /* nombre d'octets de données, y compris l'en-tête
(de type socklen_t dans POSIX) */
int cmsg_level; /* protocole d'origine */
int cmsg_type; /* type dépendant du protocole */ /* suivi de
unsigned char cmsg_data[]; */ };
Les données annexes ne doivent être manipulées qu'avec les macros de cmsg(3).
À titre d'exemple, Linux utilise ce mécanisme de données annexes pour transmettre des erreurs étendues, des options IP ou des descripteurs de fichier sur des sockets de domaine UNIX. Pour plus d'informations sur l'utilisation de ce mécanisme sur divers domaines de socket, voir unix(7) et ip(7).
Le champ msg_flags du msghdr est rempli au retour de recvmsg(). Il peut contenir plusieurs attributs :
Ces appels renvoient le nombre d'octets reçus si elles réussissent, ou -1 si elles échouent. Dans ce dernier cas, errno permettra d'identifier la cause de l'erreur.
Lorsque le partenaire d'un socket de flux se ferme proprement, la valeur renvoyée est 0 (c'est-à-dire la valeur habituellement renvoyée lorsqu'on arrive à la fin d'un fichier).
Les sockets de datagrammes autorisent des datagrammes de longueur nulle dans différents domaines (par exemple, les domaines UNIX et Internet). Lorsque de tels datagrammes sont reçus, la valeur renvoyée est 0.
La valeur 0 peut aussi être renvoyée lorsque le nombre d'octets demandé en réception d'un socket de flux est égal à 0.
Voici quelques erreurs standards déclenchées par la couche socket. Des erreurs supplémentaires peuvent être générées et renvoyées par des modules du protocole sous-jacent. Consultez leurs pages de manuel.
POSIX.1-2001, POSIX.1-2008, 4.4BSD (les interfaces sont apparues pour la première fois dans 4.2BSD).
POSIX.1 décrit seulement les drapeaux MSG_OOB, MSG_PEEK et MSG_WAITALL.
Si un datagramme de taille nulle est en attente, read(2) et recv() avec un paramètre flags vide, donne un comportement différent. Dans ce cas, read(2) n'a aucun effet (le datagramme reste en attente) alors que recv() consomme le datagramme en attente.
Le type socklen_t a été inventé par POSIX. Voir aussi accept(2).
Selon POSIX.1, le champ msg_controllen de la structure msghdr devrait être de type socklen_t et le champ msg_iovlen devrait être de type int, mais ils ont tous deux le type size_t dans la glibc.
Consultez recvmmsg(2) pour plus d'informations au sujet d'un appel système propre à Linux, utilisé pour recevoir des datagrammes multiples avec un unique appel.
Un exemple d'utilisation de recvfrom() se trouve dans la page de manuel de getaddrinfo(3).
fcntl(2), getsockopt(2), read(2), recvmmsg(2), select(2), shutdown(2), socket(2), cmsg(3), sockatmark(3), ip(7), ipv6(7), socket(7), tcp(7), udp(7), unix(7)
La traduction française de cette page de manuel a été créée par Christophe Blaess <https://www.blaess.fr/christophe/>, Stéphan Rafin <stephan.rafin@laposte.net>, Thierry Vignaud <tvignaud@mandriva.com>, François Micaux, Alain Portal <aportal@univ-montp2.fr>, Jean-Philippe Guérard <fevrier@tigreraye.org>, Jean-Luc Coulon (f5ibh) <jean-luc.coulon@wanadoo.fr>, Julien Cristau <jcristau@debian.org>, Thomas Huriaux <thomas.huriaux@gmail.com>, Nicolas François <nicolas.francois@centraliens.net>, Florentin Duneau <fduneau@gmail.com>, Simon Paillard <simon.paillard@resel.enst-bretagne.fr>, Denis Barbier <barbier@debian.org>, David Prévot <david@tilapin.org>, Cédric Boutillier <cedric.boutillier@gmail.com>, Frédéric Hantrais <fhantrais@gmail.com> et Jean-Philippe MENGUAL <jpmengual@debian.org>
Cette traduction est une documentation libre ; veuillez vous reporter à la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.
Si vous découvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message à debian-l10n-french@lists.debian.org.
3 décembre 2022 | Pages du manuel de Linux 6.03 |