RECV(2)

NOM
recv, recvfrom, recvmsg - Recevoir un message sur une socket

SYNOPSIS
#include <sys/types.h>
#include <sys/socket.h>

int recv(int s, void *buf, int len, unsigned int flags);

ssize_t recvfrom(int s, void *buf, size_t len, int flags,
                 struct sockaddr *from, socklen_t *fromlen);

ssize_t recvmsg(int s, struct msghdr *msg, unsigned int flags);

DESCRIPTION
Les appels système recvfrom() et recvmsg() sont utilisés pour recevoir des messages depuis une socket s, et peuvent servir sur une socket orientée connexion ou non.

Si from n'est pas NULL, et si le protocole sous-jacent fournit l'adresse de la source, celle-ci y est insérée. L'argument fromlen est un paramètre résultat, initialisé à la taille du tampon from, et modifié en retour pour indiquer la taille réelle de l'adresse enregistrée.

L'appel recv() est normalement utilisé sur une socket connectée (voir connect(2)) et est équivalent à recvfrom() avec un paramètre from nul.

Ces trois routines renvoient la longueur du message si elles 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 la socket, les fonctions de réception se mettent en attente, à moins que la socket soit non bloquante (voir fcntl(2)), auquel cas la valeur -1 est renvoyée, et errno est positionnée à EAGAIN. Les fonctions de réception renvoient normalement les données disponibles sans attendre d'avoir reçu le nombre exact réclamé.

Les appels système select(2) ou poll(2) peuvent permettre de déterminer si des données supplémentaires sont disponibles.

L'argument flags de l'appel recv() est constitué par un OU binaire entre une ou plusieurs des valeurs suivantes :

MSG_CMSG_CLOEXEC (recvmsg() seulement ; depuis Linux 2.6.23)
    Positionne l'attribut « close-on-exec » pour le descripteur de fichier reçu via un descripteur de fichier de domaine Unix en utilisant l'opération SCM_RIGHTS (décrite dans unix(7)). Cet attribut est utile pour les mêmes raisons que l'attribut O_CLOEXEC de open(2).

MSG_DONTWAIT
    Activer les opérations non-bloquantes. Si l'opération devait bloquer, EAGAIN serait renvoyé (on peut aussi activer ce comportement avec l'option O_NONBLOCK de la fonction F_SETFL de fcntl(2).)

MSG_ERRQUEUE
    Cet attribut demande que les erreurs soient reçues depuis la file d'erreur de la socket. Les erreurs sont transmises dans un message annexe dont le type dépend du protocole (IP_RECVERR pour IPv4). Il faut alors fournir un tampon de taille suffisante. Voir cmsg(3) et ip(7) pour plus de détails. Le contenu du paquet original qui a causé l'erreur est passé en tant que données normales dans msg_iovec. L'adresse de destination originale du datagramme ayant causé l'erreur est fournie dans msg_name.

    Pour les erreurs locales, aucune adresse n'est passée (ceci peut être vérifié dans le membre cmsg_len de cmsghdr). Pour les erreurs reçues, le MSG_ERRQUEUE est placé dans msghdr. Après qu'une erreur ait été transmise, l'erreur en attente sur la socket est régénérée en fonction de la prochaine erreur dans la file, et sera transmise lors de l'opération suivante sur la socket. L'erreur est contenue dans une structure sock_extended_err :
    #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 {
        u_int32_t       ee_errno;       /* numéro d'erreur        */
        u_int8_t        ee_origin;      /* origine de l'erreur    */
        u_int8_t        ee_type;        /* type                   */
        u_int8_t        ee_code;        /* code                   */
        u_int8_t        ee_pad;         /* remplissage            */
        u_int32_t       ee_info;        /* données supplémentaires*/
        u_int32_t       ee_data;        /* autres données         */
        /* More data may follow */
    };
    struct sockaddr *SO_EE_OFFENDER(struct sock_extended_err *);

    ee_errno contient le code errno de l'erreur en file. ee_origin est le code d'origine de l'erreur. Les autres champs sont spécifiques au protocole. La macro SOCK_EE_OFFENDER renvoie un pointeur sur l'adresse de l'objet réseau ayant déclenché l'erreur, à partir d'un pointeur sur le message. Si l'adresse n'est pas connue, le membre sa_family de la structure sockaddr contient AF_UNSPEC et les autres champs de la structure sockaddr sont indéfinis. Le contenu du paquet ayant déclenché l'erreur est transmis en données normales.

    Pour les erreurs locales, aucune adresse n'est transmise (ceci peut être vérifié dans le champ cmsg_len de cmsghdr). À la réception d'erreur, msghdr sera rempli avec MSG_ERRQUEUE. Après la lecture d'une erreur, l'état de la socket est modifié d'après l'erreur suivante dans la file.

MSG_OOB
    permet la lecture des données hors-bande qui ne seraient autrement pas placées dans le flux de données normales. Certains protocoles placent ces données hors-bande en tête de la file normale, et cette option n'a pas lieu d'être dans ce cas.

MSG_PEEK
    permet de lire les données en attente dans la file sans les enlever de cette file. Ainsi une lecture ultérieure renverra à nouveau les mêmes données.

MSG_TRUNC
    Renvoyer la longueur réelle du paquet, même s'il était plus long que le tampon transmis. Valide uniquement pour les sockets paquets.

MSG_WAITALL
    demande que l'opération de lecture soit bloquée jusqu'à ce que la requête complète soit satisfaite. Toutefois, la lecture peut renvoyer quand même moins de données que prévu si un signal est reçu, ou si une erreur ou une déconnexion se produisent.

