Vous êtes sur la page 1sur 6

Ecole Supérieur de Technologie de Khénifra

Département : Génie de l’informatique et sciences sociales


Filière : Administrateur des Systèmes et Réseaux
Module : Systèmes et applications répartis
TP N°2 les sockets UDP
Objectifs du TP :
Le but de ce TP est de montrer la mise en œuvre du protocole de transport UDP (mode non
connecté) au moyen des sockets en Java.

Principes généraux
Le mode de communication utilisé par le protocole UDP est le mode non connecté. Dans ce mode
de fonctionnement, il n’est pas nécessaire de préparer la communication. Chaque datagramme est
transféré indépendamment des autres. Ceci implique que chaque datagramme devra rechercher une
route vers le destinataire. De ce fait, il n’y a pas de garantie, ni sur l’arrivée des paquets à destination,
ni sur l’ordre d’arrivée de ces derniers. La seule garantie offerte par ce mode de communication est
le fait que les données reçues sont sans erreur.
Pour utiliser le protocole de transport UDP, il est nécessaire en Java de manipuler deux
classes DatagramPacket et DatagramSocket

La classe DatagramPacket

Cette classe permet de créer des objets qui contiendront les données envoyées ou reçues ainsi que
l'adresse de destination ou de provenance du datagramme.

Deux constructeurs sont disponibles, un pour les paquets à recevoir, l'autre pour les paquets à
envoyer.

 public DatagramPacket(byte buffer[], int taille) : Construit un objet pour recevoir un


datagramme. Le paramètre buffer correspond à la zone où doit être stocké le datagramme reçu
et le paramètre taille correspond à la taille maximale des datagrammes à recevoir.

 public DatagramPacket(byte buffer[], int taille, InetAddress adresse, int port) : Construit un
objet pour envoyer un datagramme. Le paramètre buffer correspond à la zone où est stocké le
datagramme à envoyer, le paramètre taille correspond à la taille du datagramme à
envoyer, adresse correspond à l'adresse de la machine à qui envoyer le datagramme et port sur
quel port UDP.

Des méthodes sont disponibles pour manipuler de tels objets :

 public synchronized InetAddress getAddress () : Retourne l'adresse stockée dans le paquet.

 public synchronized int getPort () : Retourne le port stocké dans le paquet.

 public synchronized byte[] getData () : Retourne les données stockées dans le paquet.

 public synchronized int getLength () : Retourne la taille des données stockées dans le paquet.

 public synchronized void setAddress(InetAddress iaddr): Modifie ou affecte l'adresse de


destination.

 public synchronized void setPort(int iport): Modifie ou affecte le port de destination.


 public synchronized void setData(byte ibuf[]): Modifie ou affecte la référence de la zone
contenant les données.

 public synchronized void setLength(int ilength): Modifie ou affecte la taille de la zone


contenant les données.

La classe DatagramSocket

Cette classe permet de créer des sockets UDP qui permettent d'envoyer et de recevoir des
datagrammes UDP.

Avant toute communication en mode UDP il est nécessaire de créer une socket aussi bien du coté
client que du coté serveur. Pour cela Java propose trois constructeurs :

 public DatagramSocket () throws SocketException : Crée un objet de type socket et l'attache à


un port disponible de la machine locale. Ce constructeur doit être utilisé dans les clients pour
lesquels le port d'attachement n'a pas besoin d'être connu.

 public DatagramSocket (int port) throws SocketException : Crée un objet de type socket et
l'attache au port UDP local passé en paramètre. En particulier, ce constructeur doit être utilisé
dans les serveurs pour lesquels le port d'attachement a besoin d'être fixé préalablement afin qu'il
soit connu des clients.

 public DatagramSocket(int port, InetAddress laddr) throws SocketException: Crée un objet de


type socket, l'attache au port UDP local passé en paramètre et à une adresse spécifique de la
machine locale. Ce constructeur n'est utile que si la machine locale dispose de plusieurs adresses
Internet.

Une fois la socket (objet de type DatagramSocket) créée et attachée à un port particulier de la
machine locale, il est possible d'envoyer et de recevoir des datagrammes, via cette socket, au moyen
des méthodes suivantes :

 public void send(DatagramPacket data) throws IOException: Permet d'envoyer les données
contenues dans la variable data vers la machine et le port dont les valeurs ont été préalablement
spécifiées dans la variable data.

 public synchronized void receive(DatagramPacket data) throws IOException : Permet de


recevoir un datagramme qui sera stocké dans data. Après appel, data contient les données
reçues, leur taille, l'adresse de l'envoyeur ainsi que son port d'attachement. Cette méthode est
bloquante tant qu'il n'y a rien à recevoir. Si le message est trop long pour être stocké, celui-ci
est tronqué, et le reste est perdu. Il n'est donc pas possible de recevoir des messages dont on ne
connait pas préalablement la taille.

Il est possible de spécifier un délai d'attente maximal en reception. Pour cela, il faut positionner
une variable de timeout sur la socket au moyen de la méthode :

 public synchronized void setSoTimeout(int timeout) throws SocketException: Une valeur


de 0 (zéro) correspond à ne pas avoir de timeout.

D'autres méthodes sont disponibles pour manipuler ces sockets :

 public void close () : Ferme la socket et libère les ressources qui lui sont associées. La socket ne
