0% ont trouvé ce document utile (0 vote)
39 vues30 pages

CH 3

Transféré par

James Larrieux
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
39 vues30 pages

CH 3

Transféré par

James Larrieux
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Module D225

Gestion des réseaux

Partie 2 : Programmation réseau

La programmation réseau en Java

Introduction
Les classes java.net correspondantes aux communications orientées connexion
Les classes java.net communes pour les communications orientées connexion et orientées sans
connexion
Les classes java.net correspondantes aux communications orientées sans connexion

Kechid Mounir
[email protected]
La programmation réseau en Java

Introduction

Le langage java offre l'un de ses aspects les plus originaux, à travers le package Java.net. Ce
package rassemble toutes les classes nécessaires à l'élaboration de programmes réseaux
communiquant via les interfaces Socket. Les classes de java.net peuvent être reparties en deux
principales catégories.

● Les classes pour la communication WEB : Ce sont les classes facilitant les fonctions réseaux
liées aux Word Wide Web, ainsi que les classes liées aux URLs (URL,URL connexion). Cette
catégorie de classes sort du cadre de ce cours et ne sera pas donc abordée.
● Les Classes générales de communication : C'est l‛ensemble de classes qui offre l'accès aux
communications réseau brutes (Communications du niveau socket). Selon le mode de
communication, cet ensemble peut être réparti en trois groupes. Un groupe de classes pour
les communications en mode connexion, un autre pour celles en modes sans connexion et un
troisième commun aux deux types de communication.

1. Les classes java.net correspondantes aux communications orientées


connexion

Deux classes sont offertes par java pour permettre des communications orientées connexion entre
les programmes distants. La classe java.net.ServerSocket qui est utilisée, normalement, par les
programmes serveur (pour l‛écoute sur un port) et la classe java.net.socket qui est utilisée par les
clients (pour la connexion et la communication) et les serveurs (pour communiquer).

1.1 La classe java.net.socket

La classe java.net.Socket est utilisée pour la programmation des sockets connectées, côté client et
côté serveur (pour la communication avec les clients connectés comme on va le voir infra).

Les constructeurs :
Cette classe possède six constructeurs.

1. public Socket(String hote, int port ) throws UnknownHostExeption


2. public Socket (InetAddress adresse, int port ) throws IOExeption
3. public Socket (String hote, int port, InetAddress localaddr,int local port) throws
IOExeption
4. public Socket (InetAddress address, int port, InetAddress localaddr, int localport) throws
IOExeption

Les deux premiers constructeurs construisent une socket connectée à la machine et


