Vous êtes sur la page 1sur 16

Langage Java Communication Réseau

SOMMAIRE
1 Communication réseau .................................................................................................. 2
1.1. Adresses Internet .................................................................................................... 2
1.2. Java et protocole UDP ............................................................................................ 3
1.2.1 La classe DatagramPacket ................................................................................ 3
1.2.2 La classe DatagramSocket................................................................................ 4
1.3. Java et protocole TCP ............................................................................................. 6
1.3.1 La classe Socket ............................................................................................... 6
1.3.2 La classe ServerSocket ..................................................................................... 9
1.4. Les classes URL et URLConnection .................................................................... 10
1.4.1 La classe URL ................................................................................................ 10
1.4.2 La classe URLConnection .............................................................................. 11
1.5. Remote Method Invocation (RMI) ....................................................................... 12
1.5.1 Définition d’interface ..................................................................................... 13
1.5.2 Implémentation de l’interface par une classe ................................................. 13
1.5.3 Lancer l’application Serveur ........................................................................... 14
1.5.4 Création et lancement de l’application Cliente ............................................... 15
1.6. Exercices ............................................................................................................... 16

Formateurs: ASSALE Adjé & KOUAME Appoh 1/16 INP-HB


Langage Java Communication Réseau

LANGAGE JAVA

1 Communication réseau

Le paquetage java.net offre les moyens de communications entre machines à


travers les réseaux, et notamment à travers Internet.

1.1. Adresses Internet

La classe InetAddress permet de manipuler les adresses Internet des machines


connectées sur le réseau.
Cette classe ne dispose pas de constructeur ; il est nécessaire d’utiliser les
méthodes des classes pour obtenir une instance :

• public static InetAddress getLocalHost() throws


UnknownHostException : retourne un objet contenant l’adresse Internet
de la machine
• public static synchronized InetAddress getByName(String host_name)
throws UnknownHostException : retourne un objet contenant l’adresse
Internet d la machine dont le nom est passé en paramètre
• public static synchronized InetAddress[] getAllByName(String
host_name) throws UnknownHostException : retourne un tableau
d’objets contenant l’ensemble des adresses Internet de la machine qui
répond au nom passé en paramètre.

Les méthodes applicables à un objet de cette classe sont :

• public String getHostName() : retourne le nom de la machine dont


l’adresse est stockée dans l’objet.
• public byte[] getAddress() : retourne l’adresse Internet stockée dans
l’objet sous forme d’un tableau de 4 octets dans l’ordre réseau
• public StringtoString() : retourne une chaîne de caractères qui liste le
nom de la machine et son adresse.

Exemple :

InetAddress adresseLocale = InetAdress.getLocalHost() ;


InetAddress adresseServeur = InetAdress.getByName("www.assale.com") ;

Formateurs: ASSALE Adjé & KOUAME Appoh 2/16 INP-HB


Langage Java Communication Réseau

1.2. Java et protocole UDP

Ils permettent des communications de bas niveau. Il s’agit de transmissions de


paquets individuels, en mode non connecté. Ces transmissions sont peu fiables :
Elles ne garantissent pas la réception des paquets et n’assurent pas que l’ordre
d’arrivée soit le même que l’ordre d’émission.
Deux classes sont nécessaires pour effectuer une telle communication :

1.2.1 La classe DatagramPacket

Elle 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 existent, 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ée 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() : tourne les données stockées dans
le paquet
• public synchronized int getLength() : tourne 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

Formateurs: ASSALE Adjé & KOUAME Appoh 3/16 INP-HB


Langage Java Communication Réseau

• public synchronized void setLength(int ilength) : modifie ou affecte la


taille de la zone contenant les données.

1.2.2 La classe DatagramSocket

Avant toute communication en mode UDP, il est nécessaire de créer une socket
aussi bien du coté client que du coté serveur. On utilise pour cela la classe
DatagramSocket qui propose trois constructeurs :

• pubic 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 iaddr) 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 connaît pas préalablement la taille.

Il est possible de spécifier un délai d'attente maximal en réception. Pour cela, il


faut positionner une variable de timeout sur la socket au moyen de la méthode :

