web-dev-qa-db-fra.com

Programmation des sockets - Quelle est la différence entre listen () et accept ()?

J'ai lu ce tutoriel pour en savoir plus sur la programmation des sockets. Il semble que les appels système listen() et accept() fassent la même chose, à savoir bloquer et attendre qu'un client se connecte au socket créé avec la fonction socket() appel système. Pourquoi avez-vous besoin de deux étapes distinctes pour cela? Pourquoi ne pas utiliser un seul appel système?

Soit dit en passant, j'ai googlé cette question et trouvé des questions similaires, mais aucune des réponses n'était satisfaisante. Par exemple, l'un d'eux a dit que accept() crée le socket, ce qui n'a aucun sens, car je sais que le socket est créé par socket().

17
Zen Hacker

La fonction listen() définit fondamentalement un indicateur dans la structure de socket interne marquant le socket comme socket d'écoute passive, celui que vous pouvez appeler accept. Il ouvre le port lié afin que le socket puisse alors commencer à recevoir des connexions des clients.

La fonction accept() demande à un socket d'écoute d'accepter la prochaine connexion entrante et de renvoyer un descripteur de socket pour cette connexion. Donc, dans un sens, accept()does crée un socket, mais pas celui que vous utilisez pour listen() pour les connexions entrantes.

18

Tout cela fait partie de la configuration historique. listen prépare le socket pour le prochain appel accept. L'écoute permet également de configurer le backlog - le nombre de connexions qui seront acceptées par le système, et de mettre en attente jusqu'à ce que votre programme puisse vraiment les accepter. Tout ce qui vient après l'arriéré est bien rejeté par le système. listen ne bloque jamais, tandis que accept bloque (sauf si le socket est en mode non bloquant) jusqu'à ce que la prochaine connexion arrive. De toute évidence, il ne doit pas nécessairement s'agir de deux fonctions distinctes - il est concevable que la fonction accept() puisse faire tout ce que fait listen.

20
SergeyA

Les deux réponses ci-dessus indiquent clairement la différence entre accepter et écouter. Pour répondre à votre autre question - pourquoi avons-nous besoin de deux fonctions distinctes?

Un cas d'utilisation est, par exemple, si vous voulez seulement tester si un port est toujours disponible/accessible, vous pouvez le faire en écoutant simplement le port puis en le fermant sans accepter aucune connexion.

Par exemple https://github.com/coolaj86/golang-test-port utilise l'appel d'écoute pour tester la disponibilité d'un port.

4
J Aamish