au port spécifiés (distants). Par défaut, la connexion est de type TCP fiable. Les deux autres
constructeurs permettent, en outre, de fixer l'adresse IP et le numéro de port utilisés côté client
(plutôt que d'utiliser un port disponible quelconque).Ces constructeurs sont utiles dans le cas où la
machine contenant le client contient plusieurs cartes réseaux et ainsi plusieurs adresses IP.

Exemple :

try
{
// Connexion au serveur http (dont le port est 80) de l‛hôte 192.21 22.23
Socket maSocket = new Socket ( "192.21 22.23", 80);
// ......
// Connexion à un serveur local dont le port est 2000
Socket maSocketLocale = Socket("localhost"[1], 7);
}
catch (Exception e)
{
System.err.println ("Err – " + e);
}

Remarque : Le temps de réponse de ces constructeurs dépend du réseau et du


système d‛exploitation. S‛il n‛y a aucun problème, l‛exécution du constructeur finira dès que la
connexion sera établie. Dans le cas contraire (si la machine distante, ou plutôt le réseau, tarde à
répondre), le constructeur bloque l‛application appelante pour un temps indéfini. Ainsi, pour les
applications critiques, la procédure de création de la socket connectée est faite dans un
thread à part.

Les méthodes

Les méthodes les plus importante de cette classe sont exposées selon leurs utilités :

Les méthodes d'interrogation :


● public InetAddress getInetAddress()
● public Inetaddress getLocalAddress()
● public int getPort()
● public int getLocalPort()

Les deux premières méthodes récupèrent, respectivement, l'adresse IP distante et l'adresse IP


locale sur laquelle est connectée la socket. Les deux dernières méthodes renvoient le numéro de
port distant et local sur lequel est connectée la socket en question.

Les méthodes de communication :

La communication effective à travers une socket connectée utilise la notion de flots de données
(java.io.OutputStream et java.io.InputStream). Les deux méthodes suivantes sont utilisées pour
obtenir les flots en entrée et en sortie.

● public InputStream getInputStream() throws IOException


● public OutputStream getOutputStream() throws IOException

La première méthode renvoie un flux d'entrée pour la socket, qui peut être utilisé pour lire les
octets de données de la socket. La deuxième renvoie un flux de sortie pour la socket qui peut être
utilisé pour écrire les octets dans la socket. L‛exemple suivant montre comment, créer les streams
pour lire et écrire sur la socket (maSocket) et comment les utiliser pour communiquer.

Exemple :

try
{
// Connexion au serveur http de l‛hôte 192.21 22.23
Socket maSocket = new Socket ( "192.21 22.23 ", 80);
// Création du Stream pour lire sur la socket (maSocket)
BufferedReader fEntrant = new BufferedReader (new InputStreamReader (maSocket.
getInputStream() ) );
// Création du Stream pour écrire sur la socket (maSocket)
PrintStream fSortant = new PrintStream( maSocket.getOutputStream() );
...
// Écriture sur maSocket (envoi à ( "192.21 22.23", 80) )
fSortant.println("Bonjour ");
...
// Lecture (des flux reçus de ( "192.21 22.23 ", 80)) sur maSocket
String reception = fEntrant.readLine();

}
catch (Exception e)
{
System.err.println ("Error – " + e);
}

Les méthodes d'option

Ces méthodes permettent de gérer certaines options pendant une communication connectée, les
noms de ces méthodes, leurs prototypes et leurs rôles sont résumés dans le tableau suivant :

Option Prototypes des méthodes Rôle des méthodes

● void setTcpNoDelay(boolean L‛une active (désactive) et l‛autre


onFlag) throws java.net. vérifie l‛activation de l‛option qui
SocketException retarde l‛envoi des petits
● boolean getTcpNoDelay () throws morceaux de données.
java.net.SocketException
TcpNoDellay

● int getSoLinger() throws java.net. La première permet de fixer un


SocketException délai pour la fermeture de la
● void setSoLinger(boolean onFlag, socket et la deuxième vérifie si la
int duration) throws java.net. socket en question est limitée par
SocketException java.lang. un délai.
SoLinger
IllegalArgumentException

● void setSoTimeout(int duration) L‛une fixe et l‛autre retourne la


throws java.net.SocketException durée de blocage de la méthode
SoTimeout ● int getSoTimeout() throws java. de lecture (readLine()...) en
net.SocketException attente des données.

La méthode close :

void close() throws java.io.IOException

Elle sert à fermer la connexion à travers la socket en question.


Exercice 1: Le service Daytime est usuellement fourni par un serveur dont le port est 13. Ce
serveur retourne, aux clients qui le contactent, la date du jour et l‛heure courante. On
suppose que l‛on a l‛adresse d‛une machine qui fourni ce service (soit, par exemple, la machine
locale). Ecrire en Java le code du client Daytime.

Indices 1 : La structure supérieure du Daytimeclient demandé est la suivante

● Créer la socket
● Créer un flux d‛entrée (input stream) et le relier à la socket créée.
● Lire les données du flux d‛entrée crée et afficher le résultat.

Solution 1 :

1. import java.net.*;
2. import java.io.*;

3. public class DaytimeClient


4. {
5. public static final int SERVICE_PORT = 13;
6. public static void main(String args[])
7. {
// Lecture du nom de l'hôte serveur. Nous avons choisis l'hôte local pour faciliter
le test isolé
8. String hostname = "localhost";
9. try
10. {
// Création et connexion de la socket au serveur daytime
11. Socket daytime = new Socket (hostname, SERVICE_PORT);
12. System.out.println ("Connexion établie");
// Création du stream d'entrée et lecture sur ce stream (à partir du serveur)
13. BufferedReader reader = new BufferedReader (new
InputStreamReader (daytime.getInputStream() ));
14. System.out.println ("Le résultat : " + reader.readLine());
// Fermeture de la connexion
15. daytime.close();
16. }
17. catch (IOException ioe)
18. {
19. System.err.println ("Error " + ioe);
20. }
21. }
22. }

Code 1 : le client Daytime (DaytimeClient.java)


La lecture des flux de donnée qui proviennent de l‛interlocuteur extérieur (serveur ou client) peut
conduire l‛application qui le fait à attendre pour un temps indéterminé (voir pour toujours), à cause
de l‛aspect bloquant de la méthode de lecture. Pour limiter le temps d‛attente de la méthode de
lecture (readline) sur la socket, la classe java.net a prévu une méthode pour le fixer. C‛est la
méthode setSoTimeout, vue supra.

Q: Si l‛on veut que notre client Daytime ne se bloque pas en attente de la réponse plus que 5
secondes. Que doit-t-on rajouter et où dans le code 1 ?

R : On doit rajouter entre la ligne 11 et 13 du code 1 :

daytime.setSoTimeout (5000);

Note : Si vous voulez tester le programme DayTimeClient (avec les programmes serveur présentés
infra), n‛oubliez pas d‛effacer les numérotations des lignes du code1.

1.2 La classe java.net.ServerSocket

Cette classe englobe des objets qui représentent l'interface socket (la socket) pour les serveurs
en mode connecté. De telles sockets attendent des connexions de la part des clients, lorsqu'un
client sollicite une connexion, la socket serveur l'accepte en créant (comme on va le voir) une autre
socket de la classe précédente (java.net.socket) pour communiquer avec le client. Donc on peut dire
que ces socket sont des socket d'écoute. Elles ne font qu'accepter des connexions. Aucune
communication effective (échange d‛information) ne se passe à travers elles. Les différents
constructeurs et méthodes de cette classe sont énumérés dans les sous-sections suivantes.

Les constructeurs

Cette classe possède trois constructeurs :

1. public ServerSocket( int port) throws IOExeption


2. public ServerSocket( int port, int backlog) throws IOExeption
3. public ServerSocket( int port, int backlog, InetAddress bindAddress) throws IOExeption

Pour un objet ServerSocket deux informations sont essentielles, le numéro de port spécifique sur
lequel écoute la socket (il doit être supérieur à 1024 pour éviter les confusions avec les serveurs
standard qui prennent des numéro de ports entre 0 et 1024) et la longueur maximale de la file
d'attente des connexions entrantes (si cette file est pleine, tout client qui sollicite une connexion
sera rejeté).

