accept() - C - Programmation
Marsh Posté le 01-12-2004 à 21:44:35
yartempion a écrit : Bonjour, |
http://msdn.microsoft.com/library/ [...] cept_2.asp
Si j'ai bien compris (c'est très frais...) accept() est appelée sur un serveur (socket placé en écoute (listen) par un appel à listen() , et crée un socket 'client' lorsqu'un client se connecte (TCP). Le socket 'original', (celui du serveur) n'est pas détruit ni remplacé.
Mais je me pose aussi des questions. Si le client se déconnecte ... je suppose que la fermeture du socket est automatique... Est-on prévenu ? Mystère...
D'autres avis éclairés sont les bienvenus.
Marsh Posté le 02-12-2004 à 03:33:29
listen() met une socket en écoute de connexion
accept() acceptte une connection et retourne la socket utilisée pour dialoguer avec le client...
donc ça fait:
SOCKET slisten=socket()
...
bind( slisten, addr machin qui définit le port d'écoute etc etc)
...
listen( slisten ) mets la socket en écoute (pour des connexion)
....
SOCKET sClient;
while/for
sClient=accept(sListen ... ) pour accepter les connexions
-> par exemple création de thread qui dialoguer avec le client connecté via sClient.
si le client se déconnecte les opérations sur sClient retourneront un code d'erreur....
Marsh Posté le 02-12-2004 à 11:24:23
Pour être prévenu en temps réel de la déconexion du client, voir les sockets asynchrones je pense, auquel cas tu reçois FD_CLOSE.
Y'a aussi la possibilité de créer une socket KEEPALIVE :
setsockopt( SO_KEEPALIVE ).
ça permet de détecter les fermetures anormales.
cf la FAQ
http://tangentsoft.net/wskfaq/
Marsh Posté le 06-12-2004 à 13:16:32
HelloWorld a écrit : Pour être prévenu en temps réel de la déconexion du client, voir les sockets asynchrones je pense, auquel cas tu reçois FD_CLOSE. |
J'ai compris qu'une socket est cree mais le client qui s'est connecte au depart l'a fait avec un N° de port specifique une fois que le serveur a fait appel a accept() visiblement une nouvelle socket est cree cote serveur pour continuer le dialogue mais avec un nouveau N° de port, le client devrai utiliser ce nouveau N° de port pour continuer a communiquer. Faut il indiquer au client ce nouveau port ou est ce le noyaeu qui se charge de faire la correspondance entre la socket source et la nouvelle socket de communiation cote serveur?
Marsh Posté le 06-12-2004 à 13:40:51
Le client doit connaitre le numéro de port du service qu'il demande.
Marsh Posté le 06-12-2004 à 14:52:49
HelloWorld a écrit : Le client doit connaitre le numéro de port du service qu'il demande. |
Oui en effet amis je croyais que le N° de port changeait apres l'appel de accept().La nouvelle socket a les memes caracteristiques que l'ancienne c'est le N° de socket qui change. Je pense que c'est le noyeau qui s'occupe d'effectuer la translation des donnees reçues du correspondant distant sur la nouvelle socket.
Marsh Posté le 06-12-2004 à 14:53:37
Oui en effet mais je croyais que le N° de port changeait apres l'appel de accept().La nouvelle socket a les memes caracteristiques que l'ancienne c'est le N° de socket qui change. Je pense que c'est le noyeau qui s'occupe d'effectuer la translation des donnees reçues du correspondant distant sur la nouvelle socket.
Marsh Posté le 06-12-2004 à 15:03:11
Tu peux considérer que la nouvelle socket que te renvoie accept (elle change pas, c'est une nouvelle) est celle du côté client. Pour communiquer il faut 2 bouts, le premier est celui de ton serveur, sur lequel tu fais le accept. L'autre bout est créé a chaque connexion, c'est celui du client fraichement connecté. C'est ce que te renvoie accept.
Marsh Posté le 06-12-2004 à 16:01:10
Non, tu ne peux pas considerer que accept() renvoit la socket cote client. Pour chaque connexion il y a deux sockets, une cote serveur et une cote client. accept() cree simplement une nouvelle socket cote serveur, binde sur le meme port que la socket initiale. yartempion a raison quand il parle de "translation des donnees". Les connexions sont "multiplexees" par le kernel.
D'ailleurs sur un serveur netstat montre bien qu'il y plusieurs sockets bindees sur un meme port.
Marsh Posté le 06-12-2004 à 17:03:56
En me relisant en effet je me suis vautré dans ma comparaison. J'avais en tête l'image du tuyau qui relie les 2 protagonistes, le accept connectant en quelque sorte le tuyau sur le client, on pouvait considérer la socket comme branchée du coté du client. Bon c'était nul désolé.
Marsh Posté le 06-12-2004 à 17:14:48
Il ne faut pas confondre les numéros de port tcpip côté client et serveur. En résumé (mes connaissances ne me permettant pas d'aller beaucoup plus loin !) :
- le serveur se met en attente sur un N° de port (par exemple disons le N° 12345)
- le client demande une connexion sur le même N° de port (ex: 12345)
- à la connexion, le serveur créé un socket et lui donne en interne un N° de port "virtuel" (ex: 9876). Ce numéro interne ne concerne pas le client. Pour le client seul existe le N° de port demandé pour le service (12345).
- le serveur, qui reste en ecoute, peut accepter une autre connexion simultanée sur le même port. Si un autre client se connecte il va créer un nouveau socket avec un N° interne différent (disons le 9877). ...etc. Ces différents numéros de port internes permettent au serveur de différencier les N clients connectés.
Est-ce plus clair pour les numéros de port ? (j'ai pas dit trop d'âneries ?)
Marsh Posté le 06-12-2004 à 17:26:38
T'es sûr de ton coup pour les numéros ports internes ? Il me semblait que le multiplexage utilisait l'IP source pour s'y retrouver.
Marsh Posté le 06-12-2004 à 17:33:34
Bon d'accord, mais une fois connecte le client ne connais que le port 12345 auquel il s'est connecte alors que le serveur lui a affecte un nouveau port 9876 pour le tarnsfert des donnees. Cote client il continue a envoyer des donnees toujours sur le port 12345 alors que le serveur les attends sur le 9876. Comment ca se passse? Est ce le noyeau qui fait la correspondance ou y a t'il un autre mecanisme?
Marsh Posté le 06-12-2004 à 17:40:58
HelloWorld a raison. Par exemple, dans le cas d'un client et d'un serveur web :
1) Quand le serveur http est lance sur le serveur, une socket et cree sur le serveur. Elle est bindee au port 80, et elle est a l'etat LISTEN.
2) Quand le client decide de se connecter, une socket est cree sur le client. Elle est bindee sur le client a un port choisi de maniere aleatoirement (mettons 12345). Elle se connecte au port 80 du serveur.
3) Le serveur accept() la connexion, et le "handshake" tcp est echange. Une nouvelle socket est cree sur le serveur. Cette socket est elle aussi bindee au port 80. La connexion est maintenant etablie entre le port 12345 du client et le port 80 du serveur, sur cette nouvelle socket qui est a l'etat ESTABLISHED. La socket qui ecoutait initialement sur le port 80 sur serveur ecoute toujours sur le port 80 du serveur, mais elle ne fait pas partie de la connexion. Elle est toujours a l'etat LISTEN.
4) Le client envoie des donnees sur sa socket. Les donnees sont envoyees au serveur sur le port 80. Evidemment il y a maintenant plusieurs socket attachees au port 80 sur le serveur... Mais une seule pour cette connexion : la nouvelle socket cree par accept().
Ce mecanisme permet a plusieurs clients de dialoger avec une meme machine sur un meme port. Les packets venant des differents clients sont tous emis vers la meme adresse (le serveur) et vers le meme port (80), mais les packets venus de clients differents ont des adresses source differentes et appartiennents a des connexions differentes, lies a des sockets differentes sur le serveur, toutes bindees au port 80.
Marsh Posté le 06-12-2004 à 17:56:05
http://www.google.com/search?&q=li [...] read+close
http://www.urec.cnrs.fr/cours/Applis/netprog.pdf
http://www-inst.eecs.berkeley.edu/ [...] ockets.pdf (pas mal à partir de la page 10). Qui de mieux que Berkeley pour expliquer les sockets ?
Marsh Posté le 06-12-2004 à 17:57:59
C'est ces sockets ESTABLISHED spécifiques au dialogue avec un client que j'ai maladroitement appelée "côté client".
Marsh Posté le 29-11-2004 à 06:17:06
Bonjour,
Je cherche a comprendre un peut mieux la fonction acepte().
Au moment ou on l'invoque visiblement elle recree une socket avec un nouveau N° de port afin de liberer la socket originale pour de nouvelles connections cote serveur. Mais cote client comment ca se passe? Quand on invoque connect() on fournit un N° de port, si celui ci change apres la connection comment fait le client pour continuer a rester en relation puisque il doit avoir le nouveau N° de port?