accept, accept4 - Accepter une connexion sur une socket
Bibliothèque C standard (
libc,
-lc)
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *_Nullable restrict addr,
socklen_t *_Nullable restrict addrlen);
#define _GNU_SOURCE /* Consultez feature_test_macros(7) */
#include <sys/socket.h>
int accept4(int sockfd, struct sockaddr *_Nullable restrict addr,
socklen_t *_Nullable restrict addrlen, int flags);
L'appel système
accept() est employé avec les sockets
utilisant un protocole en mode connecté (
SOCK_STREAM,
SOCK_SEQPACKET). Il extrait la première connexion de la file des
connexions en attente de la socket
sockfd à l'écoute,
crée une nouvelle socket et alloue pour cette socket un nouveau
descripteur de fichier qu'il renvoie. La nouvelle socket n'est pas en
état d'écoute. La socket originale
sockfd n'est pas
modifiée par l'appel système.
L'argument
sockfd est une socket qui a été
créée avec la fonction
socket(2), attachée
à une adresse avec
bind(2), et attend des connexions
après un appel
listen(2).
L'argument
addr 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
addr dépend du domaine dans lequel la
communication s'établit (consultez
socket(2) et la page de
manuel correspondant au protocole). Quand
addr vaut NULL, rien n'est
rempli ; dans ce cas,
addrlen n'est pas utilisé et doit
aussi valoir NULL.
addrlen est un paramètre-résultat : l'appelant doit
l'initialiser de telle sorte qu'il contienne la taille (en octets) de la
structure pointée par
addr, et est renseigné au retour
par la longueur réelle (en octets) de l'adresse remplie.
L'adresse renvoyée est tronquée si le tampon fourni est trop
petit ; dans ce cas,
addrlen renverra une valeur
supérieure à celle fournie lors de l'appel.
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 ou
EWOULDBLOCK.
Pour être prévenu de l'arrivée d'une connexion sur une
socket, on peut utiliser
select(2),
poll(2) ou
epoll(7).
Un événement « lecture » sera
délivré lorsqu'une tentative de connexion aura lieu, et on
pourra alors appeler
accept() pour obtenir une socket pour cette
connexion. Autrement, on peut configurer la socket pour qu'elle envoie un
signal
SIGIO lorsqu'une activité la concernant se produit,
consultez
socket(7) pour plus de détails.
Si
flags vaut
0 alors
accept4() est identique à
accept(). Les valeurs suivantes peuvent être combinées
dans
flags par un OU binaire pour obtenir un comportement
différent :
- SOCK_NONBLOCK
- Placer l'attribut d'état de fichier
O_NONBLOCK sur la description du fichier ouvert
référencée par le nouveau descripteur de fichier
(consulter open(2)). Utiliser cet attribut économise des
appels supplémentaires à fcntl(2) pour obtenir le
même résultat.
- SOCK_CLOEXEC
- Placer l'attribut
« close-on-exec » ( FD_CLOEXEC) sur le
nouveau descripteur de fichier. Consultez la description de l'attribut
O_CLOEXEC dans open(2) pour savoir pourquoi cela peut
être utile.
S'ils réussissent, ces appels système renvoient un descripteur de
fichier pour la socket acceptée (un entier positif ou nul). En cas
d'erreur, ils renvoient
-1,
errno est positionné pour
indiquer l'erreur et
addrlen est laissé inchangé.
Sous Linux,
accept() (et
accept4()) 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.
-
EAGAIN ou EWOULDBLOCK
- La socket est marquée comme étant non
bloquante et aucune connexion n'est présente pour être
acceptée. POSIX.1-2001 et POSIX.1-2008 permettent de renvoyer l'une
ou l'autre des erreurs dans ce cas et n'exige pas que ces constantes aient
la même valeur. Une application portable devrait donc tester les
deux possibilités.
- EBADF
-
sockfd n'est pas un descripteur de fichier
valable.
- ECONNABORTED
- Une connexion a été abandonnée.
- EFAULT
-
addr n'est pas dans l'espace d'adressage accessible
en écriture.
- EINTR
- L'appel système a été interrompu par
l'arrivée d'un signal avant qu'une connexion valable ne
survienne ; consultez signal(7).
- EINVAL
- La socket n'est pas en attente de connexions, ou
addrlen est non autorisée (par exemple négatif).
- EINVAL
- (accept4()) flags contient une valeur
incorrecte.
- EMFILE
- La limite du nombre de descripteurs de fichiers par
processus a été atteinte.
- ENFILE
- La limite du nombre total de fichiers ouverts pour le
système entier a été atteinte.
-
ENOBUFS, ENOMEM
- Pas assez de mémoire disponible. En
général, cette erreur est due à la taille
limitée du tampon des sockets, et non à la mémoire
système proprement dite.
- ENOTSOCK
- Le descripteur de fichier sockfd ne fait pas
référence à un socket.
- EOPNOTSUPP
- La socket utilisée n'est pas de type
SOCK_STREAM.
- EPERM
- Les règles du pare-feu interdisent la
connexion.
- EPROTO
- Erreur de protocole.
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.
L'appel système
accept4() est disponible depuis
Linux 2.6.28 ; la prise en charge dans la glibc est disponible
depuis la glibc 2.10.
accept() : POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD
(
accept() est apparu dans BSD 4.2).
accept4() est une extension non standard de Linux.
Avec la version Linux de
accept(), la nouvelle socket n'hérite
pas des attributs comme
O_NONBLOCK et
O_ASYNC de la
socket en écoute. Ce comportement est différent de
l'implémentation BSD de référence. Les programmes
portables ne doivent pas s'appuyer sur cette particularité, et doivent
reconfigurer les attributs sur la socket renvoyée par
accept().
Il n'y a pas nécessairement de connexion en attente après la
réception de
SIGIO ou après que
select(2),
poll(2) ou
epoll(7) indiquent quelque chose à lire. En
effet la connexion peut avoir été annulée à cause
d'une erreur de réseau asynchrone ou par un autre thread avant que
accept() ne soit appelé. Si cela se produit, l'appel bloquera en
attendant une autre connexion. Pour s'assurer que
accept() ne bloquera
jamais, la socket
sockfd transmise doit avoir l'attribut
O_NONBLOCK (consultez
socket(7)).
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.
Dans l'implémentation des sockets de BSD originale (et sur d'autres
anciens systèmes), le troisième paramètre de
accept() était déclaré en tant que
int *. Un brouillon du standard POSIX.1g voulait le changer pour
size_t *C ; les derniers standards POSIX et glibc 2.x
mentionnent
socklen_t * .
Consultez
bind(2).
bind(2),
connect(2),
listen(2),
select(2),
socket(2),
socket(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
<
[email protected]>, Thierry Vignaud
<
[email protected]>, François Micaux, Alain Portal
<
[email protected]>, Jean-Philippe Guérard
<
[email protected]>, Jean-Luc Coulon (f5ibh)
<
[email protected]>, Julien Cristau
<
[email protected]>, Thomas Huriaux <
[email protected]>,
Nicolas François <
[email protected]>, Florentin
Duneau <
[email protected]>, Simon Paillard
<
[email protected]>, Denis Barbier
<
[email protected]>, David Prévot <
[email protected]>,
Cédric Boutillier <
[email protected]>,
Frédéric Hantrais <
[email protected]> et Jean-Philippe
MENGUAL <
[email protected]>
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 à
[email protected]