Alors que le premier constructeur ne permet de définir que le numéro de port (la longueur de la file
étant prise par défaut égale à 50) le deuxième donne la liberté du choix de cette longueur. Si
l'hôte où réside le serveur contient plusieurs adresses IP, le troisième constructeur donne la
possibilité d'indiquer l'adresse IP à laquelle créer la socket.

Remarque : un constructeur de cette classe est équivalent à la succession des


primitives (socket, bind, listen) vues dans le chapitre précédent.

Exemple :

try
{
// Attacher la socket au port 80, pour fournir un service orienté connexion
ServerSocket maServer = new ServerSocket ( 80 );
// ......
}
catch (IOException ioe)
{
System.err.println ("I/O error – " + ioe);
}

Les méthodes :

Les méthodes d'information :

● public InetAddress getInetAdress ()


● public int getLocalport()

La première méthode retourne l'adresse IP locale sur laquelle est connectée la socket serveur
invoquée et la deuxième permet d'en récupérer le numéro de port local.

La méthode accept :

public socket accept() throws IOExeption

A la détection d'une demande de connexion d'un client, la méthode accept retourne un objet socket
de la classe java.net.socket (vu supra). C‛est cette socket retournée qui sera utilisée pour la
communication avec le client et pas la socket serveur qui ne fait qu'écouter.
Exemple :

try
{
// Attacher la socket au port 80, pour fournir un service orienté connexion (like
HTTP)
ServerSocket monServeur = new ServerSocket ( 80 );
// Établissement d‛une écoute bloquante pour la lecture de la prochaine
connexion //socket
Socket nextSocket = monServeur.accept();
// Création du Stream pour lire et écrire sur la socket (nextSocket)
BufferedReader reader = new BufferedReader (new InputStreamReader
(nextSocket.getInputStream() ) );
PrintWriter writer = new PrintWriter( new OutputStreamWriter (nextSocket.
getOutputStream() ) );
}
catch (IOException ioe)
{
System.err.println ("I/O error – " + ioe);
}

La méthode setSoTimeout :

public void setSoTimeout( int timeout) throws socketExeption

Comme son analogue vue supra, cette méthode permet de fixer la période de temporisation d‛une
méthode bloquante. Il s‛agit de accept(). Avec une valeur égale à zéro la période de temporisation
devient infinie.

La méthode toString :

public toString()

Cette méthode renvoie une représentation sous forme de chaîne de caractères de la socket
serveur invoquée (adresse IP du programme distant, son port et le port local).

La méthode close :

public void close() throws IOExeption

Cette méthode ferme la socket serveur invoquée.


Création de serveurs :

Voyons maintenant, comment développer en Java chacun des deux types de serveur présentés dans
le chapitre 1 :

Serveur itératif : Les serveurs itératifs traitent un client à la fois.


Leur développement pour le mode connecté en java est très simple. Ils sont implémentés par des
applications mono-thread (souvent appelées en anglais bare-bones server).

Exercice 2 : Ecrire le code du serveur itératif Daytime.

Indice 2 : La méthode permettant de donner la date et l‛heure courante est java.util.Date()

Solution 2 :

import java.net.*;
import java.io.*;

public class ServeurDaytime


{
public static final int SERVICE_PORT = 13;
public static void main(String args[])
{
try
{

//Attacher la socket au port 13, pour garantir aux clients l'accès au service
daytime

ServerSocket server = new ServerSocket (SERVICE_PORT);


System.out.println ("le service Daytime a commencé");

//Boucler indéfiniment pour accepter et servir les client


for (;;)
{
// Connexion au prochain client.
Socket nextClient = server.accept();
// Affichage des détaille de la connexion
System.out.println ("Reception d'une requette de " + nextClient.getInetAddress
() + ":" + nextClient.getPort() );
// Création du Stream pour écrire sur la socket (nextClient)
OutputStream out = nextClient.getOutputStream();
PrintStream pout = new PrintStream (out);
// Envoyer la date du jour au client
pout.print( new java.util.Date() );
// Effacer les bytes non émis
out.flush();
// fermeture du stream
out.close();
// fermeture de la connexion
nextClient.close();
}
}
catch (BindException be)
{
System.err.println ("Service already running on port "+ SERVICE_PORT );
}
catch (IOException ioe)
{
System.err.println ("I/O error - " + ioe);
}
}
}

Code 2 : Le serveur itératif Daytime (ServeurDaytime.java)

Serveur concurrent :

Les serveurs concurrents traitent plusieurs requêtes en même temps. Ils sont donc implémentés
par des applications muti-thread. Comme vu, au chapitre précédent, le principe est le suivant :

Pour implémenter un serveur concurrent en Java, deux types de thread sont utilisés. Un processus
(thread) primaire et les threads secondaires. Le rôle du thread primaire est : (1) d‛écouter sur le
port correspondant à travers la méthode socket, et, (2) de lancer un thread secondaire, à chaque
fois qu‛un client se connecte. Le lancement du thread secondaire nécessite qu‛une classe de threads
soit déjà définie. Les objets de cette classe sont des threads qui implémentent le service demandé.
Un thread secondaire aura le rôle de réaliser les calculs et les communications nécessaires pour
fournir le service au client en question. Dans l‛exemple suivant nous présentons un code commenté
de la version concurrente du serveur dayTime.
Exemple : serveur dayTime concurent.