L'appel recvmsg() utilise une structure msghdr pour minimiser le nombre de paramètres à fournir directement. Cette structure à la forme suivante, définie dans <sys/socket.h> :
struct msghdr {
    void	 *msg_name;       /* optional address */
    socklen_t     msg_namelen;    /* size of address */
    struct iovec *msg_iov;        /* scatter/gather array */
    size_t        msg_iovlen;     /* # elements in msg_iov */
    void         *msg_control;    /* ancillary data, see below */
    socklen_t     msg_controllen; /* ancillary data buffer len */
    int           msg_flags;      /* flags on received message */
};

Ici msg_name et msg_namelen spécifient l'adresse d'origine si la socket n'est pas connectée, msg_name peut être un pointeur nul si le nom n'est pas nécessaire. msg_iov et msg_iovlen décrivent les tampons de réception comme décrit dans readv(2). msg_control, de longueur msg_controllen, pointe sur un tampon utilisé pour les autres messages relatifs au protocole, ou à d'autres données annexes. Lorsqu'on invoque recvmsg(), msg_controllen doit contenir la longueur disponible dans le tampon msg_control ; au retour il contiendra la longueur de la séquence de message de contrôle.

Les messages ont la forme :
struct cmsghdr {
    socklen_t cmsg_len;     /* data byte count, including hdr */
    int       cmsg_level;   /* originating protocol */
    int       cmsg_type;    /* protocol-specific type */
/* followed by
    u_char    cmsg_data[]; */
};

Les données de service ne doivent être manipulées qu'avec les macros de cmsg(3).

À titre d'exemple, Linux utilise ce mécanisme pour transmettre des erreurs étendues, des options IP, ou des descripteurs de fichiers sur des sockets Unix.

Le champ msg_flags du msghdr est rempli au retour de recvmsg(). Il peut contenir plusieurs attributs :

MSG_EOR
    indique une fin d'enregistrement, les données reçues terminent un enregistrement (utilisé généralement avec les sockets du type SOCK_SEQPACKET).

MSG_TRUNC
    indique que la portion finale du datagramme a été abandonnée car le datagramme était trop long pour le tampon fourni.

MSG_CTRUNC
    indique que des données de contrôle ont été abandonnées à cause d'un manque de place dans le tampon de données annexes.

MSG_OOB
    indique que des données hors-bande ont été reçues.

MSG_ERRQUEUE
    indique qu'aucune donnée n'a été reçue, sauf une erreur étendue depuis la file d'erreurs.

VALEUR RENVOYÉE
Ces fonctions renvoient le nombre d'octets reçus si elles réussissent, ou -1 si elles échouent. La valeur de retour sera 0 si le pair a effectué un arrêt normal.

ERREURS
Il y a des erreurs standards déclenchées par le niveau socket, et des erreurs supplémentaires spécifiques aux protocoles. Voyez leurs pages de manuel.

EAGAIN
    La socket est non-bloquante et aucune donnée n'est disponible, ou un délai de timeout a été indiqué, et il a expiré sans que l'on ait reçu quoi que ce soit.

EBADF
    L'argument s n'est pas un descripteur valide.

ECONNREFUSED
    Un hôte distant a refusé la connexion réseau (généralement parce qu'il n'offre pas le service demandé).

EFAULT
    Un tampon pointe en dehors de l'espace d'adressage accessible.

EINTR
    Un signal a interrompu la lecture avant que des données soient disponibles.

EINVAL
    Un argument est invalide.

ENOMEM
    Impossible d'allouer de la mémoire pour recvmsg().

ENOTCONN
    La socket est associée à un protocole orienté connexion et n'a pas encore été connectée (voir connect(2) et accept(2)).

ENOTSOCK
    L'argument s ne correspond pas à une socket.

CONFORMITÉ
BSD 4.4 (ces fonctions sont apparues dans BSD 4.2), POSIX.1-2001.

POSIX.1-2001 décrit seulement les drapeaux MSG_OOB, MSG_PEEK, et MSG_WAITALL.

NOTES
Les prototypes fournis concernent la glibc 2. Les Spécifications Single Unix les définissent, mais le type de retour est ssize_t (alors que BSD 4.*, libc4 , et libc5 renvoient un int). L'argument flags est un int dans BSD 4.*, mais unsigned int dans libc4 et libc5. L'argument len est un int dans BSD 4.*, mais un size_t dans libc4 et libc5. L'argument fromlen est un int * dans BSD 4.*, libc4 et libc5. Le type socklen_t * a été inventé par POSIX. Conformément à POSIX.1-2001, le champ msg_controllen de la structure msghdr devrait être typé socklen_t, mais la glibc actuelle (2.4) le type comme un size_t.

EXEMPLE
Un exemple de l'utilisation de recvfrom() est donné dans getaddrinfo(3).

VOIR AUSSI
accept(2), fcntl(2), getsockopt(2), read(2), select(2), socket(2), shutdown(2), cmsg(3), sockatmark(3)

TRADUCTION

Ce document est une traduction réalisée par Christophe Blaess <http://www.blaess.fr/christophe/> le 13 octobre 1996 et révisée le 22 décembre 2007.

L'équipe de traduction a fait le maximum pour réaliser une adaptation française de qualité. La version anglaise la plus à jour de ce document est toujours consultable via la commande : « LANG=C man 2 recv ». N'hésitez pas à signaler à l'auteur ou au traducteur, selon le cas, toute erreur dans cette page de manuel.