Index général des pages de man   Index Section man 2   Table des Matières de accept   Imprime la page de man accept en mode Texte   Recherche dans les pages de man   Page de man en français      Fonctions du système (section 2)

accept

 
  

Nom

accept - Accepter une connexion sur une socket.

Synopsis

#include <sys/types.h>
#include <sys/socket.h>
int accept(int sock, struct sockaddr *adresse, socklent_t *longueur);

Description

accept est utilisé généralement avec des processus serveurs orientés-connexion.

L'argument sock est une socket qui a été créée avec la fonction socket(2) . On lui a affecté une adresse avec bind(2) . Enfin on a indiqué au système, avec listen(2) qu'elle désirait recevoir des connexions entrantes.

L'appel système accept extrait la première connexion de la file des connexions en attente, crée une nouvelle socket avec essentiellement les mêmes propriétés que sock et alloue un nouveau descripteur de fichier pour cette socket.

S'il n'y a pas de connexion en attente dans la file, et si la socket est bloquante, accept se met en attente d'une connexion. Si la socket est non-bloquante, et qu'aucune connexion n'est présente dans la file, accept retourne une erreur décrite ci-dessous.

Une socket acceptée ne peut pas être utilisée pour accepter de nouvelles connexions. La socket originale sock reste ouverte. Remarquez que les attributs correspondant aux propriétés du descripteur de fichier (tout ce qu'on peut configurer avec l'option F_SETFL de setfl() comme l'état non-bloquant ou asynchrone), ne sont pas hérités durant un accept. L'argument adresse est un paramètre résultat qui est renseigné avec l'adresse de l'entité se connectant, telle qu'elle est connue par la couche de communication. Le format exact du paramètre adresse est fonction du domaine dans lequel la communication s'établit. Le paramètre-resultat longueur est renseigné avec la longueur (en octets) de l'adresse retournée. Ce paramètre doit initialement contenir la longueur du paramètre adresse.

Cet appel système est utilisé avec les sockets utilisant un protocole en mode connecté, généralement du type SOCK_STREAM.

Lorsque l'on désire accepter des connexions sur plusieurs sockets simultanément, il est important de ne pas rester bloqué en attente avec l'appel accept sur une seule d'entre elles. Il est alors possible d'utiliser l'appel-système select(2) sur l'ensemble des sockets pour déterminer la disponibilité des données à lire, et d'effectuer ensuite l'appel accept sur celles qui ont effectivement reçu des demandes de connexion.

Pour certains protocoles nécessitant une confirmation explicite, comme ISO ou DATAKIT, accept peut être considéré comme extrayant simplement la connexion suivante de la file, sans demander de confirmation. Cette confirmation peut être effectuée par une simple lecture ou écriture sur le nouveau descripteur de fichier, et un rejet peut être effectué en fermant simplement la nouvelle socket.

On peut obtenir les données utilisateur d'une connexion sans confirmation, en effectuant un appel-système recvmsg(2) avec un msg_iovlen valant zéro, et un msg_controllen non nul, ou en effectuant une demande getsockopt(2) .

De même on peut fournir des informations sur un rejet de connexion en utilisant un appel sendmsg(2) en fournissant uniquement les données de contrôle, ou en appelant setsockopt(2) .

Valeur Renvoyée

accept renvoie -1 en cas d'erreur. S'il réussit il renvoie un entier non-négatif, constituant un descripteur pour la nouvelle socket.

Erreurs

EBADF
sock est un descripteur invalide.
ENOTSOCK
sock est un descripteur de fichier, pas de socket.
EOPNOTSUPP
La socket de référence n'est pas de type SOCK_STREAM.
EFAULT
adresse pointe en-dehors de l'espace d'adressage accessible.
EPERM
Certaines règles de firewall du noyau interdisent les connexions.
ENOBUFS, ENOMEM
Par assez de mémoire disponible. En général, cette erreur due à la taille limitée du buffer des sockets, et pas à la mémoire système proprement dite, mais ce n'est pas toujours certain.
EWOULDBLOCK
La socket est non-bloquante et aucune connexion n'est présente dans la file.

De plus, des erreurs dues au protocole réseau peuvent être renvoyées. Certains noyaux Linux peuvent donner les erreurs EMFILE, EINVAL, ENOSR, ECONNABORTED, ESOCKTNOSUPPORT, EPROTONOSUPPORT, ETIMEDOUT, ERESTARTSYS.

Exemple

Un scénario typique de mise en oeuvre de serveur orienté connexion est le suivant :


int  pnum;
int  sock;
int  nouvelle;
sock  = socket (famille, type, 0);
if (sock < 0) {
    perror ("socket");
    exit (1);
}
if (bind (sock, & mon_adresse, longueur_adresse) < 0) {
    perror ("bind");
    exit (1);
}
if (listen (sock, 5) < 0) {
    perror ("listen");
    exit (1);
}
while (1) {
    nouvelle = accept (sock, & adresse_client, & lg_adresse_client);
    if (nouvelle < 0) {
        perror ("accept");
        exit (1);
    }
    if ((pnum = fork ()) == 0) {
        /* Processus fils */
        close (sock);
        Traiter_le_client (nouvelle);
        exit (0);
    }
    if (pnum > 0) {
        /* Processus père */
        close (nouvelle);
        /* Attendre la connexion suivante */
        continue;
    }
    perror ("fork");
    exit (1);
}

Conformité

SVr4, BSD 4.4. La fonction accept est apparue dans BSD 4.2. IRIX fournit des conditions d'erreur supplémentaires EMFILE et ENFILE. Solaris documente les erreurs supplémentaires EINTR, ENODEV, ENOMEM, ENOSR et EPROTO.

Note

Le troisième argument de accept était, à l'origine, déclaré comme un `int *' (et c'est le cas dans libc4 et libc5 ainsi que pour beaucoup d'autres systèmes comme BSD 4.*, SunOS 4, SGI). Une proposition de standard POSIX 1003.1g l'a modifié en `size_t *' et c'est ce qu'utilise SunOS. Les dernières propositions POSIX en ont fait un `socklen_t *', ce que suivent les spécifications Single Unix, et la glibc2. Pour citer Linus Torvalds: `Toute bibliothèque sensée doit garder "socklen_t" équivalent à un int. Toute autre chose invaliderait tout le niveau des sockets BSD. POSIX l'avait d'abord remplacé par un size_t, et je m'en suis plaint violemment (ainsi que d'autres heureusement, mais bien entendu pas tant que ça). Le remplacement par un size_t est complètement inutile car size_t à exactement la même taille qu'un int sur les architectures 64 bits par exemple. Et il a la même taille qu'un "int" parce que c'était ainsi qu'étaient définies les sockets BSD. Finalement, les gens de POSIX ont compris et ont créé un "socklen_t". Ils n'auraient jamais dû y toucher, mais une fois commencé, ils ont décidé de créer un type spécifique, pour des raisons encore inavouées (il y a probablement quelqu'un qui ne veut pas perdre la face en expliquant que le premier travail était stupide et ils ont simplement renommé leur bricolage).

Voir Aussi

bind(2) , connect(2) , listen(2) , select(2) , socket(2)

Traduction

Christophe Blaess, 1997.


Table des matières


Haut de page

© 1996-2000 Adaptation française "Christophe Blaess"