pourra plus être utilisée ni pour envoyer, ni pour recevoir des datagrammes.
 public int getLocalPort () : Retourne le port d'attachement de la socket.

 public synchronized int getSoTimeout() throws SocketException: Retourne la valeur courante


du timeout associé à la socket.

Voici un schéma d’émission et de réception d’un datagramme UDP en Java :


Emission
1. Création d’un socket UDP. Pour cela, utilisez un constructeur de la classe
Java.net.DatagramSocket.
2. Fabrication d’un paquet avec les données à envoyer ;
3. Envoyer le paquet à travers le socket.
4. Recommencer l´étape de fabrication si nécessaire.
Réception
1. Création d’un socket UDP sur un port spécifique (le port de réception des données).
Pour cela, utilisez un constructeur de la classe Java.net.DatagramSocket;
2. Préparation d’un paquet coquille pour la réception des données ;
3. Attendre la réception d’un paquet ;
4. Récupérer les informations contenues dans le paquet si nécessaire (adresse et port de
l´émetteur, données).
5. Utilisez les données en fonction de vos besoins.

Exercice 1 :

Tester sur même machine et deux machines distants le code des parties client et serveur.
Module Systèmes Répartis
Coté client :

import java.net.*;
import java.util.Scanner;

public class ClientUDP {

public static void main(String argv[]) {


int port = 0;
String host = "";
Scanner keyb = new Scanner(System.in);

try {
// on récupère les paramètres : nom de la machine serveur et
// numéro de port
System.out.println("Adress du serveur : ");
host = keyb.next();
System.out.println("port d'écoute du serveur : ");
port = keyb.nextInt();
InetAddress adr;
DatagramPacket packet;
DatagramSocket socket;

// adr contient l'@IP de la partie serveur


adr = InetAddress.getByName(host);

// données à envoyer : chaîne de caractères


byte[] data = (new String("Hello Word")).getBytes();

// création du paquet avec les données et en précisant l'adresse


// du serveur (@IP et port sur lequel il écoute)
packet = new DatagramPacket(data, data.length, adr, port);

// création d'une socket, sans la lier à un port particulier


socket = new DatagramSocket();

// envoi du paquet via la socket


socket.send(packet);

// création d'un tableau vide pour la réception


byte[] reponse = new byte[15];
packet.setData(reponse);
packet.setLength(reponse.length);

// attente paquet envoyé sur la socket du client


socket.receive(packet);

// récupération et affichage de la donnée contenue dans le paquet


String chaine = new String(packet.getData(), 0,
packet.getLength()); System.out.println("
reçu du serveur : " + chaine);
} catch (Exception e) {
System.err.println("Erreur : " + e);
}
}
}

Coté serveur :

import java.net.*;
import java.util.Scanner;

public class ServeurUDP {

public static void main(String argv[]) {

int port = 0;
Scanner keyb = new Scanner(System.in);
try {

// on récupère le paramètre : port


d'écoute System.out.println("port d'écoute
: "); port = keyb.nextInt();

DatagramPacket packet;

// création d'une socket liée au port précisé en paramètre


DatagramSocket socket = new DatagramSocket(port);

// tableau de 15 octets qui contiendra les données


reçues byte[] data = new byte[15];

// création d'un paquet en utilisant le tableau d'octets


packet = new DatagramPacket(data, data.length);

// attente de la réception d'un paquet. Le paquet reçu est placé


// dans packet et ses données dans data.
socket.receive(packet);

// récupération et affichage des données (une chaîne de caractères)


String chaine = new String(packet.getData(), 0,
packet.getLength());
System.out.println(" recu : " + chaine);

System.out.println(" ca vient de : " + packet.getAddress() + ":"


+ packet.getPort());

// on met une nouvelle donnée dans le paquet


// (qui contient donc le couple @IP/port de la socket coté
client) byte[] reponse = (new String("bien recu")).getBytes();
packet.setData(reponse); packet.setLength(reponse.length);

// on envoie le paquet au client


socket.send(packet);
} catch (Exception e) {
System.err.println("Erreur : " + e);
}
}
}
Exercice 2 :

On souhaite échanger entre le client/serveur les objets d’une classe voiture via les sockets
UDP.
Pour cela le client Crée un objet voiture et l’envoi au serveur pour lui fixer une quantité de
carburant avec la méthode setCarburant().

import java.io.*;

class voiture implements Serializable {

private int carburant;


private String model;
private String type;
private static int capacite = 300;

voiture(String _type, String _model) {


type = _type;
model = _model;
carburant = 0;
}

public void setCarburant(int c) {


int maxi = capacite - carburant;
if (c < maxi) {
carburant += c;
System.out.println("Le remplissage a été effectué sans problème.");
} else {
carburant = capacite;
System.out.println((c - maxi) + " litre(s) de carburant ont
débordé.");
}
}
public int getCarburant() {
return carburant;
}
public int getCapacite() {
return capacite;
}
}
1. Ecrire la partie client de l’application et la partie serveur.
2. Tester cette application sur la même machine.
3. Tester cette application sur deux machines reliées par réseaux.

Exercice 3 :

Créez localement un serveur UDP qui écoutera sur le port 1250 et qui pour chaque datagramme
reçu et quelque soit leur contenu, retournera à l’émetteur un datagramme contenant la date et
l’heure courante.

Vous aimerez peut-être aussi