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 ?