Vous êtes sur la page 1sur 4

Université Paris 7

M2 II
Protocole Internet

TP1

Document à rendre: Vous devez rendre pour le 25 novembre au secrétariat


de l’UFR:
1. Le code java de la question 2 de l’exercice 1 accompagné d’un cours rapport
(environ 1 page).
2. Le code java des questions 6 et 7 de l’exercice 2, accompagné d’un cours
rapport (environ 3 pages) présentant plus particulièrement la description
du protocole de la question 7 et la manière dont vous avez testé votre
application (question 7.2).

Exercice 1: Application client/serveur

On veut créer une application client/serveur qui permet de savoir si une machine
est active. Cette application utilise des sockets TCP.
1. • Le serveur attend une requête du client sur le port 1027 et lui envoie
un message (par exemple contenant l’heure locale). Le serveur doit
donc être capable de gérer plusieurs clients simultanément.
• Le client lit une adresse au clavier et envoie une requête au serveur
de la machine correspondante pour savoir si elle est active. Dans
l’affirmative, il affiche le message envoyé par le serveur.

2. Modifier l’application précédente pour que


• Le serveur attend une requête du client sur le port 1027 puis envoie
un message régulièrement. L’arrêt de la communication se fait à
l’initiative du client.
• Le client lit une adresse au clavier et envoie une requête au serveur
de la machine correspondante pour savoir si elle est active. Dans
l’affirmative, il affiche les messages envoyés par le serveur jusqu’à ce
que l’utilisateur demande d’arrêter.

1
Exercice 2: Application Pair-à-Pair

L’objectif de cet exercice est de réaliser une application distribuée pair-à-pair en


utilisant les sockets UDP en mode diffusion (i.e. permettant l’envoi d’un message
à toutes les machines connectées au réseau en une seule opération d’envoi).
On veut réaliser une application de discussion multipoint ("chat"). Votre
programme devra envoyer sur les machines participantes de la salle toutes les
lignes lues sur l’entrée standard et afficher sur la sortie standard tous les mes-
sages reçus.
On utilise ici la classe MulticastSocket (java.net.MulticastSocket) qui permet
des communications de groupe. Elle permet d’envoyer et de recevoir des paquets
sur l’internet. Un groupe de multicast est identifié par une adresse IP de classe
D et par un port UDP classique. Les adresses de classes D vont de 224.0.0.0 à
239.255.255.255. L’adresse 224.0.0.0 est réservée et ne doit pas être utilisée.
1. Création
Écrire une classe Com pour l’envoi et la réception de paquets de la dis-
cussion. Votre classe contiendra les champs :
int port ; // Le port d’écoute du socket
InetAddress multicastAddress ; // L’adresse IP utilisée pour la commu-
nication de groupe.
MulticastSocket socket ; // Le socket identifié par son port
Dans la phase de test vous choisirez le port 66i et l’adresse multicast
230.1.1.i où i est la position de votre mac sur 2 chiffres dans la salle depuis
la porte d’entrée. Pour réaliser la discussion entre toutes les machines de
la salle, vous utiliserez le port à 6666 et l’adresse multicast 230.1.1.66.
Dans la suite p désigne le port et am l’adresse multicast.
2. Écrire un constructeur qui :
• initialise le port à p
• crée le socket par socket = new MulticastSocket (port)
• crée l’adresse multicast par multicastAddress = InetAddress.getByName
("am"),
• indique que le socket va servir à recevoir les paquets à destination de
cette adresse par socket.joinGroup (multicastAddress).
La classe ByteBuffer (java.nio.ByteBuffer) est utilisée pour envoyer et recevoir
des paquets. Un ByteBuffer b manipule de manière interne un tableau d’octets
que l’on obtient par b.array(). On peut obtenir sa capacité par b.capacity(). On
peut de plus lire et écrire à une position courante (obtenue par b.position()) par
des méthodes de type get et put. Les lectures se font jusqu’à une position limite
donnée par b.limit(). La méthode getString suivante sert à lire une String de
longueur connue dans un ByteBuffer:

2
static String getString (ByteBuffer b, int len) {
byte[] t = new byte[len] ;
b.get (t) ;
return new String (t, 0, len) ;
}
La conversion de String vers byte[] se fait par la méthode getBytes().

3. Écrire une méthode send() qui prend en argument un ByteBuffer et envoie


son contenu sur le socket par la méthode send de MulticastSocket. Seuls
les octets entre le début du ByteBuffer et sa position courante doivent être
envoyés.
Il faudra pour cela construire un DatagramPacket à partir du ByteBuffer,
de l’adresse am et du port p de destination. Vous pouvez utiliser le con-
structeur: DatagramPacket(byte[] buf, int length) pour affecter les don-
nées et la méthode setSocketAddress(SocketAddress address) pour affecter
l’adresse destination am, et le port p.
4. Écrire une méthode receive() qui prend en argument un ByteBuffer, rem-
plit son contenu par celui du paquet reçu et renvoie l’adresse et le port
de l’envoyeur sous forme de SocketAddress. Utiliser pour cela la méthode
receive(DatagramPacket x) de MulticastSocket pour recevoir un paquet.
Vous pouvez utiliser le constructeur DatagramPacket(byte[] buf, int length)
pour partager le même tableau de bytes que le ByteBuffer. Mettre ensuite
la position du ByteBuffer à 0 et sa limite à la longueur du Datagram-
Packet (qui est obtenue par getLength()). Renvoyer l’adresse et le port de
l’envoyeur du paquet obtenus par getSocketAddress().
5. Tester vos méthodes avec le code ci-dessous qui envoie un message lu dans
les arguments du main et affiche dans une boucle infinie tous les paquets
reçus.

public static void main (String[] args) {


Com s = new Com (ad);
ByteBuffer b = ByteBuffer.allocate(1400) ;
InetAddress moi;
try {
moi = InetAddress.getLocalHost();
} catch (UnknownHostException ex) {
moi=null;
}
String msg = "envoi de "+ moi.getHostAddress() ;
for (String a : args) msg += " " + a ;
b.put (msg.getBytes()) ;
s.send (b);
while (true) {

3
System.out.println ("reception de " + s.receive (b) + " : "
+ getString (b, b.limit())) ;
}
}

Pour pouvoir discuter clairement les uns avec les autres de manière plus
robuste, on utilise un format particulier de message :

ID est un champ indiquant la nature du message (ce qui permet de prévoir


des extensions)(codé sur 2 octets). Pour l’instant l’ID des messages est
DATA avec "public static short DATA = 1 ;".
surnom identifie l’envoyeur, c’est une suite de 6 lettres (codée sur 6 octets).

seq est un numéro de séquence (sur 2 octets) incrémenté par l’envoyeur chaque
fois qu’il envoie un paquet.
taille est la longueur du message qui suit sur 2 octets.
message c’est la suite des caractères du message.

Le protocole indique que tous les messages correctement formés suivant la de-
scription ci-dessus seront affichés dés qu’ils sont reçus (on ne se préoccupe pas
ici de vérifier le champ seq).
6. Écrire l’application de discussion avec un thread pour la réception des
messages, le thread principal étant dédié à l’envoi.

7. Dans une application réelle de discussion sur Internet, des paquets peu-
vent être perdus ou déséquencés, notamment en cas de congestion dans le
réseau.
(a) Définissez un protocole ( en ajoutant de nouveaux types de messages)
pour signaler la perte du message à son émetteur et demander la
réémission des paquets perdus. Lors la définition de ce protocole vous
aurez des choix à faire: quand, à qui et combien de fois demander
la réémission d’un paquet, dans quel ordre afficher les messages, que
faire en cas de message non reçu... Justifiez les choix que vous avez
faits.
(b) Réalisez une application suivant le protocole que vous avez défini.
(c) Testez votre application en émulant des pertes des messages et des
dé séquencés.

Vous aimerez peut-être aussi