import java.net.*;
import java.io.*;
import java.lang.*;
import java.util.*;
public class ServeurDaytimeConc
{
public static final int SERVICE_PORT = 13;
public static void main(String args[])
{
try
{
//Attacher la socket au port 13, pour garantir aux clients l'accès au service
daytime
ServerSocket server = new ServerSocket (SERVICE_PORT);
System.out.println ("le service Daytime a commencé");
//Boucler indéfiniment pour accepter les clients
while (true)
{
//Connexion au prochain client.
Socket nextClient = server.accept();
// Affichage des détailles de la connexion
System.out.println ("Réception d'une requête de" + nextClient.
getInetAddress() + ":" +nextClient.getPort() );
//affectation d'un thread de la classe DaytimeThread (définie en bas)
//et l'initialiser par la socket nextClient
DaytimeThread Dt = new DaytimeThread (nextClient);
// Lancement du thread Dt
Dt.start();
}
}
catch ( Exception exc)
{
System.out.println ("Error - " + exc.toString());
}
}
}
// La classe DaytimeThread
class DaytimeThread extends Thread
{
// La socket sur laquelle s'effectue la communication
Socket incoming;
DaytimeThread (Socket incoming)
{
this. incoming = incoming;
}
// La méthode exécutable implémentée par la classe de thread
public void run()
{
try
{
// Création du Stream pour écrire sur la socket (incoming)
OutputStream out = incoming.getOutputStream();
PrintStream pout = new PrintStream (out);
// Envoyer la date du jour au client
pout.print (new java.util.Date() );
// Effacer les bytes non émis
out.flush();
// Fermeture du stream
out.close();
// Fermeture de la connexion
incoming.close();
}
catch (IOException ioe)
{
System.err.println ("Error " + ioe);
}
}
}

Code 3 : Le serveur concurrent Daytime (ServeurDaytimeConc.java)

Note : A travers les trois exemples précédents, vous pouvez vous amusez à tester toutes
les méthodes des classes socket et ServerSocket.

[1] "localhost"est le nom assigné à l‛adresse 127.0.0.1 qui représente généralement l‛adresse de la
machine locale.
2. Les classes java.net communes pour les communications orientées
connexion et orientées sans connexion

Dans ce paragraphe, nous allons voir principalement la classe java.net.IntAddress

2.1 La classe java.net.InetAddress

Dans le réseaux Internet, au niveau application, chaque hôte peut être représenté, soit par une
adresse IP sous la forme de notation décimale à point comme (192.21 22.23), soit, par une
notation textuelle : le nom d ‛ hôte [1] , comme www.google.fr. Un serveur
distribué dit Serveur de noms DNS est utilisé, dans le réseau Internet,
pour la translation des noms d‛hôte en adresses IP et vis vers ça.

En java, notamment pour les communications


orientées sans connexion , l‛identification des hôtes et la
manipulation de leurs adresses sont réalisés à travers la classe java.net.InetAddress. Ainsi, les
objets de cette classe sont utilisés pour représentés les adresse IP dans les application Java et
ses méthode permettent de les manipuler : (en extraire leur représentation décimale à point ou
textuelles…).

Contrairement aux autres classes, celle-ci n‛a pas de constructeur. A la place, elle a des méthodes
qui retournent des objets InetAddress.

Méthodes:

1-La méthode getAllByName :

public static InetAddress[] getAllByName ( String hostname ) throws


java.net.UnknownHostException, java.lang.SecurityException—

Elle a pour rôle de retourner les différentes adresses IP propres à un hôte dont le nom est
spécifié comme paramètre d'entrée sous la forme de notation décimale à point ou bien sous la
forme d'un nom DNS.

2-La méthode getByName

public static InetAddress getByName (String hostname) throws java.


net.UnknownHostException, java.lang.SecurityException

C'est une version spécifique de la précédente, mais cella ne retourne que l'une (aléatoirement)
des adresses IP de l‛hôte. Elle est utilisée pour les hôtes n'ayant qu'une seule carte réseau.

3- La méthode getLocalHost()

public static InetAddress getLocalHost() throws java.net.


UnknownHost Exception, java.lang.SecurityException—

4-La méthode equals :

public boolean equals(object obj )

Elle permet la comparaison de deux objets. Elle retourne true si les deux objets comparés sont
égaux (la même adresse IP) et false sinon.

5- La méthode getAddress

public byte [ ] getAddress ( )

Elle retourne l'adresse IP brute sous la forme d'une matrice d'octet dans l'ordre des octets du
réseau.

6- La méthode getHostAddress:

public String getHostAdress ( )

Elle renvoie l'adresse IP sous forme de notation décimale à point.

7-La méthode getHostNam:

public String getHostNam ( )

Cette méthode a le même rôle que la précédente mais elle retourne une IP sous forme textuelle :
le nom DNS.

8 -La méthode IsMulticastAdress :

public Boolean IsMulticostAdress ( )

Elle définit si l'adresse IP en question est multicast ou pas.


Exemples : Pour illustrer l‛utilisation de la classe InetAddress , dans cet
exemple, nous avons pris l‛adresse de l‛hôte local pour permettre le test sur une machine
isolée. Vous pouvez le faire pour toute autre adresse valide si votre machine est connectée.

import java.net.*;
public class ResolutionAdresse
{
static final String adresseIP="127.0.0.1";
public static void main(String args[])
{
System.out.println ("resolution de l'adresse " + adresseIP);
try
{
InetAddress addr = InetAddress.getByName ( adresseIP);
System.out.println ("Le nom de l'hote correspndant à : "+ addr.
getHostAddress() + " est: "+ addr.getHostName() );
}
catch (UnknownHostException uhe)
{
System.out.println ("Error - incapable de trouver le nom du Hôte " );
}
}
}

Code 4 : Résolution d‛adresse (ResolutionAdresse.java)

[1] La notation textuel nom d‛hôte est apparus pour permettre aux administrateurs,
programmeurs et utilisateurs finaux du réseau de mémoriser facilement les noms des hôtes.
3. Les classes Java.net correspondantes aux communications orientées
sans connexion

Nous allons voir, dans cette section, les différentes classes essentiellement offertes par Java
aux programmes communiquant à distance une communication orientée sans connexion (via UDP).

3.1 La classe java.net.DatagramPacket

Alors que dans les communications orientées connexion :

1) Toutes les informations concernant l‛identification d‛un processus (adresse Ip et port) sont
prise en charge dans les classes socket (Socket et SocketServer) qui établissent le contact et la
communication distante.

Et,

2) Une fois les socket créés et configurées, Les communication sont effectuées à travers les
méthodes d‛entrées/sortie habituelles où les périphériques d‛entrées/ sortie (clavier, écran,
fichier..) sont remplacés par (des objet sockets ou socketServer)

Pour les applications orientées sans connexion, Java consacre toute une classe pour les données
destinées à être communiquées via UDP (sans connexion). C‛est la classe java.net.
DatagramPacket. Un objet de cette classe contiendra en plus des données mises sous forme d‛un
tableau d‛octets, des informations sur l‛adressage du programme
distant , à savoir son adresse IP et son Port. La signification du contenu (Données et
info d‛adressage) d‛un objet DatagramPacket dépend du contexte. En effet, les objets
DatagramPacket sont manipulés soit (1) pour l‛envoi de données vers l‛extérieur, soit, (2) pour la
réception de données venant de l‛extérieur. Dans le premier cas, l‛adresse IP et le port
concernent le programme distant qui va recevoir les données et dans le
deuxième cas, ces informations concernent le programme distant duquel
proviennent ces données. La forme d‛un objet de la classe DatagramPacket est donnée à la
figure suivante:
Les constructeurs :

Les paquets de Datagrammes sont créés et initialisés par des données sous la forme de matrices
(tableaux) d'octets. Et selon que le programme veut envoyer des données ou en recevoir dans sa
communication sans connexion, il utilisera le premier ou le deuxième constructeur de cette classe.

● Le constructeur par défaut :

public DatagramPacket( byte[] Ibuf, int Ilength)

Ce constructeur est dédié à la création d'objets récipients destinés à la réception. Le premier


paramètre de type tableau d'octet constitue le tampon de cette réception. Le deuxième
paramètre de ce constructeur indique la taille du tampon.

Exemple : DatagramPacket packet = new DatagramPacket(new byte[256], 256);

● Le constructeur de D-paquets destinés à l'émission :

public DatagramPacket ( byte[] Ibuf, int Ilength, InetAddress Iaddr, int port )

Le premier paramètre de ce constructeur indique le tampon à partir duquel doivent être envoyées
les données. Le deuxième indique le nombre d'octets en paquets à envoyer, les deux autres
paramètres permettent lors de l'envoi ultérieur de ce paquet d'identifier le programme cible en
fournissant le couple (adresse IP, numéro de port).

Remarque : Le type des données à encapsuler dans un DatagramPacket devant être le type Byte
[], Java offre pour tous les autre types des méthodes pour la conversion au type Byte[].Par
exemple pour envoyer des données de type string

Exemple :

InetAddress adresse = InetAddress.getByName("192.168.15.12");


String ChaineCar = "voici les données à envoyer" ;
Byte [] sendData = ChaineCar.getbyte() ;
DatagramPacket packet= New DatagramPacket(senddata, sendData.lenghth,
adresse, 2000);

Les méthodes :

La méthode getAddress et setAddress :

● public inetaddress getAddress()


● public void setAddress (Inetaddress Iaddr)

Ces deux méthodes permettent de manipuler l'adresse IP d‛un datagramPacket. L‛une (la
première) sert à récupérer et l‛autre à positionner (c.à.d donner une nouvelle valeur à) l'adresse
IP à laquelle, les données en paquet, doivent être envoyées (si le datagrapPacket est utilisé pour
l‛émission) ou depuis laquelle elles étaient envoyées (si le datagramPacket est utilisé pour
l‛émission).

Les méthodes getport et setport :

● public int getport()


● publuc void setport( int port)

La première méthode permet de récupérer et l'autre de fixer le numéro de port du programme


vers lequel, les données en paquet, doivent être envoyées (si le datagrapPacket est utilisé pour
l‛émission) ou depuis lequel elles étaient envoyées (si le datagramPacket est utilisé pour la
reception).

Les méthodes getData et setData :

● public byte[] getData()


● public void setData (byte[] buf)

La première méthode sert à lire les données du datagramPacket (reçues ou à envoyer), et la


deuxième définit, pour un datagramPacket, les données à envoyer (elle permet aussi de modifier
les données préalablement définies).
NB : Il n‛est pas difficile de remarquer qu‛à travers ces deux méthodes, pour répondre à un
programme à partir duquel on a reçu des données à travers un datagramPacket D, on a qu‛à
remplacer (à travers setData) les données reçues du datagramPacket D par les données à envoyer
et l‛utiliser pour répondre plutôt que d‛en définir un nouveau. Nous allons voir de telles
manipulations dans les exemples suivants.

Les méthodes getlegth et setlengt

● public int getlength( )


● public void setlength (int length)

La première méthode sert à retourner la longueur en octets des données stockées dans le
DatagramPacket (cette longueur peut être inférieure à la taille du tampon de données du
DatagramPacket) et la deuxième permet de fixer cette longueur pour les paquets destinés à
l'envoi.

3.2 La classe java.net.DatagramSocket

Alors que la classe précédente permet la préparation de l‛envoi et de la réception de données à


travers une communication orientée sans connexion (UDP), c‛est la classe java.net.
DatagramSocket qui permet d‛effectuer cette la communication.

Les constructeurs :

Cette classe possède trois constructeurs d'objet :

public DatagramSocket() throws Socketexeption

Ce constructeur permet la création de socket capable de se connecter sur n'importe quel port
local disponible.

public Datagramsocket ( int port) throws Socketexeption

Les objets créés par ce constructeur sont des sockets datagramme qui seront attaché sur le port
spécifique indiqué par son paramètre d'entrée

public DatagramSocket( int port, InetAddress Iaddr) throws SocketExeption

En plus du numéro de port, ce constructeur permet d'indiquer pour les objets créés l'adresse IP
sur laquelle ils seront attachés. Ce dernier constructeur est utilisé lorsque l‛on dispose de
plusieurs adresses IP pour le même hôte (plusieurs cartes réseau par exemple).
NB : Notez que pour pouvoir communiquer à travers UDP : Pour chaque message à communiquer le
programme qui veut le faire doit : (1) spécifier le destinataire (pour que le protocole puisse lui
délivrer les données) et peut être amené à : (2) s‛identifier lui-même en s‛attachant au port sur
lequel il veut recevoir les données et l‛adresse IP s‛il y en a plusieurs (cas d‛un serveur par
exemple). La première tâche est faite via la classe DatagramPacket (nous avons vu en haut que
les informations d‛adressage dans un Datagrampacket concernent toujours le programme distant).
La deuxième tâche est réalisée à travers la classe DatagramSocket.

Les méthodes :

Les méthodes d'échange de données :

● public void send ( DatagramPacket d) throws IOExeption


● Public void receive (DatagramPacket d) throws IOExeption

La méthode send permet l'envoi du DatagramPacket indiqué dans son paramètre. Ce


DatagramPacket doit avoir une destination configurée préalablement. La méthode receive
récupère les données reçues et les met dans le DatagramPacket indiqué par son paramètre. Elle
positionne aussi les informations d‛adressage de ce DatagramPacket par la valeur de l‛adresse IP
et du port de l‛émetteur.

Les méthodes d ‛ information:

● public InetAddress getLocalAddress ()


● public int getLocalPort()

La première méthode récupère l'adresse IP sur laquelle est attachée la socket invoquée et la
deuxième permet d'en récupérer le port.

Les méthodes de fixation et de


récupération de temps de
temporisation de receive :

● public void setSoTimeout (int timeout) throws SocketExeption


● public int getSoTimeout()throws SocketExeption

Sachant que la méthode receive() est bloquante la classe java.net.DatagramSocket offre ces
méthodes permettant l'une de fixer (via son paramètre) et l'autre de retourner la durée (en
milliseconde)de blocage de la méthode receive(), en attente des données.

Méthode pour activer/désactiver


l ‛ attachement restreint d ‛ une
DatagramSocket :
Il est possible de restreindre l‛attachement d‛une socket datagramme à un destinataire précis.
Dans ce cas, les DatagramPacket émis sur la socket seront toujours pour l'adresse spécifiée. Cet
attachement (restreint) simplifie l'envoi d'une série de DatagramPacket (il n'est plus nécessaire
de spécifier l'adresse de destination pour chacun d'entre eux) et accélère les contrôles de
sécurité. Deux méthodes sont offertes par la classe DataGramSocket, l‛une pour activer un tel
attachement : connect et autre pour le désactiver ce type d‛attachement « déconnexion »
enlève l'association (la socket redevient disponible comme dans l'état initial).

● public void connect(InetAddress address, int port)


● public void disconnect()

NB : l‛utilisation du mot connexion (connect) pour nommer cette méthode signifie attachement et
non pas connexion au sens propre du terme.

La méthode de fermeture de socket :

public void close()

Cette méthode sert à fermer la DatagramSocket invoquée.

3.3 Comment établir une communication orientée sans connexion entre deux
programmes ?

Répondre à cette question revient à répondre aux deux questions suivantes :

Q1 : Que doit faire un programme qui veut recevoir des données ?

