| accept | |||
Nomaccept - 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); Descriptionaccept 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éeaccept 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
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. ExempleUn 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.NoteLe 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 Aussibind(2) , connect(2) , listen(2) , select(2) , socket(2)
TraductionChristophe Blaess, 1997.
|