Formateurs: ASSALE Adjé & KOUAME Appoh 4/16 INP-HB


Langage Java Communication Réseau

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.

Exemple :

Dans cet exemple nous créons deux classes :

• une classe ServeurEcho qui attend une chaîne de caractères et la retourne


• une classe ClientEcho qui envoie une chaîne de caractères, attend que le
serveur la lui retourne et l'affiche.

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

class ServeurEcho
{ final static int port =
8532; final static int taille =
1024;
final static byte buffer[] = new byte[taille];

public static void main(String argv[]) throws Exception


{
DatagramSocket socket = new DatagramSocket(port);
while(true)
{
DatagramPacket data = new DatagramPacket(buffer,buffer.length);
socket.receive(data);
System.out.println(data.getAddress());
socket.send(data);
}
}
}

Formateurs: ASSALE Adjé & KOUAME Appoh 5/16 INP-HB


Langage Java Communication Réseau

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

public class ClientEcho


{
final static int taille = 1024;
final static byte buffer[] = new byte[taille];

public static void main(String argv[]) throws Exception


{
InetAddress serveur = InetAddress.getByName(argv[0]);
int length = argv[1].length(); byte
buffer[] = argv[1].getBytes();
DatagramPacket dataSent = new
DatagramPacket(buffer,length,serveur,ServeurEcho.port);
DatagramSocket socket = new DatagramSocket();

socket.send(dataSent);

DatagramPacket dataRecieved = new DatagramPacket(new


byte[length],length); socket.receive(dataRecieved);
System.out.println("Data recieved : " + new String(dataRecieved.getData()));
System.out.println("From : " + dataRecieved.getAddress() + ":" +
dataRecieved.getPort());
}
}

1.3. Java et protocole TCP

L'API utilisée pour accéder au protocole TCP se décompose en deux classes, une
utilisée par les clients et l'autre par les serveurs.

1.3.1 La classe Socket

La classe Socket est utilisée par les clients TCP.

Pour créer un objet de la classe Socket, il est nécessaire d'utiliser un des


constructeurs suivants :

Formateurs: ASSALE Adjé & KOUAME Appoh 6/16 INP-HB


Langage Java Communication Réseau

• public Socket (String machine, int port) throws UnknownHostException,


IOException
• public Socket (InetAddress adresse, int port) throws
UnknownHostException, IOException
• public Socket(String machine, int port, InetAddress local, int portLocal)
throws IOException
• public Socket(InetAddress adresse, int port, InetAddress local, int
portLocal) throws IOException

La création d'un objet Socket entraîne la création d'un point de connexion (la
socket) et la connexion vers une autre socket (le serveur). L'adresse du serveur est
composée de l'adresse d'une machine (sous forme d'un nom ou d'un objet de la
classe InetAddress) et d'un numéro de port.

L'adresse locale et le port local peuvent également être spécifiés. Par défaut,
l'appel au constructeur est bloquant tant que la connexion TCP n'est pas établie.

Une fois la connexion établie, il est possible de récupérer le flux d'entrée et le flux
de sortie de la connexion TCP vers le serveur au moyen des méthodes :

• public InputStream getInputStream () throws IOException


• public OutputStream getOutputStream () throws IOException

Il est alors possible d'échanger des données avec le serveur au moyen de toutes les
primitives de lecture et d'écriture des différentes classes du package java.io.

Par défaut les primitives de lecture, tel que read(), sont bloquantes tant que rien
n'est lisible sur le flux. La primitive suivante permet de définir un temps maximal
d'attente :

public synchronized void setSoTimeout(int timeout) throws SocketException

Une fois la connexion terminée il est très important de fermer le flux d'entrée et le
flux de sortie, mais aussi la socket au moyen de la méthode :

public synchronized void close() throws IOException

Par défaut cette primitive n'est pas bloquante mais la socket reste ouverte tant qu'il
reste des paquets à envoyer (en particulier le datagramme FIN). La primitive
suivante permet de définir un temps maximum d'attente avant de vraiment fermer
la socket.

public void setSoLinger(boolean on, int val) throws SocketException

Formateurs: ASSALE Adjé & KOUAME Appoh 7/16 INP-HB


Langage Java Communication Réseau

Par défaut, les implémentations du protocole TCP essaye de remplir au maximum


chaque paquet afin de diminuer le trafic réseau. Pour éviter ce comportement, ce
qui est souvent souhaitable dans le cas d'application interactives¸ une primitive
est disponible :

public void setTcpNoDelay(boolean on) throws SocketException D'autres

méthodes sont également disponibles et en particulier :

• public InetAddress getInetAddress ()


• public int getPort ()
• public InetAddress getLocalAddress ()
• public int getLocalPort ()
• int getLocalPort ()
• public int getSoLinger() throws SocketException
• public synchronized int getSoTimeout() throws SocketException
• public boolean getTcpNoDelay() throws SocketException

Remarque : une applet peut (pour des questions de sécurité) se connecter


uniquement à la machine depuis laquelle elle a été chargée.
Exemple :

package test;

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

public class SmtpClient {


public static void main(String argv[]) throws Exception {
sendmail("aaa","roussel@univ-mlv.fr");
}
static void sendmail(String message, String to) throws Exception {
Socket s = new Socket(InetAddress.getByName("pixel.univ-mlv.fr"),25);
PrintStream output = new PrintStream(s.getOutputStream());
output.println("HELO qqcvd.univ-mlv.fr\r"); output.println("MAIL
FROM: \r"); output.println("RCPT TO:<" + to + ">\r");
output.println("DATA\r"); output.println(message);
output.println("\r\n.\r");
}
}

Formateurs: ASSALE Adjé & KOUAME Appoh 8/16 INP-HB


Langage Java Communication Réseau

1.3.2 La classe ServerSocket

Cette classe est utilisée (comme son nom l'indique) pour créer une socket du coté
serveur.

La classe ServerSocket permet de créer un point de communication, sur un port


particulier, en attente de connexions en provenance de clients. Contrairement à la
classe Socket elle n'ouvre pas de connexion. Pour créer un tel objet, il faut utiliser
un des constructeurs suivants, où port correspond au port d'attente et count au
nombre maximum de connexions en attente, non encore acceptées.

• public ServerSocket(int port) throws IOException


• public ServerSocket(int port, int count)throws IOException
• public ServerSocket(int port,int count, InetAddress locale) throws
IOException

Une fois la socket créée, on attend les connexions de clients avec la méthode
bloquante :

• public Socket accept() throws IOException

Il est possible de spécifier un temps maximal d'attente. Pour cela il faut appeler la
méthode suivante avant l'appel à accept() :

public synchronized void setSoTimeout(int timeout) throws SocketException

La méthode accept() retourne un nouvel objet de la classe Socket qui est connecté
avec un client particulier, celui qui a demandé la connexion. Il est alors possible
de récupérer le flot d’entrée et de sortie comme pour la socket du client.

Exemple :

public class DaytimeServeur {


public static void main(String argv[]) throws Exception {
ServerSocket s = new ServerSocket(0);
System.out.println(s.getLocalPort()); while(true)
{
Socket serviceSocket = s.accept();
PrintStream output = new PrintStream(serviceSocket.getOutputStream());
output.println(new Date());
serviceSocket.close();
}
}

Formateurs: ASSALE Adjé & KOUAME Appoh 9/16 INP-HB


Langage Java Communication Réseau

}
D'autres méthodes de manipulation sont également disponibles :

• public void close() throws IOException


• public int getLocalPort()
• public InetAddress getInetAddress()
• public synchronized int getSoTimeout() throws IOException

1.4. Les classes URL et URLConnection

1.4.1 La classe URL

La classe URL permet de faire apparaître comme un fichier séquentiel de type


InputStream n’importe quelle ressource accessible sur le Web au moyen d’une
URL.

class URL { URL


(String url) ;
Socket (InetAddress adr, int port);
String getFile();
String getHoste();
InputStream openStream();
URLConnection openConnection();
}

Formateurs: ASSALE Adjé & KOUAME Appoh 10/16 INP-HB


Langage Java Communication Réseau

Une façon simple de l’utiliser est de créer un objet URL au moyen du constructeur
avec l’URL en paramètre, sous forme d’une chaîne de caractères de la forme :
http://..., puis d’utiliser la méthode openStream() pour obtenir un objet de type
InputStream qui permet de lire le contenu de cette url.

Exemple :

Le programme suivant lit au clavier un nom d’URL, supposé désigner un fichier


texte, et l’imprime sur le terminal :

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

public class TestUrl {


public static void main(String arg[]) {
System.out.println(“url :”);
String chaineUrl = Lecture.chaine(“\n”);
try{
URL url = new URL(chaineUrl);
InputStream in =url.openStream();
int k= in.read();
while (k!=-1) {System.out.print((char) k); k= in.read();}
}
catch(EOFException e) {System.out.println("\n termine");} catch(Exception e)
{System.out.println("erreur"); System.exit(0);}
}
}

La méthode openConnection() rend un objet de type URLConnection qui permet


des accès plus élaborés.

1.4.2 La classe URLConnection

URLConnection est une classe abstraite qui propose une interface simple pour
manipuler les entêtes et le contenu d'une URL, d'une façon indépendante du
protocole. Un objet de cette classe est construit par l'appel à la méthode
openConnection() sur un objet de la classe URL.

La première chose à faire consiste à spécifier les entêtes de requêtes au moyen


de la méthode suivante : public void setRequestProperty(String key, String
value)

Formateurs: ASSALE Adjé & KOUAME Appoh 11/16 INP-HB


Langage Java Communication Réseau

D'autres méthodes raccourcis sont disponibles : public long getIfModifiedSince()


...
Il faut ensuite ouvrir la connexion : public abstract void connect() throws
IOException

Il est alors possible de récupérer chacune des entêtes par une des méthodes
suivantes :

• public String getHeaderField(String name) : retourne l'entête dont le nom


est passé en paramètre si elle est présente et null sinon.
• public int getHeaderFieldInt(String name, int default)
• public long getHeaderFieldDate(String name,long default)
• public String getHeaderFieldKey(int n)
• public String getHeaderField(int n)

Les méthodes suivantes sont des raccourcis pour les entêtes les plus courantes :

• public int getContentLength ()


• public String getContentType ()
• public long getDate ()

Pour récupérer le contenu du document il suffit d'utiliser la méthode : public


Object getContent() throws IOException

D'autres inter-action de plus bas niveau sont également possible en récupérant les
flux d'entrée et de sortie sur la connexion.

public InputStream getInputStream() throws IOException public

OutputStream getOutputStream() throws IOException Exemple :

int len = connexion.getContentLength();


InputStream input = connexion.getInputStream();
for(;len != 0; len--)
System.out((char)input.read());

1.5. Remote Method Invocation (RMI)

Cette technologie permet de manipuler des objets sur des machines distantes
(objets distants) de la même que des objets sur la machine locale. Cette méthode
se met en œuvre à travers les étapes suivantes :
- Définir des interfaces pour les objets distants

Formateurs: ASSALE Adjé & KOUAME Appoh 12/16 INP-HB


Langage Java Communication Réseau

- Implémenter l’interface distante


- Lancer l’application Serveur
- Créer et lancer l’application Cliente

Le problème : soit à mettre en place une application distante contenant des


méthodes pgcd(int a, int b) et fibo(int n) qui permettent de calculer respectivement
le pgcd de 2 entiers et le nième terme de la suite de fibonacci. L’application cliente
accédera à ces méthodes via le réseau.

1.5.1 Définition d’interface

La définition d’interface pour les objets distants nécessite le respect des directives
suivantes :
- L’interface doit être publique
- Elle doit hériter de java.rmi.Remote
- Chaque méthode doit déclarer java.rmi.RemoteException dans sa
clause throws en plus des autres exceptions spécifiques à l’application Par
exemple :
import java.rmi.* ;
public interface Calculer extends Remote{ public int
pgcd(int a, int b)throws RemoteException ; public int
fibo(int n)throws RemoteException;
}

1.5.2 Implémentation de l’interface par une classe

On a deux possibilités : soit on crée une classe qui implémente l’interface et


ensuite on définit une application serveur (contenant la méthode main) qui utilise
cette classe, soit on crée directement une application serveur qui implémente
l’interface. Dans les deux cas, les directives suivantes sont à respecter :
- La classe hérite de UnicastRemoteObject et implémente l’interface
- La classe peut avoir d’autres méthodes mais elles ne seront pas disponibles
pour le client
- Il faut définir explicitement un constructeur de cet objet, même si c’est
seulement un constructeur par défaut appelant la classe
- Dès fois, on peut implémenter l’interface Serializable

Dans notre cas on obtient le code suivant :


import java.rmi.*;
import java.rmi.server.*;

Formateurs: ASSALE Adjé & KOUAME Appoh 13/16 INP-HB


Langage Java Communication Réseau

public class Calcul extends UnicastRemoteObject implements Calculer {


private int a;
private int b; private
int n;
public Calcul()throws RemoteException {
super();
}
public int pgcd(int a, int b)throws RemoteException{
int r=a%b; while(r!=0)
{
a=b;
b=r;
r=a%b;
}
return b;
}
public int fibo(int n) throws RemoteException{
if(n==1 || n==0)
return 1;
else
return (fibo(n-1)+fibo(n-2));
}
}

1.5.3 Lancer l’application Serveur

On définir d’abord une application serveur, si cela n’a pas été fait dans le
paragraphe précédent. Cette application serveur doit enregistrer une instance de
la classe implémentant notre interface par Naming.rebind ("nom_acces_objet",
instance_classe) ; Dans notre cas on a ceci : import java.rmi.*; import
java.rmi.server.*;
import java.net.*;

public class ServeurCalcul {


public static void main(String [] args) {
try{
//création d'un objet calcul
Calcul cal = new Calcul();
//enregistrement de l'instance de Calcul
Naming.rebind("lecalcul",cal);

Formateurs: ASSALE Adjé & KOUAME Appoh 14/16 INP-HB


Langage Java Communication Réseau

} catch(Exception e){ e.printStackTrace();}


}

Une fois notre application serveur compilée, avant de la lancer, on lance le


rmiregistry par : start rmiregistry
Ensuite on lance notre application serveur par : java nom_appli Dans
notre cas on a :
>start rmiregistry
>java ServeurCalcul

N.B. : les chemins d’accès aux classes à charger doivent être définis dans la
variable d’environnement CLASSPATH

1.5.4 Création et lancement de l’application Cliente

On crée une application cliente qui fera appel aux méthodes de notre objet ; de ce
fait, elle contiendra une référence à notre objet de la manière suivante:
(interface_objet) Naming.lookup (url) ;
l’URL est définie par : "rmi://serveur/nom_acces_objet"
Pour le lancement de l’application, le fichier class de l’interface doit être
disponible (dans le même répertoire que la classe de l’application cliente). Dans
notre exemple, le client peut être ceci : import java.rmi.*;

public class ClientCalcul {


public static void main(String []args) {
String serveur;
Calculer cal=null;
//récupération d'une référence sur Calcul
try{
System.out.println("Entrer le nom de la machine serveur"); serveur=new
String(Lire.S());
System.out.println("Entrer le nom de l'objet serveur");
String objet=new String(Lire.S());
String url= new String("rmi://"+serveur+"/"+objet);
System.out.println("recherche de l'objet Calculer");
cal= (Calculer)Naming.lookup(url);
}catch(Exception e){
System.out.println("Erreur à l'accès de Calculer "+e);
}
System.out.println("Entrer 1 entier");
int a=Lire.i();

Formateurs: ASSALE Adjé & KOUAME Appoh 15/16 INP-HB


Langage Java Communication Réseau

System.out.println("Entrer 1 entier");
int b=Lire.i();
try{
System.out.println("leur pgcd est: "+cal.pgcd(a,b));
} catch(Exception e){System.out.println("erreur de calcul");}
}
}

1.6. Exercices

Fiche de TD exercices 11, 12 et 13

Formateurs: ASSALE Adjé & KOUAME Appoh 16/16 INP-HB

Vous aimerez peut-être aussi