R1 : Pour qu‛un programme puisse accéder aux données qui lui sont envoyé, par l‛interlocuteur
distant, il doit d‛abord attacher une socket à un port local en utilisant un constructeur de
DatagramSocket. Il doit aussi, créer un objet DatagramPacket D qui va servir de récipient pour
les données à recevoir. Une fois ces tâches faites, il appelle la méthode DatagramSocket.receive
avec comme paramètre le DatagramPacket D. Cette méthode remplira les différents champs
de D. Le champ data par les données reçues, les champs addresse
IP et port par les valeurs correspondantes à l‛émetteur distant. Le code
commenté suivant illustre un tel comportement. Il s‛agit d‛un programme qui reçoit (infiniment)
des données et les affiche ainsi que leur origine.
import java.awt.*;
import java.net.*;
public class ReceptionSC
{
public static void main(String args[])
{
// Créer un tampon pour la réception
byte[] buffer = new byte[1024];
// Créer un DatagramPacket pour la réception
DatagramPacket D = new DatagramPacket(buffer, buffer.length);
// Créer une DatagraamSocket pour écouter et recevoir les données sur le port 1500
try
{
DatagramSocket socket = new DatagramSocket(1500);
// Boucler infiniment pour recevoir des données
while(true)
{
// Attendre un nouveau packet
try
{
System.out.println("Je suis en attente de reception sur le port "+socket.
getLocalPort());
socket.receive(D);
}
catch(Exception exc)
{
System.out.println("Error! - " + exc.toString());
}
// Extraire les données du Datgrampacket D
String ChaineReçue = new String(buffer, 0, 0,D.getLength());
// Récupérer l'origine du packet
InetAddress OrigineAdresse = D. getAddress();
int port=D.getPort();
// Afficher la chaîne reçue et son origine
System.out.println("J'ai reçus " +ChaineReçue+" de la part de "+
OrigineAdresse.getHostAddress() +" ;" +port);
}
}
catch(Exception exc)
{
System.out.println("Error! - " + exc.toString());
}
}
}
Code 5 : Programme de réception orienté sans connexion (ReceptionSC.java)

Q2 : Que doit faire un programme qui veut émettre des données ?

R2 : Pour qu‛un programme puisse envoyer des données dans le mode sans connexion, il doit créer
un DatagramPacket D, et positionner ces différents champs. Cela signifie qu‛il doit affecter les
données à envoyer au champ Data, et l‛adresse IP et le port du programme destinataire aux
champs (Ip address, port) de D. Une fois le DatagramPacket D prêt à l‛émission, le programme
doit créer une socket en utilisant un constructeur de DatagramSocket. Et c‛est via la méthode
DatagramSocket.send() avec comme paramètre le Datgrampacket D, que l‛émission est réalisée.
Le code suivant illustre un tel comportement. Il s‛agit d‛un programme qui envoi des salutations
("Bonne année 2007") à un programme sur l‛hôte : HoteDestination dont
le numéro de port est 1500.

import java.net.*;
import java.io.*;
public class EmissionSC
{
// L'adresse Ip de l'hôte serveur.
//Ici, nous avons choisis le même hôte du client pour faciliter le test sur machine isolée
public static final String HoteDistination="127.0.0.1";
public static void main (String args[])
{
try
{
// Préparation du message à envoyer et sa conversion au format byte[]
int année = 2007;
String message= " Bonne année"+année;
// Conversion
int Longueurmessage = message.length();
byte[] messageFinale = new byte[Longueurmessage];
messageFinale = message.getBytes();
// Création d'un datagramPacket contenant notre message
DatagramPacket packet = new DatagramPacket(messageFinale, Longueurmessage );
// Récupération de l'objet InetAddress correspondent à l'hôte destination (ici l'hôte
locale)
InetAddress adresseDistante = InetAddress.getByName(HoteDistination);
// Positionnement des champs adresse et port du DatagramPacket
packet.setAddress (adresseDistante);
packet.setPort (1500);
// Création d'une socket datagram attachée à n'import quel port disponible
DatagramSocket socket = new DatagramSocket();
// Affichage du port affecté à notre socket par l'implémentation
System.out.println ("vous êtes attaché au port local " + socket.getLocalPort());
// Emission du datagramPacket
socket.send (packet);
System.out.println ("le message <<Bonne année 2007>> est émis.");
}
catch (IOException ioe)
{
System.err.println ("Error - " + ioe);
}
}
}

Code 6 : Programme d‛émission orienté sans connexion (EmissionSC.java)

Note : Pour tester le comportement des deux programmes précédents (EmissionSC.java et


ReceptionSC.java) , il suffit que la valeur de HoteDestination dans EmissionSC.java soit égale à
l‛adresse de l‛hôte exécutant ReceptionSC.java. Affecter à HoteDestination la valeur (127.0.0.1)
permet leur test sur la même machine.

3.4 Exercice : Le service Echo

Echo est, pratiquement, un service de diagnostique basé sur UDP qui opère de la manière suivante
(RFC 862) :

1. Les clients se mettent à envoyer des données au serveur.

2. Le serveur retourne toute chose qu‛il reçoit au client émetteur.

Q : En se basant sur les deux exemples précédents, développez en java une version simplifiée de
ce service (codes client et serveur).

Indices :

Le client se comporte de la manière suivante :

1. Lire à partir du clavier.


2. Ecrire sur un DatagramPcket et configurer pour l‛envoi au serveurEcho.
3. Lire le retour (l‛echo) du serveur sur un DatagramPacket configuré pour la réception.
4. Afficher la chaîne retournée à l‛écran

Le serveur Echo boucle indéfiniment pour servir les clients successivement. Dans chaque itération
il accompli les tâches suivantes :

1. Créer un DatagramPacket pour la lecture des données en entrée


2. Recevoir dans le DatagramPacket crée
3. Extraire les données du Datgrampacket
4. Retourner les données reçues à l'émetteur

Solution

import java.net.*;
import java.io.*;
public class ServeurEcho
{
// Définition du port UDP auquel le service est attaché
public static final int SERVICE_PORT = 2007;
// Prendre une taille assez large, pour le tampon, qui suffira normalement pour
n'importe quel client
public static final int BUFTAILLE = 4096;
// Définition de la socket qui sera utilisée pour l'émission et la réception
private DatagramSocket socket;
public ServeurEcho ()
{
try
{
// Attachement de la socket à un port UDP pour écouter les données en entrée
socket = new DatagramSocket( SERVICE_PORT );
System.out.println ("Le serveur est actif sur le port " +socket.getLocalPort() );
}
catch (Exception e)
{
System.err.println ("Unable to bind port");
}
}
public void serviceClients()
{
// Création d'un tampon assez large pour les paquets de données en entrée.
byte[] buffer = new byte[BUFTAILLE];
for (;;)
{
try
{
//Créer un DatagramPacket pour la lecture des paquets de données en entrée
DatagramPacket packet = new DatagramPacket (buffer, BUFTAILLE);
// Réception des paquets de données en entrée
System.out.println ("Le serveur est en attente de réception de données sur
le port : "+socket.getLocalPort() );
socket.receive(packet);
// Extraire les données du Datgrampacket Packet
String MessageReçu = new String ( buffer, 0, 0, packet.getLength());
System.out.println ("Un paquet dont le contenu est : "+ MessageReçu + "
est reçu de la part de: " +packet.getAddress() + ":" + packet.getPort() );
// Renvoi des données reçues vers l'émetteur. Nous utilisons ici le même objet
// datagrampacket puisque l'adresse et le port distant sont déjà bien positionnée
// et aussi les données à retourner qui sont les même pour le service Echo
socket.send(packet);
}
catch (IOException ioe)
{
System.err.println ("Error : " + ioe);
}
}
}
public static void main(String args[])
{
ServeurEcho serveur = new ServeurEcho();
serveur.serviceClients();
}
}

Code 7 : Serveur Echo orienté sans connexion (ServeurEcho.java)

import java.net.*;
import java.io.*;
public class EchoClient
{
// Le port auquel le service à demander est attaché
public static final int SERVICE_PORT = 2007;
// L'adresse Ip de l'hôte serveur.
//Ici, nous avons choisis le même hôte du client pour faciliter le test sur
machine isolée
public static final String HoteServeur="127.0.0.1";
// La taille maximale de paquet de donnée
public static final int BUFSIZE = 256;
public static void main(String args[])
{
// Récupérer l'objet InetAddress correspondent au nom de l'hôte serveur
InetAddress addr = null;
try
{
addr = InetAddress.getByName(HoteServeur);
}
catch (UnknownHostException uhe)
{
System.err.println ("impossible de trouver le nom de l‛hôte ");
return;
}
try
{
// Création d'une socket datagram attachée à n'import quel port disponible
DatagramSocket socket = new DatagramSocket();
// Fixer le temps d'attente en lecture à deux seconds en positionnant la
valeur de //Timeout
socket.setSoTimeout (2 * 1000);
BufferedReader in = new BufferedReader (new InputStreamReader
(System.in));
String line;
System.out.print ("vous pouvez commencer le test du service Echo
sur le poste" +HoteServeur+": ");
while(true)
{
line="";
try
{
line = in.readLine();
}
catch (IOException e)
{
System.err.println(e.getMessage());
}
// Préparer le message à l'envoi en le translatant au format byte[]
char[] TableauC = line.toCharArray();
byte[] TamponEmi= new byte[TableauC.length];
for (int offset = 0; offset < TableauC.length ; offset++)
{
TamponEmi[offset] = (byte) TableauC [offset];
}
// Création du DatagramPacket à envoyer au serveur
DatagramPacket PacketEmi = new DatagramPacket(TamponEmi,
TableauC.length, addr, SERVICE_PORT);
System.out.println ("Envoi du message à " + HoteServeur);
// Envoi du DatagramPacket i
socket.send (PacketEmi);
System.out.print ("En attente du retour.... ");
// Création d'un DatagramPacket pour la réception de l'écho
byte[] TamponRec= new byte[BUFSIZE];
DatagramPacket PacketRec = new DatagramPacket(TamponRec,
BUFSIZE);
// Declaration d'un drapeau timeout pour la gestion collective de toutes
// les exceptions possibles durent l'attente de réception des paquets
boolean timeout = false;
try
{
socket.receive (PacketRec);
}
catch (InterruptedIOException ioe)
{
timeout = true;
}
if (!timeout) // pas d'erreurs
{
System.out.println ("écho reçu");
// Extraire les données du Datgrampacket receivePacket
String MessageReçu = new String (TamponRec, 0, 0, PacketRec.
getLength());
// Afficher le message reçu
System.out.println(" Le serveur à retourné: " +
MessageReçu);
}
else // erreur
{
System.out.println ("massage perdu !");
}
}
}
catch (IOException ioe)
{
System.err.println ("Socket error " + ioe);
}
}
}
Code 8 : Client Echo orienté sans connexion (EchoClient.java)

Exercice 2 : Utilisez les méthodes setData et getData pour le remplissages et l‛extraction


des données des datagramPacket manipulés dans chacun des programmes (code5, 6, 7et 8).

Vous aimerez peut-être aussi