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 :

[DNS] "fiabiliser" les échanges en UDP


Sujet :

Réseau C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2010
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2010
    Messages : 21
    Par défaut [DNS] "fiabiliser" les échanges en UDP
    Bonjour tout le monde,



    Pour un projet scolaire, je dois coder un client DNS léger en C, devant permettre une communication avec le serveur DNS autant en UDP qu'en TCP, et implémentant les requêtes inverses...voilà pour le cadre
    Mais on nous demande aussi de gérer la fiabilitié de nous-même en ce qui concerne UDP, c'est-à-dire si je ne me trompe pas, d'utiliser un timeout à la réception et de retransmettre si celui-ci arrive à son terme. A priori, pas besoin de numéros de séquence ou autre de ce genre, puisque dans tous les cas, on envoie une seule requête, et on recevra une seule réponse du serveur.

    Je met donc en place un timeout de 50 millisecondes, et si la première tentatie échoue (timeout), je réessaye 4 fois, c'est-à-dire que 4 fois je refais le cycle envoi_de_la_requête/attente_de_la_réponse, toujours avec le même timeout ; et toutes ces belles petites lignes de code fonctionnent très bien.

    J'ai fait plusieurs tests, et parfois je dois retransmettre une fois ; par ailleurs, une fois qu'une info est en cache du serveur DNS, je n'ai jamais eu un temps d'attente supérieur à 35 ms (entre 15 et 25ms généralement) ; autrement, surtout si c'est une requête inverse, le temps d'attente monte assez rarement au-dessus de 150 ms (j'ai vu juste une fois une pointe à 200 ms et une à 226 ms).

    Cela m'étonne d'ailleurs un peu que je n'aie pour l'instant pas eu à retransmettre plus d'une fois, étant donné les temps d'attente qu'il m'est déja arrivé d'avoir...si quelqu'un a une explication...



    Cependant un problème m'embête, et plusieurs questions me viennent à l'esprit :

    - j'ai utilisé un timeout de 50 ms un peu pour voir comment tout allait se passer, d'ailleurs comme dit plus haut je suis un peu étonné ; mais je pourrais utiliser un timeout plus ou moins variable, dans le genre 150 ms d'attente au premier essai, puis 50 ms pour les 4 retransmissions possibles, puisque l'info demandée est forcément en cache depuis le temps. Qu'en pensez-vous ? De cette manière j'attends suffisamment longtemps si le serveur met du temps à répondre, je ne spammerai pas le serveur inconsidérément ; on pourrait même monter ce timeout initial à 300 ms (jamais vu un temps d'attente supérieur à çà), mais à ce moment c'est l'utilisateur du programme qui le sentira passer si le message s'est perdu. Car le timeout fixe de 50 ms 5 fois est bien du point de vue du programme, mais je spamme le serveur en cas de perte/lenteur. A la limite c'est pas moi que ça concerne, mais bon hein quand même ^^ je suis pas sur que ça soit très....moral.

    - je retransmets 4 fois la requête, surtout pour le cas où il y aurait perte de ma réponse ; faudrait-il plus de retransmissions ? Le but étant quand même que l'utilisateur de mon client DNS n'attende pas des heures, il faut quand même qu'a un moment je lui dise "tant pis pas de bol, le réseau veut pas te donner ta réponse", il réessayera plus tard. Tout le problème est dans l'ajustement du nombre de retransmissions, et le temps de timeout...

    - enfin, je sais que le serveur met en cache les réponses, qu'il en ait trouvé une ou que sa réponse soit "domain name doesn't exist", d'après la RFC en tout cas. Par contre ce que je n'ai pas trouvé, c'est la façon dont le serveur réagit si une défaillance interne a lieu ; est-ce qu'il retourne immédiatement une réponse (avec donc un temps de réponse bien sous la barre des 50 ms), ou bien est-ce qu-il met 10 plombes à se rendre compte qu'il est en panne, et dans ce cas des timeout de 50 ms ne suffiront jamais à savoir que le serveur s'est planté ?



    Voila, donc déja félicitations et merci pour être arrivé au bout du pavé ^^ je sais que c'est assez précis comme questions, mais je n'ai trouvé les réponses ni dans la RFC 1035, ni avec Google.
    Je pourrais si vous le demandez poster du code, mais il me semble que la question est plus...philosophique qu'autre chose



    Merci d'avance à ceux qui prendront la peine de m'aider !

  2. #2
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 129
    Billets dans le blog
    149
    Par défaut
    Bonjour,

    Pour la partie client DNS je ne peux pas vraiment dire ... car j'ai jamais lu la spec pour les DNS. (Surtout pour l'histoire du cache que je n'ai presque rien compris )

    Maintenant, sur l'UDP, il faut savoir que le numero de paquet peut être utile si vous envoyer deux messages, que le premier perdu, mais le deuxième reçu. Il semble que vous n'ayez qu'un message ... mais que se passe t'il, si le premier message est envoyé, le rappel aussi , le rappel reçu avec le premier message, puis le premier message ?

    Sachant la vitesse des réseaux, je dirai qu'un timeout devrait mettre 300ms à 1 seconde ... car normalement, en jeu vidéo, le ping est de 150 / 200 dans de mauvaises condition. Donc, on peut déclaré un paquet perdu, qu'après une attente supérieur à ces vitesses "habituelles".
    Après, oui ... cela est long pour l'utilisateur, mais bon ... s'il a perdu la connexion, une attente de 5 * 50 ms (qui n'est peut être pas assez fiable, pour dire que la connexion est perdu.)

    Après, je ne sais plus ce que je voulais dire d'autre
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  3. #3
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2010
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2010
    Messages : 21
    Par défaut
    Merci de vous pencher sur mon problème ^^

    En ce qui concerne le cache, lorsqu'un client demande au serveur de résoudre un nom de domaine en addresse IP, il lui demande en fait un enregistrement de ressource, du genre "mon_nom_de_domaine adresse_ip_correspondante".
    Le serveur va donc envoyer cette réponse au client, mais en parallèle, il va aussi le stoker dans sa mémoire cache, ce qui peut en fait être utile pour répondre à de futures demandes de clients ; même chose s'il ne trouve pas d'adresse IP correspondante, apparemment il stocke aussi cette information.

    Cela accélère grandement le temps de traitement de la requête, comme le prouvent les chiffres donnés plus haut :
    pas en cache : 50-150 ms, max 226 ms
    en cache : 15-25 ms, max 35 ms

    Sinon, comme vous l'aviez deviné, je n'envoie à chaque fois qu'un seul message UDP, de même je n'en recevrai qu'un seul du serveur. Par contre je n'ai pas compris le coup du "rappel". Est-ce l'acquittement ? Parce que dans ce cas, il n'y en a pas ici (ou alors la RFC m'aurait menti argh).

    Concernant le timeout, 300 ms à 1 seconde ??? Naooooooooon...l'utilisateur (et le prof surtout) va pleurer c'est pas possible. Vu qu'en fait le timeout est surtout là pour empêcher le recvfrom() de bloquer indéfiniment en cas de perte. Bon à la limite, 150 ou 200 ms j'aurai pas été contre, mais je pensais plutôt que peu importe si la réponse à ma première requête n'arrive pas dans les délais du premier timeout, elle serait arrivée plus tard, et je la lirais au "tour" d'après. Vu que j'ai 5 tentatives, avec disons un timeout fixe de 100 ms, la réponse à la 1ère requête aurait 500 ms maximum pour arriver, la réponse à la requête du 2ème tour aurait 400 ms, etc...et en cas de perte, justement je retransmet à chaque fois donc ça me semblait bon.

    J'aurai vraiment voulu que l'utilisateur n'attende pas plus d'une demi-seconde voire d'une seconde en fait mais s'il n'y pas moyen de faire autrement, tant pis. En tout cas merci de m'aider !

  4. #4
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 129
    Billets dans le blog
    149
    Par défaut
    Citation Envoyé par Elindur Voir le message
    Sinon, comme vous l'aviez deviné, je n'envoie à chaque fois qu'un seul message UDP, de même je n'en recevrai qu'un seul du serveur. Par contre je n'ai pas compris le coup du "rappel". Est-ce l'acquittement ? Parce que dans ce cas, il n'y en a pas ici (ou alors la RFC m'aurait menti argh).
    Euh ... je ne fait pas le lien avec ma reponse ...

    Citation Envoyé par Elindur Voir le message
    Concernant le timeout, 300 ms à 1 seconde ??? Naooooooooon...l'utilisateur (et le prof surtout) va pleurer c'est pas possible. Vu qu'en fait le timeout est surtout là pour empêcher le recvfrom() de bloquer indéfiniment en cas de perte. Bon à la limite, 150 ou 200 ms j'aurai pas été contre, mais je pensais plutôt que peu importe si la réponse à ma première requête n'arrive pas dans les délais du premier timeout, elle serait arrivée plus tard, et je la lirais au "tour" d'après. Vu que j'ai 5 tentatives, avec disons un timeout fixe de 100 ms, la réponse à la 1ère requête aurait 500 ms maximum pour arriver, la réponse à la requête du 2ème tour aurait 400 ms, etc...et en cas de perte, justement je retransmet à chaque fois donc ça me semblait bon.

    J'aurai vraiment voulu que l'utilisateur n'attende pas plus d'une demi-seconde voire d'une seconde en fait mais s'il n'y pas moyen de faire autrement, tant pis. En tout cas merci de m'aider !
    Pour ne pas faire attendre l'utilisateur, on utilise un thread, pour que le reseau ne bloque pas l'application ...
    Deuxiemement... vous dites que c'est long, parce qu'il semble que les utilisateurs ont oublie du temps du 56k. Sachant que chez moi, j'ai encore du 28k ... Donc oui l'utilisateur attend ... mais si on attend pas ... on va croire qu'il y a eu un echec de connexion, alors que c'etait juste une lenteur du reseaux. De plus, ci cette utilisateur lance un programme qui bouffe tout le reseau ... vous n'allez plus pouvoir connecter votre programme, car vous n'attendez pas assez lontemps.

    Enfin la, est mon point de vue
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  5. #5
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2008
    Messages
    1 515
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 515
    Par défaut
    Citation Envoyé par Elindur Voir le message
    Sinon, comme vous l'aviez deviné, je n'envoie à chaque fois qu'un seul message UDP, de même je n'en recevrai qu'un seul du serveur.
    Le cas qui peut poser problème est celui où le client envoie un premier paquet et ne reçoit pas de réponse avant le timeout. Là le client envoie un deuxième paquet, mais le premier paquet fini quand même par arriver. Donc le client aura envoyé deux paquets, et recevra deux paquets.

    D'un autre côté il me semblait que dans le protocole UDP il y a un numéro qui permet d'appairer une réponse et une requête. Si c'est bien le cas il n'y a effectivement pas de confusion possible.

    Pour les histoire de timeout, je crois que tu ne regardes pas le problème du bon côté. Le timeout ne servira que s'il y a des problèmes réseau. Tu peux mettre un timeout de 1 seconde, ou 10 secondes, ça ne changera rien si le réseau fonctionne correctement. Par contre, ce qu'il faut éviter, c'est qu'un timeout trop court vienne gêner le déroulement optimal de l'échange sur un réseau "pas très bon mais fonctionnel". Si tu met un timeout trop court, tu risque d'ignorer des réponses qui viendraient "juste un peu trop tard", et du coup prendre un pénalité supplémentaire que tu aurais pu éviter en n'envoyant pas tout de suite une deuxième requête.

  6. #6
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2010
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2010
    Messages : 21
    Par défaut
    @LittleWhite

    Citation Envoyé par LittleWhite Voir le message
    Il semble que vous n'ayez qu'un message ... mais que se passe t'il, si le premier message est envoyé, le rappel aussi , le rappel reçu avec le premier message, puis le premier message ?
    C'est de ce "rappel" que je parle, désolé je ne comprend pas.

    Citation Envoyé par LittleWhite Voir le message
    Deuxiemement... vous dites que c'est long, parce qu'il semble que les utilisateurs ont oublie du temps du 56k. Sachant que chez moi, j'ai encore du 28k ... Donc oui l'utilisateur attend ... mais si on attend pas ... on va croire qu'il y a eu un echec de connexion, alors que c'etait juste une lenteur du reseaux. De plus, ci cette utilisateur lance un programme qui bouffe tout le reseau ... vous n'allez plus pouvoir connecter votre programme, car vous n'attendez pas assez lontemps.
    Effectivement, je n'avais pas pensé au fait que l'utilisateur pourrait "surcharger" le réseau (surtout avec du 28k... bravo, ça c'est du courage). Damned ! Et comme vous dites, si c'est le cas il faut que j'augmente mes timeout



    @matafan

    Citation Envoyé par matafan Voir le message
    D'un autre côté il me semblait que dans le protocole UDP il y a un numéro qui permet d'appairer une réponse et une requête. Si c'est bien le cas il n'y a effectivement pas de confusion possible.
    En fait on envoie en UDP une requete DNS qui contient elle-même un ID, et j'y met le numéro du processus. Mais en réalité ce n'est pas utile de distinguer les réponses ; mettons qu'on soit dans le cas suivant :

    Citation Envoyé par matafan Voir le message
    Le cas qui peut poser problème est celui où le client envoie un premier paquet et ne reçoit pas de réponse avant le timeout. Là le client envoie un deuxième paquet, mais le premier paquet fini quand même par arriver. Donc le client aura envoyé deux paquets, et recevra deux paquets.
    Puisque je réenvoie ma requête (qui reste donc identique), le serveur doit réenvoyer la réponse, qui doit être la même (à moins qu'entre temps il y ait une mise à jour interne des correspondances ip ---> nom de domaine, mais bon ;-). Donc peu importe si je lis sa 1ère ou sa 2ème réponse finalement.

    Citation Envoyé par matafan Voir le message
    Pour les histoire de timeout, je crois que tu ne regardes pas le problème du bon côté. Le timeout ne servira que s'il y a des problèmes réseau. Tu peux mettre un timeout de 1 seconde, ou 10 secondes, ça ne changera rien si le réseau fonctionne correctement. Par contre, ce qu'il faut éviter, c'est qu'un timeout trop court vienne gêner le déroulement optimal de l'échange sur un réseau "pas très bon mais fonctionnel". Si tu met un timeout trop court, tu risque d'ignorer des réponses qui viendraient "juste un peu trop tard", et du coup prendre un pénalité supplémentaire que tu aurais pu éviter en n'envoyant pas tout de suite une deuxième requête.
    Oula, tu as tout à fait raison. Je voyais ça comme soit un bon réseau rapide et tout et tout, soit un truc super lent/surchargé qui ne permet pas que les messages arrivent... mais je n'avais pas envisagé la situation intermédiaire.



    Du coup voila comment je pense faire : j'utilise un premier timeout de 500ms, c'est dans l'intervalle 300ms/1s de LittleWhite, et ça laisse laaaargement le temps au serveur de traiter la requête et d'envoyer la réponse sur un réseau pas trop chargé. Si j'ai rien en retour, on peut admettre que soit la réponse est perdue (réseau surchargé), soit le réseau est vraiment trop lent (et la réponse est peut-être toujours en route), soit les deux, mais en réalité on ne peut pas savoir.
    Ce qui fait que pour le premier cas je dois retransmettre, et pour le 2ème cas je dois augmenter le timeout, ou continuer à attendre ; mais bon, vu que à chaque nouvelle tentative je retransmet ma requête, et que je recommence à attendre un temps donné, finalement ça couvre les 2 cas. Il faut juste que j'augmente mon timeout.

    Donc au final, 3 tentatives : la première avec un timeout de 500ms, la 2ème avec un timeout de 1s, et la 3ème avec un timeout de 2 ou 3s (comme ça si ça ne marche pas je pourrais dire à l'utilisateur de changer de FAI ou d'aller habiter en ville).
    Quel est votre avis ?

    Là j'ai l'impression que ça couvre bien les différents cas possibles, et si rien n'est recu, on peut vraiment dire à l'utilisateur que le réseau est en faute (alors qu'avant, avec maximum 250ms d'attente, je n'aurai pas pu).

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