IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Réseau C Discussion :

De la magie de connect() et accept()


Sujet :

Réseau C

  1. #1
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut De la magie de connect() et accept()
    Hey !

    Je suis en train de travailler avec des sockets TCP mais non BSD, fourni par Keil pour son compilateur sur ARM. Ils font partis de la bibliothèque TcpNet.

    Je n'ai à ma disposition que ces fonctions et je n'ai notamment pas de fonction accept(). Quand je crée un socket, je lui passe un callback et ce callback est appelé chaque fois qu'il y a un "évènement", en particulier quand il y a une question entrante sur un socket à l'écoute. Si j'accepte cette connexion, le socket à l'écoute devient le socket de communication avec le client et n'est donc plus à l'écoute.

    Je dois utiliser ces fonctions pour implémenter des fonctions d'une API d'une surcouche, qui elle se base plutôt sur des sockets type BSD (que je ne peux pas utiliser pour des raisons techniques propres au projet).

    Je cherche donc à comprendre comment fonctionnent les fonctions connect() et accept() des sockets BSD. connect() se connecte à un serveur et est bloquante tant que le serveur ne répond pas (ou timeout). accept() accepte une connexion en attente ou en attend une nouvelle.

    Mettons qu'on ait :
    • un serveur possède un socket à l'écoute mais n'appelle pas accept()
    • un client utilise connect()

    J'ai lu sur le net que le serveur pouvait accepter la connexion entrante sans pour autant qu'il y ait forcément eu un appel à accept(). Est-ce vrai ? Si la réponse est non, cela veut dire qu'on ne peut pas envoyer de données au serveur tant que celui-ci ne nous a pas connecté à un socket dédié. Si la réponse est oui, on pourrait donc envoyer des données au serveur avant son appel à accept() mais ça me parait un peu bizarre... Les données n'iraient nul part ? Comment ces 2 fonctions s'articulent t-elles ? L'une attend-elle l'autre pour se débloquer ?

    Merci d'avance pour vos réponses !

  2. #2
    Membre expérimenté

    Homme Profil pro
    Collégien
    Inscrit en
    Juillet 2010
    Messages
    545
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Afghanistan

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Juillet 2010
    Messages : 545
    Points : 1 429
    Points
    1 429
    Par défaut
    Salut,

    Je pense que dans ton cas les notions standards de connect, accept, etc sur les serveur sont difficilement applicables.

    Voir exemple :http://www.keil.com/support/man/docs...cp_mulconn.htm

  3. #3
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    C'est justement mon problème !

    Je dois interfacer deux APIs : celle du dessus se cale sur un modèle BSD, celle du dessous non.

    J'ai forcément étudié dans la journée la page que tu donnes, mais le problème est qu'on a là un pool de sockets qui sont en attentes et qui prennent les connexions au fur et à mesure qu'elles arrivent. On perd la notion de socket d'écoute passant la main à des sockets dédiés à l'échange de données en mode connecté. Et j'en ai besoin

  4. #4
    Invité
    Invité(e)
    Par défaut
    Salut,

    J'ai lu sur le net que le serveur pouvait accepter la connexion entrante sans pour autant qu'il y ait forcément eu un appel à accept(). Est-ce vrai ?
    Ca n'a pas vraiment de sens d'un "point de vue TCP".

    Parce qu'une connexion TCP entrante ne peut être acceptée que si la phase de TCP Handshake s'est déroulée avec succès. Dans le monde BSD, ce sont les fonctions connect() côté client et accept() côté serveur qui déclenchent et gèrent le handshake. Sans ça, impossible de transmettre la moindre donnée, toute tentative d'appel d'un write() côté client génèrera une erreur.

    Bon, pas sûr que ça résolve ton problème mais c'est ainsi que TCP fonctionne...

    On perd la notion de socket d'écoute passant la main à des sockets dédiés à l'échange de données en mode connecté
    Je crains que tu n'aies pas le choix... C'est toujours le même dilemme : simplicité versus performance...

    Steph

  5. #5
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Dans le monde BSD, ce sont les fonctions connect() côté client et accept() côté serveur qui déclenchent et gèrent le handshake.
    C'est ce que des collègues plus expérimentés que moi en réseau m'ont expliqué ^^ Je me pose quand même toujours la question de manière dont des connections en attente peuvent être mise en file d'attente et qu'accept() dépile quand elle est appelée (ou se bloque si cette queue est vide)...

    Je crains que tu n'aies pas le choix... C'est toujours le même dilemme : simplicité versus performance...
    Du coup, je recode un mécanisme pour simuler un accept() mais de manière non bloquante, avec des évènements. Pas simple, je suis à fond dans mes diagrammes de séquences et autres organigrammes !!

  6. #6
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Bktero Voir le message
    Je me pose quand même toujours la question de manière dont des connections en attente peuvent être mise en file d'attente et qu'accept() dépile quand elle est appelée (ou se bloque si cette queue est vide)...
    C'est la beauté du listening mode (et ça n'est pas spécifique à TCP/IP)

    Citation Envoyé par Bktero Voir le message
    Du coup, je recode un mécanisme pour simuler un accept() mais de manière non bloquante, avec des évènements. Pas simple, je suis à fond dans mes diagrammes de séquences et autres organigrammes !!
    Tu vas peut-être créer un nouveau protocole qui va porter ton nom

    Steph

  7. #7
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par IP_Steph Voir le message
    C'est la beauté du listening mode (et ça n'est pas spécifique à TCP/IP)
    Ça ne répond pas vraiment à ma question (mais ça colle bien au titre du thread)

    Citation Envoyé par IP_Steph Voir le message
    Tu vas peut-être créer un nouveau protocole qui va porter ton nom
    Trop de la balle ! Je retourne bosser ! Euh.... non, je vais dormir plutôt ^^

  8. #8
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Bktero Voir le message
    Je me pose quand même toujours la question de manière dont des connections en attente peuvent être mise en file d'attente et qu'accept() dépile quand elle est appelée (ou se bloque si cette queue est vide)...
    Parce que listen() crée justement des files (c'est le 2ème argument de la fonction, le backlog) qui sont en dehors de l'espace de l'application, les TCP listen queues.

    Pour être plus précis, à chaque fois qu'un port TCP est basculé en listening mode, le kernel crée 2 files d'attente : la completed et l' incomplete connection queues. La valeur backlog de listen() désigne la somme maximale de ces 2 files d'attente.

    Lorsque le serveur reçoit le 1er SYN lors du TCP Handshake, le kernel crée une entrée dans l' incomplete queue (correspondant à une socket dans l'état SYN_RCVD). Puis accept() déclenche le SYN-ACK vers le client. Et lorsque le serveur reçoit l'ACK du client qui termine donc le Handshake, le kernel déplace cette entrée de l' incomplete vers la complete queue (la socket est alors dans l'état ESTABLISHED).

    Steph

  9. #9
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Il est malin le noyau Linux ! Le mécanisme d'attente est donc fourni par lui et sa stack... Je me disais bien que c'était une histoire de mémorisé qui avait envoyé un SYN et de répondre seulement lors du accept().

    Que ce passe t-il si les SYN sont trop vieux et que le client distant est déjà tombé en timeout ? accept() essaye de communiquer avec lui, le noyau lui signale que ça ne marche pas et accept() passe à l'item suivant de la file jusqu'à la vider ou trouver un client qui renverra un ACK ?

  10. #10
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Bktero Voir le message
    Que ce passe t-il si les SYN sont trop vieux et que le client distant est déjà tombé en timeout ?
    Lorsque le client envoie son SYN, il arme un timer. S'il ne reçoit pas de SYN/ACK de la part du serveur durant ce laps de temps, il réessaie. Après plusieurs tentatives (ça dépend des implémentations), s'il n'y a toujours pas de SYN/ACK de la part du serveur, le client abandonnera la tentative de connexion.

    Lorsque le serveur reçoit le SYN du client, listen() déclenche le Handshake en produisant l'envoi du SYN/ACK de la part du serveur et en armant également un timer. Si durant de laps de temps, le serveur n'a toujours pas reçu l'ACK du client, il va réémettre le SYN/ACK un certain nombre de fois (en réarmant son timer à chaque fois) et normalement le serveur mettra fin à cette tentative de connexion en émettant un RST/FIN.


    Citation Envoyé par Bktero Voir le message
    ou trouver un client qui renverra un ACK ?
    Non, lorsque accept() reçoit le premier SYN du client, le kernel crée un Connection ID spécifique à ce client (IP addresse et port source TCP). Si le Handshake sur cette connexion ne se produit pas, l' incomplete queue est vidée de cette entrée, et le process traite le SYN suivant, s'il y en a un, ou se remet en sleep en attendant une tentative de nouvelle connexion.

    Steph

  11. #11
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Lorsque le serveur reçoit le SYN du client, listen() déclenche le Handshake en produisant l'envoi du SYN/ACK
    accept() plutôt, non ?


    ou trouver un client qui renverra un ACK ?
    Non
    Ce n'est pas ce que tu décris ? accept() prend le premier client dans l'incomplete queue, lui envoie des SYN+ACK et attend un ACK. S'il n'en reçoit pas, il passe au client suivant ; sinon, la connexion est établie. C'est ce que j'entendais par "trouver un client qui renverra un ACK".

  12. #12
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Bktero Voir le message

    Lorsque le serveur reçoit le SYN du client, listen() déclenche le Handshake en produisant l'envoi du SYN/ACK
    accept() plutôt, non ?
    Oui, évidemment, il fallait lire accept()...


    Citation Envoyé par Bktero Voir le message
    C'est ce que j'entendais par "trouver un client qui renverra un ACK".
    Ah OK... On est en phase alors

    Steph

  13. #13
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Merci beaucoup pour ces explications

Discussions similaires

  1. Réseau - Problème d'acceptation connection entrante
    Par superolive dans le forum VB.NET
    Réponses: 1
    Dernier message: 08/06/2008, 14h18
  2. Réponses: 0
    Dernier message: 08/03/2008, 20h13
  3. Pb accept connection
    Par doommick31 dans le forum MFC
    Réponses: 5
    Dernier message: 16/05/2007, 23h57
  4. Réponses: 2
    Dernier message: 07/11/2006, 09h15
  5. connect sans accept
    Par gui31 dans le forum Réseau
    Réponses: 3
    Dernier message: 14/09/2005, 10h44

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo