ACCEPT
Section: Manuel du programmeur Linux (2) Updated: 18 juillet 2003 Index
NOM
SYNOPSIS
DESCRIPTION
NOTES
VALEUR RENVOYÉE
GESTION DES ERREURS
ERREURS
CONFORMITÉ
NOTE
VOIR AUSSI
TRADUCTION
NOM
accept - Accepter une connexion sur une socket.
SYNOPSIS
#include <sys/types.h>
#include <sys/socket.h>
int accept(int sock, struct sockaddr *adresse, socklen_t *longueur);
DESCRIPTION
accept
est utilisé généralement avec des processus serveurs orientés-connexion.
Cet appel système est employé avec les sockets utilisant un protocole
en mode connecté
( SOCK_STREAM,
SOCK_SEQPACKET
et
SOCK_RDM)
Il 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 pour cette socket un nouveau descripteur de fichier qu'il renvoie.
La nouvelle socket n'est plus en état d'écoute.
La socket originale
sock
n'est pas modifiée par l'appel-système. Remarquez que les attributs du
descripteur de fichier (tout ce qu'on peut configurer avec l'option
F_SETFL
de fcntl() comme l'état non-bloquant ou asynchrone), ne sont pas hérités
durant un
accept.
L'argument
sock
est une socket qui a été créée avec la fonction
socket(2).
attachée à une adresse avec
bind(2).
et attend des connextions après un appel
listen(2).
L'argument
adresse
est un pointeur sur une structure sockaddr. La structure sera remplie avec
l'adresse du correspondant se connectant, telle qu'elle est
connue par la couche de communication. Le format exact du
paramètre
adresse
dépend du domaine dans lequel la communication s'établit. (Voir
socket(2)
et la page de manuel correspondant au protocole).
L'argument
longueur
est un paramètre-résultat : il doit contenir initialement la
taille de la structure pointée par
adresse,
et est renseigné au retour par la longueur réelle (en octet) de
l'adresse remplie. Quand
adresse
vaut NULL, rien n'est rempli.
S'il n'y a pas de connexion en attente dans la file,
et si la socket n'est
pas marquée comme non-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 EAGAIN.
Pour être prévenu de l'arrivée d'une connexion sur une socket on peut utiliser
select(2)
ou
poll(2).
Un évènement "lecture" sera délivré lorsqu'une tentative de connexion
aura lieu, et on pourra alors appeler
accept
pour la valider. Autrement, on peut configurer la socket pour qu'elle
envoie un signal
SIGIO
lorsqu'une activité la concernant se produit, voir
socket(7)
pour plus de détails.
Pour certains protocoles nécessitant une confirmation explicite,
comme
DECNet,
accept
peut être considéré comme extrayant simplement la connexion suivante de
la file, sans demander de confirmation. On peut effectuer la confirmation
par une simple lecture ou écriture sur le nouveau descripteur, et le rejet
en fermant la nouvelle socket. Pour le moment, seul
DECNet
se comporte ainsi sous Linux.
NOTES
Il n'y a pas nécessairement de connexion en attente après la réception de
SIGIO
ou après que
select(2)
ou
poll(2)
indiquent quelque chose à lire. En effet la connexion peut avoir été annulée
à cause d'une erreur réseau asynchrone ou par un autre thread avant que
accept
ne se termine.
Si cela se produit, l'appel bloquera en attendant une autre connexion.
Pour s'assurer
que
accept
ne bloquera jamais, la socket
sock
transmise doit avoir l'attribut
O_NONBLOCK
(voir
socket(7)).
VALEUR RENVOYÉE
L'appel renvoie -1 en cas d'erreur. S'il réussit il renvoie
un entier non-négatif, constituant un descripteur pour la nouvelle socket.
GESTION DES ERREURS
Sous Linux,
accept
renvoie les erreurs réseau déjà en attente sur la socket comme
une erreur de
l'appel-système.
Ce comportement diffère d'autres implémentations des sockets BSD.
Pour un comportement fiable, une application doit détecter les
erreurs réseau définies par le protocole après le
accept
et les traiter
comme des erreurs
EAGAIN,
en réitérant le mécanisme. Dans le cas de TCP/IP, ces erreurs sont
ENETDOWN,
EPROTO,
ENOPROTOOPT,
EHOSTDOWN,
ENONET,
EHOSTUNREACH,
EOPNOTSUPP,
et
ENETUNREACH.
ERREURS
accept
doit échouer si :
- EAGAIN ou EWOULDBLOCK
-
La socket est non-bloquante et aucune connexion n'est
présente dans la file.
- EBADF
-
Le descripteur est invalide.
- ENOTSOCK
-
Le descripteur n'est pas celui d'une socket.
- EOPNOTSUPP
-
La socket de référence n'est pas de type
SOCK_STREAM.
- EINTR
-
L'appel-système a été interrompu par l'arrivée d'un
signal avant qu'une connexion valide ne survienne.
- ECONNABORTED
-
Une connexion a été abandonnée.
- EINVAL
-
La socket n'est pas en attente de connexions.
- EMFILE
-
La limite des descripteurs ouverts pour le processus a été atteinte.
- ENFILE
-
Le nombre maximal de descripteurs sur le système a été atteint.
accept
peut échouer si :
- EFAULT
-
adresse
n'est pas dans l'espace d'adressage accessible
en écriture.
- 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.
- EPROTO
-
Erreur de protocole.
La version Linux de
accept
peut échouer si :
- EPERM
-
Les règles du firewall interdisent la connexion.
De plus il peut se produire des erreurs réseau dépendant du protocole
de la socket. Certains noyaux Linux peuvent renvoyer d'autres erreurs
comme
ENOSR,
ESOCKTNOSUPPORT,
EPROTONOSUPPORT,
ETIMEDOUT.
L'erreur
ERESTARTSYS
peut être rencontrée durant un suivi dans un débogueur.
CONFORMITÉ
SVr4, BSD 4.4 (La fonction
accept
est apparue dans BSD 4.2).
La page de manuel BSD documente cinq erreurs possibles
(EBADF, ENOTSOCK, EOPNOTSUPP, EWOULDBLOCK, EFAULT).
SUSv3 documente les erreurs EAGAIN, EBADF, ECONNABORTED, EINTR, EINVAL, EMFILE,
ENFILE, ENOBUFS, ENOMEM, ENOTSOCK, EOPNOTSUPP, EPROTO, EWOULDBLOCK, De
Plus, SUSv2 documentait EFAULT et ENOSR.
La version Linux de accept ne fait pas hériter les attributs comme
O_NONBLOCK.
Ce comportement est différent d'autres implémentations BSD. Les
programmes portables ne doivent pas s'appuyer sur cette particularité,
et doivent reconfigurer les attributs sur la socket renvoyée par accept.
NOTE
Le troisième argument de
accept
était, à l'origine, déclaré comme un `int *' (ceci 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 l'interface des sockets BSD.
Quoiqu'il en soit, 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 inavouées (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
TRADUCTION
Christophe Blaess, 1996-2003.
|