Fiabilisation des échanges en UDP

Cours 03

UDP n'est pas fiable

  • un paquet peut être perdu dans le réseau IP
  • l'ordre des paquets peut être modifié dans le réseau IP
  • Mise en évidence / reproductibilité ?

  • Avec un serveur distant, contrôle difficile.
  • En local, quasiment aucune perte.
  • Nous allons utiliser un proxy (relais) pour introduire artificiellement de l'instabilité dans le réseau :

  • il s'intercale entre le client et le serveur ;
  • il relaie les requêtes du client vers le serveur ;
  • il relaie les réponses du serveur vers le client ;
  • il peut interférer dans les échanges.
  • Proxy (1/12)

    Proxy (2/12)

    Proxy (3/12)

    Proxy (4/12)

    Proxy (5/12)

    Proxy (6/12)

    Proxy (7/12)

    Proxy (8/12)

    Proxy (9/12)

    Proxy (10/12)

    Proxy (11/12)

    Proxy (12/12)

    Fiabilisation

    Que peut faire un client qui n'a pas reçu de réponse ?

  • Est-ce que sa requête s'est perdue ?
  • Est-ce que sa réponse s'est perdue ?
  • Est-ce qu'un paquet est retardé ?
  • Seul mécanisme possible : renvoyer la requête au bout d'un certain temps.

  • Combien de temps attendre avant renvoi ?
  • Pourquoi ne pas compter sur un renvoi du serveur ?
  • Client UDP en Java

    La réception par la méthode datagramChannel.receive() est bloquante par défaut.

    Si on est bloqué en attente, on ne peut pas renvoyer la requête...

    Il faut donc deux threads concurrents :

  • un thread d'envoi et
  • un thread de réception.
  • Attention aux règles à respecter en programmation concurrente !

    Producteur / consommateur

  • File d'attente protégée, commune aux deux (types de) threads ;
  • Consommateur mis en attente si rien à consommer dans la file ;
  • Producteur mis en attente si pas de place dans la file.
  • Ça évite l'attente active et limite la quantité de données stockées.

  • Producteur = listener qui insère dans la file d'attente les paquets reçus depuis le réseau.
  • Consommateur = sender (main) qui extrait de la file d'attente les réponses des requêtes qu'il a envoyées.
  • On a la possibilité de borner l'attente du consommateur.

    BlockingQueue

    Throws exception Special value Blocks Times out
    Insert add(e) offer(e) put(e) offer(e, time, unit)
    Remove remove() poll() take() poll(time,unit)
    Examine element() peek() not applicable not applicable

    Attente bornée de réponse avant ré-envoi

    Points de vigilance

    • Quelle implémentation de BlockingQueue ?
      • ArrayBlockingQueue ? LinkedBlockingQueue ?
      • Taille (maximale) ?
    • Zone(s) de stockage des données = mémoire partagée...
      • Via la référence transmise par la BlockingQueue, les deux threads accèdent à une même zone de données...
      • Attention à ce que l'un n'écrive pas pendant que l'autre lit (problèmes de data-race).
    • Deux threads, un seul DatagramChannel :
      • Qui arrête qui ?
      • Qui ferme quoi ?