Vous êtes sur la page 1sur 33

ESGIS L3/IIRT Semestre 5

PROGRAMMATION RÉSEAU EN JAVA


PARTIE 2 – LA PROGRAMMATION RÉSEAU EN JAVA
Introduction
Les réseaux informatiques sont devenus incontournables dans ce monde en perpétuelle
évolution. Ils constituent le socle qui garantit le bon fonctionnement de toute organisation dont
ils influencent l’activité. Les réseaux offrent divers services notamment la messagerie, les
forums de discussions, les transactions bancaires, la navigation sur internet, etc.
Le langage Java a été conçu par SUN, une société donc l’activité est fortement tournée vers le
réseau et qui a mis au point plusieurs protocoles réseaux utilisés sur Internet (RPC, NFS, NIS).
Il peut donc paraître logique que ce langage soit tourné vers le réseau et notamment vers
Internet.
XIV- Réseaux : Notions de base
Un réseau informatique est constitué d’un ensemble d’ordinateurs et de périphériques
interconnectés. Un nœud du réseau qui correspond à un ordinateur est généralement appelé
hôte.
XIV.1. L’architecture Client / Serveur
Le mode de fonctionnement qu’un hôte établit avec un autre hôte qui fournit un service
quelconque est désigné par le terme Client / Serveur. Le processus de communication se déroule
comme suit :

 Le client lance une requête pour l’acquisition d’une ressource (Texte, Image, Son, Etc.) ;
 Le serveur exécute la requête (Lancement des scripts, Communication avec une base de
données, Etc.) ;
 Le résultat de la requête (la réponse) est renvoyé au client.

Dans les applications Client / Serveur, la communication se passe généralement entre deux
ordinateurs ; l’un des deux jouant le rôle de serveur (celui abritant la base de données de
l’application) et l’autre celui de client. Le serveur fournit quelques services (exécution des
requêtes de base de données par exemple), et le client est le consommateur de ces services
(affichage du résultat des requêtes dans le cas de notre exemple).
XIV.2. Le modèle OSI
OSI est un modèle théorique présentant la circulation des données dans un réseau. Il présente
très précisément la liaison qui existe entre deux nœuds successifs d’un réseau d’une manière
descendante et décomposée.
Il est décrit en sepr (7) couches : Application, Présentation, Session, Transport, Réseau, Liaison
et Physique.
Ce modèle a été mis au point par l’organisation internationale de normalisation (ISO) afin de
standardiser les communications entre ordinateurs.
XIV.3. Le modèle TCP/IP (Transmission Control Protocol/Internet Protocol)

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 1


ESGIS L3/IIRT Semestre 5

TCP/IP est l’architecture réseau la plus répandue dans le monde. Il est basé sur le modèle OSI.
On y trouve quatre (4) couches : Application, Transport, Réseau et Liaison. L’architecture
TCP/IP inclut de nombreux services d’application, des protocoles élaborés et complexes, sur
lesquels les applications distribuées peuvent s’appuyer.
TCP/IP contient l’ensemble des règles de communication sur Internet et se base sur la notion
d’adressage IP. De ce fait, chaque ordinateur du réseau se voit attribuer une adresse IP afin de
pouvoir acheminer des paquets de données. Les fonctions principales du TCP/IP sont les
suivantes :
 L’utilisation d’un système d’adresse ;
 Le fractionnement des messages en paquets ;
 L’acheminement des données par paquets à travers le réseau (routage) ;
 Le contrôle des erreurs de transmission de données ;
 Etc.
Le schéma suivant illustre les diverses couches TCP/IP où interviennent les différents
protocoles :

Lorsque vous écrivez un programme qui doit tourner sur un réseau, vous programmez au niveau
de la couche Application. Vous pouvez utiliser les classes du package java.net pour utiliser les
protocoles TCP et UDP pour le transport. Ces classes fournissent la communication
indépendamment des systèmes sur lesquels elles sont introduites. Cependant pour décider
quelle classe votre programme doit utiliser, vous avez besoin de comprendre la différence entre
les protocoles TCP et UDP.
XIV.4. Le protocole TCP (Transmission Control Protocol)
Lorsque deux applications veulent communiquer entre elles (dans le cas d’un appel
téléphonique par exemple), elles utilisent un support de transmission à travers lequel se font les
envois et les réceptions. Le TCP garantit l’envoi des données entre les deux applications. Ce
mode de communication est appelé Mode connecté.
TCP est un protocole qui permet une connexion de type point entre deux applications. C’est un
protocole fiable qui garantit la réception dans l’ordre d’envoi des données. Par contre, ce
protocole offre de moins bonnes performances gage de sa fiabilité.
En exploitant les ports, plusieurs applications peuvent utiliser TCP simultanément sur le même
ordinateur.
XIV.5. Le protocole UDP (User Datagram Protocol)
Le protocole UDP assure une communication non garantie entre deux applications sur un réseau
par envoi de paquets indépendants de données (appelés datagrams) d’une application à l’autre.

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 2


ESGIS L3/IIRT Semestre 5

A la manière de l’envoi de courrier par le service postal, l’ordre de la livraison n’est pas
important donc n’est pas non garantie. Chaque paquet est indépendant de l’autre. Ce mode de
communication est dit Mode non connecté.
Le protocole UDP offre de bonnes performances car il est très rapide par rapport à TCP, mais
ne garantit pas l’envoi des données dans l’ordre d’émission. Il est pratiquement réservé à des
taches peu importantes. Pour assurer les échanges, UDP utilise la notion de port ; ce qui permet
à plusieurs applications d’utiliser UDP sans que les échanges interfèrent les uns avec les autres.
UDP est utilisé dans de nombreux services tel que echo (port 7), DayTime (13), etc. et dans
plusieurs applications peer-to-peer (Ex. : Emule, Kazaa, etc.).
Une différence importante au niveau de l’utilisation des ports TCP et UDP est que le TCP
réserve pour chaque connexion une file d’attente de messages, au contraire de UDP qui associe
à chaque port sa propre file d’attente.
XIV.6. Le protocole IP (Internet Protocol)
Le protocole IP dans la couche réseau du TCP/IP du routage et du contrôle dans les réseaux
interconnectés. Il permet également l’échange de datagrammes (en mode non connecté), entre
des hôtes connectés à divers réseaux physiques. Le protocole IP est un protocole ouvert et
indépendant du système d’exploitation.
Des nœuds d’un réseau sont potentiellement reliés par plusieurs chemins. Chaque paquet suit
un chemin particulier pour atteindre sa destination, mais une succession de paquets provenant
d’un même bloc de données ne suivent pas forcément le même chemin. Pour programmer via
le protocole IP, on utilise le protocole TCP ou le protocole UDP.
XIV.7. Les ports
La liaison d’un ordinateur avec un réseau se fait par une connexion physique unique. Mais les
données qui passent par cette connexion sont utilisées par diverses applications (ou protocole).
Les ports sont utilisés pour distinguer les données propres à chaque processus.
A cause de la diversité des services fournis par un serveur, certains ports sont réservés à des
services bien spécifiés : http (80), FTP (21), SMTP (25), etc. ces ports sont appelés Well Known
Ports (WKP).
Chaque machine sous IP possède quelques 65 535 ports. De 1 à 1024 sont des ports réservés
aux services fondamentaux, de 1025 à 5000 sont disponibles aux utilisateurs.
XIV.8. Les Sockets

La notion de sockets a été introduite dans le système UNIX BSD. En effet, UNIX est un système
multi-tâches et multi-utilisateurs. Les processus peuvent coopérer entre eux. Différents outils
de communication inter-processus ont été développés: les IPC (Inter Process Communication).

La communication interprocess peut se faire à travers les signaux et les pipes. Mais tandis que
la version d'ATT était orientée gestion de ressources (sémaphores, messages, mémoire
partagée), l'université de Berkeley a développé une version orientée réseaux en implémentant
les protocoles Internet ARPA/DOD et en offrant l'interface des "Sockets".

Les Sockets forment une API (Application Program Interface): ils offrent aux programmeurs
une interface entre le programme d'application et les protocoles de communication. En aucun

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 3


ESGIS L3/IIRT Semestre 5

cas, les sockets ne forment une norme de communication ou une couche de protocole à l'instar
de TCP/IP.

Les sockets (prises de raccordement) forment un mécanisme de communication bidirectionnel


interprocessus dans un environnement distribué ce qui n'est pas le cas des autres outils tels que
les pipes. Ils permettent évidemment la communication interprocess à l'intérieur d'un même
système (sur une même machine ou à travers un réseau TCP/IP).

L'interface des "sockets" n'est pas liée à une pile de protocoles spécifique. Dans ce cours, nous
nous intéresserons, à l'utilisation des sockets dans le monde TCP/IP.

La notion de socket en tant que prise de raccordement vient d’une analogie avec le réseau
électrique et le réseau téléphonique :

Figure 1 : La métaphore des prises

Les sockets représentent donc d'une part une API c'est à dire un ensemble de primitives de
programmation et d'autre part les extrémités de la communication (notion de prise). La mise en
œuvre des sockets nécessite donc la connaissance des primitives ainsi que le modèle
client/serveur utilisé. C’est ce qui fera l’objet de ce cours.

Les sockets se situent dans la couche transport (protocole UDP ou TCP), elle-même utilisant
les services de la couche réseau.

Dans une communication, au moins 2 sockets sont utilisés. Chaque socket est identifié par une
adresse IP et un numéro de port.

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 4


ESGIS L3/IIRT Semestre 5

Figure 2 : Communication par Sockets

Les sockets représentent donc d'une part une API c'est à dire un ensemble de primitives de
programmation et d'autre part les extrémités de la communication (notion de prise). Les
extrémités de communication sont identifiées dans le monde TCP/IP par trois informations :
une adresse IP, le protocole utilisé (TCP ou UDP) et un numéro de port (entier sur 16 bits donc
de 0 à 65535. Etant donné que ces informations sont uniques dans l’Internet (les adresses IP
sont uniques et les numéros de ports sont uniques pour un protocole donné) ces trois
informations permettent d’identifier de façon unique une extrémité de communication (à
l’instar d’un numéro de téléphone dans un réseau téléphonique).

Pour maintenir l’unicité des numéros de port (par protocole) on les a répartis en trois catégories
:

- Les ports systèmes (appelés aussi ports bien connus – well known ports) de 0 à 1023 sont
réservés aux processus démarrés automatiquement par le système d’exploitation et
peuvent être déposés auprès de l’organisme IANA (Internet Assigned Numbers
Authority).
- Les ports utilisateurs (appelés aussi ports déposés – registered ports) de 1024 à 49151
sont disponibles pour les utilisateurs et peuvent eux aussi être déposés auprès de
l’organisme IANA.
- Les ports dynamiques (appelés aussi ports privés) de 49152 à 65535.

Le site web de IANA permet de connaître la liste des ports systèmes et utilisateurs assignés à
un protocole applicatif ou une application donnée (http://www.iana.org/assignments/port-
numbers). Il propose de plus deux formulaires permettant de déposer des numéros de ports
systèmes ou utilisateurs (http://www.iana.org/cgibin/sys-port-number.pl et
http://www.iana.org/cgi-bin/usr-port-number.pl ).

Pour les TPs il est recommandé d’utiliser les numéros de ports dynamiques.

En fonction du protocole transport utilisé les sockets vont fonctionner différemment. Nous
présenterons dans un premier temps les sockets utilisant le protocole TCP qui fonctionnent en
utilisant le modèle client/serveur et offrent une communication par flux. Les sockets utilisant
le protocole UDP seront ensuite présentés. Ils ont un fonctionnement beaucoup plus proche de

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 5


ESGIS L3/IIRT Semestre 5

ce qui se passe au niveau de la couche réseau (échange de paquets – appelés datagrammes dans
le monde TCP/IP – acheminés indépendamment). Les sockets UDP peuvent de plus être utilisés
pour une communication entre une application et un groupe de machine (diffusion plus ou
moins restreinte – broadcast ou multicast).

XIV.9. La diffusion

Le protocole IP a prévu de pouvoir envoyer des paquets à plusieurs machines sans faire la
duplication de ces paquets. Pour garantir la transmission des paquets par la diffusion, les
routeurs doivent accepter le passage de ces paquets, et les serveurs de diffusion doivent
posséder une adresse IP de classe D, c’est-à-dire un numéro compris entre 224.0.0.1 et
239.255.255.255 (toutes ces adresses dont déjà réservées).

Lorsqu’on diffuse un paquet, celui-ci a la possibilité de parcourir tout l’Internet. Pour éviter ce
long chemin, les paquets possèdent un champ de type entier appelé TTL (Time To Live), qui
est décrémenté à chaque passage dans les routeurs. Lorsque cette valeur passe à 0, le routeur
détruit le paquet et ne le diffuse pas. Dans le cas d’un paquet en diffusion, on doit explicitement
spécifier la valeur de ce champ :

 1 = le paquet reste dans le réseau local ;


 16 = le paquet reste dans la région ;
 127 = le paquet est envoyé dans le monde entier.

XIV.10. L’accès aux ressources via une URL

Une URL (Uniform Ressource Locator) ou localisateur de ressources uniforme, est une chaîne
de caractères qui désigne une ressource précise accessible par Internet ou Intranet. Une URL
est donc une référence à un objet dont le format dépend du protocole utilisé pour accéder à la
ressource.

XIV.10.1. Dans le cas du protocole HTTP, l’URL est de la forme :

http://<serveur>:<port>/<chemin>?<param1>&<param2>&...&<paramn>

Elle se compose du protocole http, d’une adresse IP ou du nom du serveur avec un numéro de
port (80 par défaut), d’un chemin d’accès à un fichier ou un nom de service et, éventuellement,
des paramètres sous la forme clé=valeur.

Exemple :

http://www.google.com/convert?value=100&src=miles&dest=kilometers

XIV.10.2. Dans le cas du protocole FTP, l’URL est de la forme :

ftp://<user>:<password>@<serveur>:<port>/<chemin>

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 6


ESGIS L3/IIRT Semestre 5

Où l’URL est composée d’un compte utilisateur et un mot de passe avec le nom du serveur
auquel on veut accéder. Le port par défaut du FTP est le port 21.

Exemple :

ftp://monusername:2024Ftp@monsite.com/docspersos

XIV.10.3. Dans le cas d’un e-mail, l’URL est de la forme :

mailto:<email>

Exemple :

mailto:tontonlawson@gmail.com

XIV.10.4. Dans le cas d’un fichier local, l’URL est de la forme :

file://<serveur>/<chemin>

Elle se compose de la désignation du serveur (non utilisé dans le cas du système de fichier local)
et du chemin absolu de la ressource.

Exemple :

file:///F:/LAWSON/COURS/ESGIS/Programmation%20r%C3%A9seau%20Java/Programma
tion%20r%C3%A9seau%20en%20JAVA%20_%20.PDF

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 7


ESGIS L3/IIRT Semestre 5

XV- Le langage JAVA et la programmation réseau

Depuis sa création, Java fournit une multitude de Classes et d’Interfaces destinées à la


programmation réseau, grâce à son API qui a été bien conçue et très riche d’une part, et d’autre
part, parce à son aptitude à traiter la plupart des interfaces, protocoles et plateformes.

Plusieurs domaines d’applications peuvent être programmés aisément avec Java :

 Navigation sur le Web (HTTP) ;


 Messagerie électronique (SMTP et POP) ;
 Conception de nouveaux protocoles ;
 Sécurité des communications (cryptage des messages, authentification, etc.) ;
 Recherche des hôtes et adressage (DNS) ;
 Transfert de fichiers (FTP) ;
 Déploiement à distance des applications multi-système (RMI : Remote Method
Invocation est une API Java permettant de manipuler des objets distants (c'est-à-dire un
objet instancié sur une autre machine virtuelle, éventuellement sur une autre machine
du réseau) de manière transparente pour l'utilisateur, c'est-à-dire de la même façon que
si l'objet était sur la machine virtuelle (JVM) de la machine locale.) ;
 Etc.

En plus de tout ça, notons que Java est le premier langage à fournir une bibliothèque riche,
puissant et multiplateforme qui couvre divers domaines comme ceux qui sont cités ci-dessus.

XV.1. La package java.net

Les classes et interfaces utiles au développement réseau en Java sont regroupés dans le package
java.net. Ces classes sont les suivantes :

 InetAddress, NetworkInterface : pour l’adressage IP ;


 Socket et ServerSocket pour le protocole TCP ;
 DatagramPacket, DatagramSocket et MulticastSocket : pour le protocole UDP ;
 URL, URLConnection, URLEncoder, etc. : pour la couche Application.

XV.1.1. Les adresses Internet (Adresses IP) et Java

Une machine (appelée aussi hôte ou host) est identifiée dans l’Internet par son adresse.
L’adresse IP d’une machine correspond à un numéro qui est unique dans le monde. Pour des
raisons mnémoniques, il est possible de donner un nom à une machine (ex : Toto, Garonne,
Mimosa, Etc.). Certains hôtes ont plusieurs noms. Ce nom est géré de façon hiérarchique par
le DNS (Domain Name System ou Système de Noms de Domaines).

L’adresse utilisée par la version actuelle du protocole IP (adresse IP), comporte deux champs:
le champ adresse réseau (Network) dans l’Internet et le champ adresse hôte (Host) dans le

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 8


ESGIS L3/IIRT Semestre 5

réseau. Sa taille est de 4 octets (32 bits). Elle est souvent donnée en notation décimale pointée
(ex: 127.95.35.54).

Comme l’adresse IP contient l’adresse réseau, une station changeant de réseau change
d’adresse. D’autre part, une station multi domiciliée (qui dispose de plusieurs interfaces réseau)
ou un routeur ont plusieurs adresses.

Il existe actuellement cinq classes d’adresses IP. Les trois premières permettent de gérer des
réseaux de tailles diverses. La classe D permet de gérer une communication multipoint (un
message est envoyé à plusieurs machines à la fois). La classe E est réservée et ne sera
probablement jamais utilisée puisqu’on devrait bientôt migrer vers la nouvelle version d’IP
IPv6 qui stockera les adresses IP dans 16 octets.

Figure 3 : Les classes d’adresses IP

XV.1.1.1. La classe InetAddress

La classe java.net.InetAddress permet de représenter les adresses IP. Chaque objet de cette
classe possède deux champs hostName et address contenant respectivement une chaîne de
caractère et un tableau d’octets.

Le champ hostName stocke le plus souvent le nom de l’hôte (www.esgis.org par exemple) et le
champ address l’adresse IP.

Cette classe ne possède pas de constructeurs publics. Pour créer un objet de type InetAddress il
faut donc utiliser l’une des méthodes statiques suivantes :

- public static InetAddress getByName (String nom_hote)


- public static InetAddress [ ] getAllByName (String nom_hote)

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 9


ESGIS L3/IIRT Semestre 5
- public static InetAddress getLocalHost ()

Méthode Rôle
Renvoie l’adresse Internet associée au nom
InetAddress getByName(String)
d’hôte passé en paramètre.
Renvoie un tableau des adresses Internet
InetAddress[] getAllByName(String)
associées au nom d’hôte passé en paramètre.
Renvoie l’adresse Internet de la machine
InetAddress getLocalHost()
locale.
Renvoie un tableau contenant les 4 octets de
Byte[] getAddress()
l’adresse Internet.
Renvoie l’adresse Internet sous la forme
String getHostAddress()
d’une chaîne de caractères.
String getHostName() Renvoie le nom du serveur.

a. public static InetAddress getByName (String nom_hote)

Cette méthode utilise le DNS pour renvoyer une instance de la classe InetAddress représentant
l'adresse Internet de la machine de nom nom_hote. Voici un exemple d’utilisation (en supposant
que la classe java.net.InetAddress a été précédemment importée) :

InetAddress adr = InetAddress.getByName("www.esgis.org");

Lorsque la recherche DNS n'aboutit pas, une exception UnknownHostException est levée.

b. public static InetAddress [ ] getAllByName (String nom_hote)

Cette méthode renvoie toutes les adresses Internet de la machine de nom nom_hote.

c. public static InetAddress getLocalHost ()

Renvoie une instance de la classe InetAddress représentant l'adresse Internet de la machine


locale. Très pratique pour tester sur une même machine les programmes client et serveur.
Equivalent à getByName (null) ou getByName ("localhost").

Autres méthodes :

d. public String getHostName ()

Renvoie le nom de la machine hôte, ou bien l'adresse IP si la machine n'a pas de nom.

e. public byte [] getAddress ()

Renvoie l'adresse IP stockée par une instance de la classe InetAddress sous la forme d'un
tableau d'octets rangés dans l'ordre standard du réseau (network byte order). Ainsi l'octet
d'indice 0 contient l'octet de poids fort de l'adresse.

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 10


ESGIS L3/IIRT Semestre 5

La longueur du tableau retourné est actuellement 4 dans la plupart des cas (IPv4) mais devrait
passer à 16 lorsque les adresses IP sur 128 bits auront cours (IPv6).

Méthodes surchargées

f. public int hashCode ()


g. public boolean equals (Object obj)
h. public String toString ()

Ces méthodes surchargent celles de la classe Object, pour renvoyer un code de hashing,
comparer un objet de classe InetAddress à un objet ou renvoyer une chaîne de caractères
décrivant une adresse Internet.

Remarque importante : la première méthode est directement utilisée par la classe InetAddress
qui contient une HashTable en membre statique. Ainsi, une adresse requise plusieurs fois sera
immédiatement extraite du cache et donc obtenue beaucoup plus rapidement que par l'envoi
d'une requête au serveur DNS.

Exemple :

Le programme suivant fournit l’adresse locale de la machine, l’adresse IP de l’ESGIS et les


adresse IP du serveur Yahoo.

Classe InetAddressSample.java :
package ga.esgis.l3iirtsrs.inet;

import java.net.InetAddress;

public class InetAddressSample {


public static void main(String[] args) {
try {
// Renvoie l'adresse de la machine locale
InetAddress adresseLocale = InetAddress.getLocalHost();
System.out.println("L'adresse IP de la machine locale : " +
adresseLocale.getHostName() + " : " + adresseLocale.getHostAddress());

// Renvoie l'adresse IP de ma machine via le reseau


InetAddress[] adresseServeurLocal = InetAddress.getAllByName
adresseLocale.getHostName());
System.out.println("Les adresses IP de ma machine via le reseau : ");
for(int i = 0; i < adresseServeurLocal.length; i++)
System.out.println(" " +
adresseServeurLocal[i].getHostAddress());
System.out.println();

// Renvoie l'adresse IP de l'ESGIS


InetAddress adresseServeurEsgis = InetAddress.getByName("esgis.org");
System.out.println("L'adresse IP de l'ESGIS Gabon est : " +
adresseServeurEsgis.getHostAddress());

System.out.println();
// Renvoie les adresses IP du serveur Yahoo

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 11


ESGIS L3/IIRT Semestre 5

InetAddress[] adressesServeurYahoo =
InetAddress.getAllByName("yahoo.com");
System.out.println("Voici les adresses IP de Yahoo : ");
for(int i = 0; i < adressesServeurYahoo.length; i++)
System.out.println(" " +
adressesServeurYahoo[i].getHostAddress());
}
catch(Exception e) {
e.printStackTrace();
}
}

Résultat :

L'adresse IP de la machine locale : 172.28.0.1


L'adresse IP de l'ESGIS est : 65.39.193.50
Voici les adresses IP de Yahoo :
74.6.231.21
98.137.11.163
74.6.143.25
74.6.231.20
74.6.143.26
98.137.11.164

Exercice : tentez d'afficher à l'aide de ce programme les adresses IP renvoyées par la méthode
public byte [] getAddress (). Que remarquez-vous ?

Remarque : la manipulation d'octets non signés pose des problèmes en Java car il n'y a pas
d'équivalent au type C unsigned char. Ainsi, les octets supérieurs à 127 sont traités comme des
nombres négatifs.

Pour récupérer les bonnes valeurs il convient de procéder comme suit :

int octetNonSigne = octet < 0 ? octet + 256 : octet;

XV.1.1.2. La classe NetworkInterface

La classe Java NetworkInterface permet d’obtenir la liste des interfaces de connexion au réseau
de la machine. Une interface de connexion à un réseau se caractérise par un nom court, une
désignation et une liste d’adresses IP. Les méthodes de cette classe sont les suivantes :

Méthode Description
String getName() Renvoie le nom court de l’interface.
String getDisplayName() Renvoie la désignation de l’interface.
Renvoie une énumération d’objet
Enumeration getInetAddresses() InetAddress contenant la liste des adresses IP
associées à l’interface.

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 12


ESGIS L3/IIRT Semestre 5

Le programme suivant donne la liste de toutes les interfaces liées à notre machine :

Classe NetworkInterfaceSample.java :
package ga.esgis.l3iirtsrs.inet;
import java.io.*;
import java.net.*;
import java.util.*;
import static java.lang.System.out;

public class NetworkInterfaceSample {

public static void main(String[] args) throws SocketException {


Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
for(NetworkInterface netInt : Collections.list(nets))
displayInterfaceInformation(netInt);

static void displayInterfaceInformation (NetworkInterface netInt) throws


SocketException {
out.printf("Nom court : %s\n", netInt.getName());
out.printf("designation : %s\n", netInt.getDisplayName());
Enumeration<InetAddress> inetaddresses = netInt.getInetAddresses();
for(InetAddress inetaddress : Collections.list(inetaddresses)) {
out.printf("Adresse IP : %s\n", inetaddress);
}
out.printf("\n");
}
}

Résultat :

Nom court : ethernet_0


Designation : VirtualBox Host-Only Ethernet Adapter-WFP Native MAC Layer LightWeight Filter-
0000

Nom court : ethernet_1


Designation : VirtualBox Host-Only Ethernet Adapter-Kaspersky Lab NDIS 6 Filter-0000

Nom court : ethernet_32772
Designation : Hyper-V Virtual Ethernet Adapter
Adresse IP : /fe80:0:0:0:d037:6b05:9baa:38cf%ethernet_32772
Adresse IP : /172.28.0.1

Nom court : loopback_0
Designation : Software Loopback Interface 1
Adresse IP : /0:0:0:0:0:0:0:1
Adresse IP : /127.0.0.1

Nom court : wireless_32768
Designation : Intel(R) Dual Band Wireless-AC 7265
Adresse IP : /fe80:0:0:0:812c:e380:dcb5:e2%wireless_32768
Adresse IP : /192.168.0.9

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 13


ESGIS L3/IIRT Semestre 5

XV.2. Java et la communication par des Sockets

Les Sockets sont des objets permettant la gestion de deux flux de données : un flux d’entrée
(InputStream), garantissant la réception de données, et un flux de sortie (OutputStream), servant
à envoyer des données. En Java, on distingue deux types de Sockets : les Sockets Simples dits
« Sockets clients » et les « Sockets serveurs ».

Les Sockets représentent l’objet de base pour la programmation TCP et UDP.

XV.2.1. Programmation réseau avec le protocole TCP : Sockets TCP

XV.2.1.1. Le modèlee Client/Serveur

Le protocole TCP offre un service en mode connecté et fiable. Les données sont délivrées dans
l’ordre de leur émission.

La procédure d’établissement de connexion est dissymétrique. Un processus, appelé serveur,


attends des demandes de connexion qu’un processus, appelé client, lui envoie. Une fois l’étape
d’établissement de connexion effectuée le fonctionnement redeviens symétrique.

Les deux schémas suivants présentent les algorithmes de fonctionnement des clients et serveurs.
Il est à noter que côté serveur on utilise deux sockets : l’un, appelé socket d’écoute, reçoit les
demandes de connexion et l’autre, appelé socket de service, sert pour la communication. En
effet, un serveur peut être connecté simultanément avec plusieurs clients et dans ce cas on
utilisera autant de sockets de service que de clients.

Fonctionnement du serveur Fonctionnement du client


Figure 4 : Modèle Client/Serveur

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 14


ESGIS L3/IIRT Semestre 5

Les classes URL et URLConnection fournissent un mécanisme de haut niveau pour l’accès aux
ressources Internet. Mais parfois, certains programmes nécessitent une communication réseau
de bas niveau, c’est les cas lorsqu’on développe des applications Client/Serveur.

Le package java.net offre une communication bidirectionnelle entre deux programmes qui
s’exécutent sur un réseau. Les classes Socket et ServerSocket sont utilisées pour assurer la
liaison entre le programme client et le programme serveur.

Le schéma suivant illustre le mécanisme de communication entre le serveur et le client.

Figure 5 : Communication par TCP

XV.2.1.2. La classe Socket

La classe Socket représente en Java les sockets utilisés côtés client ou les sockets de service.
Les Sockets constituent l’élément de base des communications à travers un réseau informatique.
Comme les flux Java sont transformés en format TCP/IP, il est possible de communiquer avec
l’ensemble des ordinateurs qui utilisent ce protocole quel que soit leur système d’exploitation.
La seule chose importante au niveau du système d’exploitation est qu’il soit capable de gérer
ce protocole.

Cette classe encapsule la connexion à une machine distante via le réseau. Elle gère ainsi la
connexion, l’envoi de données, la réception de données et la déconnexion.

a. Constructeurs

La classe Socket possède plusieurs constructeurs dont les principaux sont les suivants :

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 15


ESGIS L3/IIRT Semestre 5

Constructeur Rôle
Server() Constructeur par défaut.
Crée un Socket sur la machine dont le nom et
ServerSocket(string, int)
le port sont fournis en paramètre.
Crée un Socket sur la machine dont l’adresse
ServerSocket(Inetaddress, int)
IP et le port sont fournis en paramètre.

 public Socket (String hote, int port) throws UnknownHostException, IOException

Ce constructeur crée un socket TCP et tente de se connecter sur le port indiqué de l’hôte visé.
Le premier paramètre de ce constructeur représente le nom de la machine serveur. Si l’hôte est
inconnu ou que le serveur de noms de domaine est inopérant, le constructeur générera une
UnknownHostException. Les autres causes d’échec, qui déclenchent l’envoi d’une IOException
sont multiples : machine cible refusant la connexion sur le port précisé ou sur tous les ports,
problème lié à la connexion Internet, erreur de routage des paquets, etc.

Voici un exemple d’utilisation de ce constructeur :


Socket leSocket = new Socket("www.esgis.org", 80);

 public Socket (InetAddress address, int port) throws IOException

Ce constructeur fonctionne comme le premier, mais prends comme premier paramètre une
instance de la classe InetAddress. Ce constructeur provoque une IOException lorsque la
tentative de connexion échoue mais il ne renvoie pas d’UnknownHostException puisque cette
information est connue lors de la création de l’objet InetAddress.

 public Socket(String hote, int port, InetAddress adresseLocale, int portLocal)


throws IOException

Comme les deux précédents, ce constructeur crée un socket et tente de se connecter sur le port
indiqué de l’hôte visé. Le numéro du port et le nom de la machine sont fournis dans les deux
premiers paramètres et la connexion s’établit à partir de l’interface réseau physique (choix
d’une carte réseau sur un système possédant plusieurs accès réseau) ou virtuelle (système multi-
adresse) et du port local indiqués dans les deux derniers paramètres.

Si portLocal vaut 0, la méthode (comme les deux premières d’ailleurs) choisit un port
disponible (parfois appelé port anonyme) compris entre 1024 et 65 535.

Comme la première méthode cette méthode peut générer une IOException en cas de problème
de connexion et lorsque le nom d’hôte donné n’est pas correct (il s’agit dans ce cas d’une
UnknownHostException).

 public Socket(InetAddress address, int port, InetAddress adresseLocale, int


portLocal) throws IOException

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 16


ESGIS L3/IIRT Semestre 5

Cette méthode est identique à la précédente à la seule différence que le premier paramètre est,
comme pour la seconde méthode, un objet InetAddress.

 protected Socket()
 protected Socket(SocketImpl impl) throws SocketException

Ces deux derniers constructeurs sont protégés. Ils créent un socket sans le connecter. On utilise
ces constructeurs pour implanter un socket original qui permettra par exemple de chiffrer les
transactions ou d’interagir avec un Proxy.

Il existe de plus deux autres constructeurs qui permettent le choix du protocole via un booléen
mais ces méthodes sont dépréciées et ne doivent pas être utilisées. Pour créer un socket utilisant
UDP on utilisera DatagramSocket.

En dehors de ces constructeurs, la classe Socket possède plusieurs autres méthodes parmi
lesquelles :

Méthode Rôle
Renvoie l’adresse IP à laquelle le Socket est
InetAddress getInetAddress()
connecté.
int getPort() Renvoie le port auquel le Socket est connecté.
void close() Ferme le Socket.
Renvoie un flux en entrée pour recevoir des
InputStream getInputStream()
données du Socket.
Renvoie un flux en sortie pour transmettre
OutputStream getOutputStream()
des données au Socket.

b. Méthodes informatives
 public InetAddress getInetAddress ()
 public int getPort ()

Ces méthodes renvoient l'adresse Internet et le port distants auquel le socket est connecté.

 public InetAddress getLocalAddress ()


 public int getLocalPort ()

Ces méthodes renvoient l'adresse Internet et le port locaux que le socket utilise.

c. Communication avec un socket


 public InputStream getInputStream () throws IOException

Cette méthode renvoie un flux d’entrées brutes grâce auquel un programme peut lire des
informations à partir d’un socket. Il est d’usage de lier cet InputStream à un autre flux offrant
davantage de fonctionnalités (un DataInputStream par exemple) avant d’acquérir les entrées.

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 17


ESGIS L3/IIRT Semestre 5

Voici un exemple d’utilisation de cette méthode :


DataInputStream fluxEnEntree = new DataInputStream(leSocket.getInputStream());

 public OutputStream getOutputStream () throws IOException

Cette méthode renvoie un flux de sortie brutes grâce auquel un programme peut écrire des
informations sur un socket. Il est d’usage de lier cet OutputStream à un autre flux offrant
davantage de fonctionnalités (un DataOutputStream par exemple) avant d’émettre des données.

Voici un exemple d’utilisation de cette méthode :


DataOutputStream fluxEnSortie = new DataOutputStream(leSocket.getOutputStream());

d. Fermeture d’un socket


 public void close() throws IOException

Bien que Java ferme tous les sockets ouverts lorsqu’un programme se termine ou bien lors d’un
« garbage collect », il est fortement conseillé de fermer explicitement les sockets dont on n’a
plus besoin à l’aide de la méthode close.

Une fois un socket fermé on peut toujours utiliser les méthodes informatives, par contre toute
tentative de lecture ou écriture sur les « input/output streams » provoque une IOException.

e. Options des sockets

Java permet l’accès à un certain nombre d’options qui modifient le comportement par défaut
des sockets. Ces options correspondent à celles que l’on manipule en C via ioctl (ou ioctlsocket
avec Windows).

 public boolean getTcpNoDelay() throws SocketException


 public void setTcpNoDelay(boolean valide) throws SocketException

Valide/invalide l’option TCP_NODELAY. Valider TCP_NODELAY garantit que les données


seront expédiées aussi rapidement que possible quelle que soit leur taille. Ceci correspond à
interdire la mise en œuvre de l’algorithme de Nagle qui, en simplifiant, concatène les données
de taille réduite dans des segments de taille supérieure avant envoi.

Si l’on programme une application très interactive on pourra valider l’option TCP_NODELAY.

 public int getSoLinger() throws SocketException


 public void setSoLinger(boolean valide, int secondes) throws SocketException

L’option SO_LINGER indique le comportement à adopter lorsqu’il reste des données à


expédier au moment de la fermeture du socket. Par défaut, la méthode close() rend la main
immédiatement et le système tente d’envoyer le reliquat de données. Si la durée des
prolongations secondes vaut 0 et que valide est à vrai, les éventuelles données restant sont

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 18


ESGIS L3/IIRT Semestre 5

supprimés lorsque la fermeture à lieu. Si la durée est positive et que valide est à vrai, la méthode
close se fige pendant le nombre de secondes spécifiées en attendant l’expédition des données
et la réception de l’acquittement. Une fois les prolongations écoulées, le socket est clos et les
données restantes ne sont pas transmises.

Si cette option n’est pas validée (valide est à faux) on obtient le comportement par défaut et
l’appel de la méthode getSoLinger() retourne –1, sinon la méthode renvoie la durée des
prolongations.

 public int getSoTimeout() throws SocketException


 public void setSoTimeout(int ms) throws SocketException

Par défaut, lors d’une tentative de lecture sur le flux d’entrée d’un socket, read() se bloque
jusqu’à la réception d’un nombre d’octets suffisant. Lorsque SO_TIMEOUT est initialisée,
cette attente ne dépasse pas le temps imparti, exprimé en millisecondes. Tout dépassement de
temps se solde par une une java.net.SocketTimeoutException. Le socket reste malgré tout
connecté.

La valeur par défaut est 0 qui signifie, ici, un laps de temps infini. Il peut être préférable de
choisir une durée raisonnable (>0) pour éviter que le programme se bloque en cas de problème.

L’option doit être validée avant l’appel à l’opération bloquante pour être prise en compte.

Le paramètre doit être >= 0 sans quoi une exception SocketException est générée.

 public int getSendBufferSize() throws SocketException


 public void setSendBufferSize(int size) throws SocketException
 public int getReceiveBufferSize() throws SocketException
 public void setReceiveBufferSize(int size) throws SocketException

Ces méthodes permettent, grâce aux options SO_SNDBUF et SO_RCVBUF, de préciser une
indication sur la taille à allouer aux tampons d’entrée/sortie bas niveaux. Il s’agit uniquement
d’une indication donc il est conseillé après l’appel d’une méthode set… d’appeler la méthode
get… correspondante pour vérifier la taille allouée.

f. Méthode surchargée
 public String toString()

La seule méthode surchargée de la classe Object est toString(). Cette méthode provoque
l’affichage d’une chaîne ressemblant à cela :

Socket[addr=amber/192.11.4.2, port=80, localport=1167]

Cette méthode est donc plutôt destinée au débogage.

En générale, l’algorithme déroulé pour établir une connexion via un Socket est le suivant :

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 19


ESGIS L3/IIRT Semestre 5

 créer une instance de la classe Socket en précisant la machine et le port en paramètre ;


 obtenir un flux en entrée et en sortie ;
 écrire les traitements à réaliser.

Exemple 1 de programme client : TCPClientSocketEcho.java

package ga.esgis.l3iirtsrs.inet;
import java.io.*;
import java.net.*;

public class TCPClientSocketEcho extends Object {

final static int PORT = 9632;

public static void main (String args[]) {


String reponse;
Socket leSocket;
PrintStream fluxSortieSocket;
BufferedReader fluxEntreeSocket;

try {
InetAddress serveur = InetAddress.getByName(args[0]);
// creation d’une socket et connexion à la machine dont le nom est passé
en argument sur le port numéro 9632
leSocket = new Socket(serveur, PORT);
System.out.println("Connecté sur : "+leSocket);
// création d’un flux de type PrintStream lié au flux de sortie du socket
fluxSortieSocket = new PrintStream(leSocket.getOutputStream());
// creation d’un flux de type BufferedReader lié au flux d’entrée du socket
fluxEntreeSocket = new BufferedReader(new
InputStreamReader(leSocket.getInputStream()));
// envoi de données vers le serveur
fluxSortieSocket.println("Bonjour le monde!");
// attente puis réception de données envoyées par le serveur
reponse = fluxEntreeSocket.readLine();
System.out.println("Reponse du serveur : " + reponse);
leSocket.close();
} // try
catch (ConnectException ex)
{
System.err.println("Erreur de connexion au serveur : "+ex);
ex.printStackTrace();
}
catch (UnknownHostException ex)
{
System.err.println("Machine inconnue : "+ex);
ex.printStackTrace();
}
catch (IOException ex)
{
System.err.println("Erreur : "+ex);
ex.printStackTrace();
}
} // main
} // class

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 20


ESGIS L3/IIRT Semestre 5

Exemple 2 de programme client : TCPClientSocket.java

package ga.esgis.l3iirtsrs.inet;
import java.net.*;
import java.io.*;

public class TCPClientSocket {


final static int PORT = 9632;

public static void main(String[] args) {


Socket socket;
try {
InetAddress serveur = InetAddress.getByName(args[0]);
socket = new Socket(serveur, PORT);
BufferedReader in = new BufferedReader (new
InputStreamReader(socket.getInputStream()));

PrintStream out = new PrintStream(socket.getOutputStream());

Console c = System.console();
out.println("Veuillez saisir votre compte : ");
String message = c.readLine(in.readLine());
out.println(message);

System.out.println(in.readLine());

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

XV.2.1.3. La classe ServerSocket

La classe ServerSocket est utilisée côté serveur. Elle attend simplement les appels du (ou des)
client(s). Une instance de cette classe est un objet du type Socket qui prend en charge la
transmission de données.

Cette classe permet de créer des sockets qui attendent des connexions sur un port spécifié et
lors d’une connexion retournent un Socket qui permet de communiquer avec l’appelant.

Cette classe représente la partie serveur du Socket. Un objet de cette classe est associé à un port
sur lequel il va attendre les connexions d’un client. Généralement, à l’arrivée d’une demande
de connexion, un thread est lancé pour assurer le dialogue avec le client afin de ne pas bloquer
les connexions des autres clients.

g. Constructeurs

La classe ServerSocket possède plusieurs constructeurs dont les principaux sont les suivants :

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 21


ESGIS L3/IIRT Semestre 5

Constructeur Rôle
ServerSocket() Constructeur par défaut.
Crée un Socket sur le port fourni en
ServerSocket(int)
paramètre.
Crée un Socket sur le port avec la taille
ServerSocket(int, int)
maximale de la file fournis en paramètre.

Tous ces constructeurs peuvent lever une exception de type IOException.

 public ServerSocket (int port) throws IOException

Ce constructeur crée un socket serveur qui attendra les connexions sur le port spécifié. Lorsque
l’entier port vaut 0, le port est sélectionné par le système. Ces ports anonymes sont peu utilisés
car le client doit connaître à l’avance le numéro du port de destination. Il faut donc un
mécanisme, comme le port mapper des RPC, qui permet d’obtenir ce numéro de port à partir
d’une autre information.

L’echec de la création se solde par une IOException (ou à partir de Java 1.1 une BindException
qui hérite de IOException) qui traduit soit l’indisponibilité du port choisi soit, sous UNIX, un
problème de droits (sous UNIX les ports inférieurs à 1024 ne sont disponibles que pour le super
utilisateur).

 public ServerSocket (int port, int tailleFile) throws IOException

Ce constructeur permet en outre de préciser la longueur de la file d’attente des requêtes de


connexion. Si une demande de connexion arrive et que la file est pleine la connexion sera
refusée sinon elle sera stockée dans la file pour être traitée ultérieurement. La longueur de la
file d’attente par défaut (pour le premier constructeur) est 50.

Lorsque la valeur donnée est supérieure à la limite fixée par le système, la taille maximale est
affectée à la file.

 public ServerSocket (int port, int tailleFile, InetAddress adresseLocale) throws


IOException

Ce constructeur permet en outre de préciser l’adresse Internet locale sur laquelle attendre des
connexions. Ainsi on pourra choisir l’une des interfaces réseau de la machine locale si elle en
possède plusieurs. Si adresseLocale est à null le socket attendra des connexions sur toutes les
adresses locales (ce qui est aussi le cas quand on utilise l’un des deux autres constructeurs).

La classe ServerSocket possède plusieurs méthodes. En voici 2 :

Méthode Rôle
Socket accept() Attendre une nouvelle connexion.
void close() Fermer le Socket.

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 22


ESGIS L3/IIRT Semestre 5

Si un client tente de communiquer avec le serveur, la méthode accept() renvoie un Socket qui
encapsule la communication avec ce client.

h. Accepter et clore une connexion

 public Socket accept () throws IOException

Cette méthode bloque l’exécution du programme serveur dans l’attente d’une demande de
connexion d’un client. Elle renvoie un objet Socket une fois la connexion établie.

Si vous ne voulez pas bloquer l’exécution du programme il suffit de placer l’appel à accept dans
un thread spécifique.

 public void close () throws IOException

Cette méthode ferme le socket serveur en libérant le port. Les sockets serveurs sont eux aussi
fermés automatiquement par le système à la fermeture de l’application mais il est fortement
conseillé de les fermer explicitement.

En général, l’algorithme qui est exécuté pour établir une connexion est le suivant :

 Créer une instance de la classe ServerSocket en précisant le port en paramètre ;


 Définir une boucle sans fin contenant les actions ci-dessous :
o Appel de la méthode accept() qui renvoie un Socket lors d’une nouvelle
connexion ;
o Obtenir un flux en entrée et en sortie à partir du Socket ;
o Écrire les traitements à réaliser.

i. Méthodes informatives

 public InetAddress getInetAddress ()


 public int getLocalPort ()

Ces méthodes renvoient l'adresse Internet et le port locaux sur lequel le socket attend les
connexions.

j. Options des sockets serveurs

Seule l’option SO_TIMEOUT est disponible pour les sockets serveurs.

 public int getSoTimeout() throws SocketException


 public void setSoTimeout(int ms) throws SocketException

Par défaut, l’appel à accept() se bloque jusqu’à la réception d’une demande de connexion.
Lorsque SO_TIMEOUT est initialisée, cette attente ne dépasse pas le temps imparti, exprimé

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 23


ESGIS L3/IIRT Semestre 5

en millisecondes. Tout dépassement de temps se solde par une InterruptedException. Le socket


reste malgré tout connecté.

La valeur par défaut est 0 qui signifie, ici, un laps de temps infini ce qui convient à la plupart
des serveurs, conçus en général pour s’exécuter indéfiniment.

L’option doit être validée avant l’appel à accept() pour être prise en compte.

Le paramètre doit être >= 0 sans quoi une exception SocketException est générée.

k. Méthode surchargée

 public String toString()

La seule méthode surchargée de la classe Object est toString(). Cette méthode provoque
l’affichage d’une chaîne ressemblant à ce qui suit :
ServerSocket[addr=0.0.0.0/0.0.0.0, port=0, localport=80]

Sous Java 1.1 et les précédentes versions addr et port sont toujours nulles. La seule information
utile est donc localport qui indique le numéro du port d’attente des connexions. Cette méthode
est ici aussi plutôt destinée au débogage.

Exemple 1 de programme serveur : TCPServerSocketEcho.java

package ga.esgis.l3iirtsrs.inet;
import java.io.*;
import java.net.*;

public class TCPServerSocketEcho extends Object{


final static int PORT = 9632;

public static void main (String args[]) {


ServerSocket socketEcoute;
Socket socketService;
InputStream entreeSocket;

OutputStream sortieSocket;
try {
System.out.println("Lancement du serveur !");
// Création du socket d’écoute (port numéro PORT)
socketEcoute = new ServerSocket(PORT);
while (true) {
// Attente d’une demande de connexion
socketService = socketEcoute.accept();
System.out.println("Nouvelle connexion : " + socketService);
// Récupération des flux d’entrée/sortie du socket de service
entreeSocket = socketService.getInputStream();
sortieSocket = socketService.getOutputStream();
try {
int b = 0;
while (b != -1) {
b = entreeSocket.read();
sortieSocket.write(b);

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 24


ESGIS L3/IIRT Semestre 5

} // while
System.out.println("Fin de connexion");
} // try
catch (IOException ex)
{
// Fin de connexion
System.out.println("Fin de connexion : "+ex);
ex.printStackTrace();
}
socketService.close();
} // while (true)
} // try
catch (Exception ex)
{
// Erreur de connexion
System.err.println("Une erreur est survenue : "+ex);
ex.printStackTrace();
}
} // main
} // class

Exemple 2 de programme serveur : TCPServerSocketSample.java

package ga.esgis.l3iirtsrs.inet;
import java.net.*;
import java.io.*;

public class TCPServerSocketSample {


final static int PORT = 9632;

public static void main(String[] args) {


try {
System.out.println("Lancement du serveur !");
ServerSocket socketServeur = new ServerSocket(PORT);
while (true) {
Socket socketClient = socketServeur.accept();
System.out.println("connexion avec : " +
socketClient.getInetAddress());
BufferedReader in = new BufferedReader (
new InputStreamReader(socketClient.getInputStream()));
PrintStream out = new PrintStream(socketClient.getOutputStream());
//Le serveur demande au client de saisir son compte
out.println("Veuillez saisir votre compte : ");
String compte = in.readLine(); //Le client saisit son compte
System.out.println("Compte d'utilisateur : " + compte);
//Message de bienvenue au client
out.println("Bienvenue " + compte);
socketClient.close();
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}

La limite de ce programme est qu’il ne peut traiter qu’une seule connexion à la fois. Si plusieurs
demandes de connexion arrivent simultanément, une seule est acceptée ; les autres sont mises

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 25


ESGIS L3/IIRT Semestre 5

en attente jusqu’à ce que la première termine sa connexion. Pour pouvoir traiter plusieurs
connexions en même temps (plusieurs clients), il faut que le serveur soit multithreadé.

Exemple : TCPServerSocketSampleThread.java

package ga.esgis.l3iirtsrs.inet;
import java.net.*;
import java.io.*;

public class TCPServerSocketSampleThread extends Thread {


final static int PORT = 9632;
private Socket socket;

public static void main(String[] args) {

try {
ServerSocket socketServeur = new ServerSocket(PORT);
System.out.println("Lancement du serveur !");
while (true) {
Socket socketClient = socketServeur.accept();
TCPServerSocketSampleThread serveur = new
TCPServerSocketSampleThread(socketClient);
}
} catch (Exception e) {
e.printStackTrace();
}

public TCPServerSocketSampleThread(Socket socket) {


this.socket = socket;
}

public void run() {


try {
String message = "";
System.out.println("Connexion avec le client : " +
socket.getInetAddress());
BufferedReader in = new BufferedReader (
new InputStreamReader(socket.getInputStream()));
PrintStream out = new PrintStream(socket.getOutputStream());
out.println("Veuillez saisir votre compte : ");
//Le client saisit son compte
message = in.readLine();
out.println("Bienvenue " + message);
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}

XV.2.2. Programmation réseau avec le protocole UDP : Sockets UDP

Le protocole UDP offre un service non connecté et non fiabilisé. Les données peuvent être
perdues, dupliquées ou délivrées dans un ordre différent de leur ordre d’émission.

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 26


ESGIS L3/IIRT Semestre 5

Le fonctionnement est ici symétrique. Chaque processus crée un socket et l’utilise pour envoyer
ou attendre et recevoir des données.

En Java on utilise la classe DatagramPacket pour représenter les datagrammes UDP qui sont
échangés entre les machines.

XV.2.2.1. La classe DatagramPacket

a. Constructeurs
 public DatagramPacket(byte[] tampon, int longueur)

Ce constructeur crée un objet utilisé pour recevoir les données contenues dans des datagrammes
UDP reçus par la machine. Le paramètre tampon doit correspondre à un tableau d’octets (type
byte en java) correctement créé (Attention ! si le tableau n’est pas assez grand les données en
excès seront détruites). Le paramètre longueur indique la longueur du tableau.

Exemple d’utilisation :
byte[] tampon = new byte[1024];
DatagramPacket datagramme = new DatagramPacket(tampon, tampon.length);

 public DatagramPacket(byte[] tampon, int longueur, InetAddress adresse, int


port)

Ce constructeur crée un objet utilisé pour envoyer un datagramme UDP. Le paramètre tampon
doit correspondre aux données à envoyer. Le paramètre longueur doit indiquer la longueur des
données à envoyer. Le paramètre adresse et le paramètre port doivent indiquer respectivement
l’adresse IP et le port de destination.

Il est à noter qu’il existe d’autres constructeurs qui permette d’indiquer un offset dans un tableau
de grande dimension. Ils doivent être utilisés pour envoyer un tableau dont la taille dépasse la
taille maximale des datagrammes IP.

Exemple d’utilisation :
String message = "Bonjour le monde!";
byte[] tampon = message.getBytes();
InetAddress adresse = InetAddress.getByName("marine.edu.ups-tlse.fr");
DatagramPacket datagramme = new DatagramPacket(tampon, tampon.length,
adresse, 7);

b. Accesseurs
 public byte[] getData()
 public void setData(byte[] buf)

Ces méthodes permettent de récupérer et de changer le tableau d’octets utilisé soit pour recevoir
soit pour envoyer un datagramme UDP.

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 27


ESGIS L3/IIRT Semestre 5

 public void setLength(int length)


 public int getLength()

Ces méthodes permettent de récupérer et de changer la longueur du tableau d’octets utilisé soit
pour recevoir soit pour envoyer un datagramme UDP.

 public InetAddress getAddress()


 public void setAddress(InetAddress iaddr)
 public int getPort()
 public void setPort(int iport)

Ces méthodes permettent de récupérer et de changer les adresses IP et numéros de ports. Si


l’objet est utilisé pour envoyer des datagrammes UDP il s’agira de l’adresse et du port de
destination sinon il s’agira de l’adresse et du port de l’émetteur du datagramme UDP.

XV.2.2.2. La classe DatagramSocket

a. Constructeurs
 public DatagramSocket() throws SocketException

Ce constructeur crée un socket UDP qui permet d’envoyer et recevoir des datagrammes UDP.
Le port qu’utilise ce socket est choisi par le système d’exploitation. De même l’adresse IP
qu’utilise ce socket est choisie automatiquement par le système.

 public DatagramSocket(int port) throws SocketException

Ce constructeur crée un socket UDP qui permet d’envoyer et recevoir des datagrammes UDP.
Le port qu’utilise ce socket est indiqué par le paramètre port. L’adresse IP qu’utilise ce socket
est choisie automatiquement par le système.

 public DatagramSocket(int port, InetAddress adresse) throws SocketException

Ce constructeur crée un socket UDP qui permet d’envoyer et recevoir des datagrammes UDP.
Le port qu’utilise ce socket est indiqué par le paramètre port. L’adresse IP qu’utilise ce socket
est indiqué par le paramètre adresse.
Ces trois constructeurs peuvent générer des exceptions de type SocketException s’il y a un
problème de configuration réseau, si le port choisi est déjà utilisé ou si l’adresse choisie n’est
pas l’une des adresses de la machine locale.

b. Emission et Réception de Datagrammes


 public void send(DatagramPacket p) throws IOException

Envoie un datagramme UDP qui contiendra toutes les informations référencées par l’objet p.

 public void receive(DatagramPacket p) throws IOException

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 28


ESGIS L3/IIRT Semestre 5

Attends un datagramme UDP et lors de sa réception stocke ses informations dans l’objet p.
Des exceptions de type IOException peuvent être générées si un problème d’entrée/sortie
survient.

c. Méthodes informatives
 public InetAddress getLocalAddress ()
 public int getLocalPort ()

Ces méthodes renvoient l'adresse Internet et le port locaux que le socket utilise.

d. Fermeture du socket
 public void close() throws IOException

Bien que Java ferme tous les sockets ouverts lorsqu’un programme se termine ou bien lors d’un
« garbage collect », il est fortement conseillé de fermer explicitement les sockets dont on n’a
plus besoin à l’aide de la méthode close.
Une fois un socket fermé on peut toujours utiliser les méthodes informatives, par contre toute
tentative d’émission ou de réception de datagrammes UDP provoque une IOException.

e. Options

Comme pour les sockets UDP on peut positionner un certain nombre d’options qui modifient
le comportement par défaut des sockets.

 public int getSoTimeout() throws SocketException


 public void setSoTimeout(int ms) throws SocketException

Par défaut, lors d’une tentative de réception d’un datagramme UDP, receive se bloque jusqu’à
la réception d’un datagramme. Lorsque SO_TIMEOUT est initialisée, cette attente ne dépasse
pas le temps imparti, exprimé en millisecondes. Tout dépassement de temps se solde par une
java.net.SocketTimeoutException. Le socket reste malgré tout connecté.
La valeur par défaut est 0 qui signifie, ici, un laps de temps infini. Il peut être préférable de
choisir une durée raisonnable (>0) pour éviter que le programme se bloque en cas de problème.
L’option doit être validée avant l’appel à l’opération bloquante pour être prise en compte.
Le paramètre doit être >= 0 sans quoi une exception SocketException est générée.

 public int getSendBufferSize() throws SocketException


 public void setSendBufferSize(int size) throws SocketException
 public int getReceiveBufferSize() throws SocketException
 public void setReceiveBufferSize(int size) throws SocketException

Ces méthodes permettent, grâce aux options SO_SNDBUF et SO_RCVBUF, de préciser une
indication sur la taille à allouer aux tampons d’entrée/sortie bas niveaux. Il s’agit uniquement
d’une indication donc il est conseillé après l’appel d’une méthode set… d’appeler la méthode
get… correspondante pour vérifier la taille allouée.

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 29


ESGIS L3/IIRT Semestre 5

 public void setReuseAddress(boolean on) throws SocketException


 public boolean getReuseAddress() throws SocketException

Ces méthodes permettent, grâce à l’option SO_REUSEADDR, de permettre à plusieurs sockets


d’utiliser le même numéro de port. L’option est désactivée par défaut. Cette option peut être
utilisée lors de diffusions (broadcast ou multicast – voir aussi la classe suivante).

XV.2.2.3. La classe MulticastSocket

Cette classe permet d’utiliser le multicasting IP pour envoyer des datagrammes UDP à un
ensemble de machines repéré grâce à une adresse multicast (classe D dans IP version 4 : de
224.0.0.1 à 239.255.255.255).

a. Constructeurs

Les constructeurs de cette classe sont identiques à ceux de la classe DatagramSocket.

b. Abonnement/résiliation

Pour pouvoir recevoir des datagrammes UDP envoyés grâce au multicasting IP il faut s’abonner
à une adresse multicast (de classe D pour IP version 4). De même lorsqu’on ne souhaite plus
recevoir des datagrammes UDP envoyés à une adresse multicast on doit indiquer la résiliation
de l’abonnement.

 public void joinGroup(InetAddress adresseMulticast) throws IOException

Cette méthode permet de s’abonner à l’adresse multicast donnée.


Note : un même socket peut s’abonner à plusieurs adresses multicast simultanément. D’autre
part il n’est pas nécessaire de s’abonner à une adresse multicast si on veut juste envoyer des
datagrammes à cette adresse.
Une IOException est générée si l’adresse n’est pas une adresse multicast ou s’il y a un problème
de configuration réseau.

 public void leaveGroup(InetAddress adresseMulticast) throws IOException

Cette méthode permet de résilier son abonnement à l’adresse multicast donnée.


Une IOException est générée si l’adresse n’est pas une adresse multicast, si le socket n’était pas
abonné à cette adresse ou si il y a un problème de configuration réseau.

c. Choix du TTL

Dans les datagrammes IP se trouve un champ spécifique appelé TTL (Time To Live – durée
de vie) qui est normalement initialisé à 255 et décrémenté par chaque routeur que le datagramme
traverse. Lorsque ce champ atteint la valeur 0 le datagramme est détruit et une erreur ICMP est
envoyé à l’émetteur du datagramme. Cela permet d’éviter que des datagrammes tournent
infiniment à l’intérieur d’un réseau IP.

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 30


ESGIS L3/IIRT Semestre 5

Le multicasting IP utilise ce champ pour limiter la portée de la diffusion. Par exemple avec un
TTL de 1 la diffusion d’un datagramme est limitée au réseau local.

 public int getTimeToLive() throws IOException


 public void setTimeToLive(int ttl) throws IOException

Ces méthodes permettent la consultation et la modification du champ TTL qui sera écrit dans
les datagrammes envoyés par ce socket.

XV.2.2.4. Exemple de programme qui envoie un datagramme

Classe UDPSendDatagram.java

package ga.esgis.l3iirtsrs.inet;
import java.net.*;
import java.io.*;

public class UDPSendDatagram {


public static void main(String argv[]) throws SocketException, IOException,
UnknownHostException
{
String message = "Bonjour le monde!";
System.out.println(message);
byte[] tampon = message.getBytes();
InetAddress adresse = null;
DatagramSocket socket;

// Recupère l’adresse IP de la machine locale dont le nom est passé en


paramètre
adresse = InetAddress.getByName(argv[0]);

// Crée l’objet qui stockera les données du datagramme à envoyer


DatagramPacket envoi = new DatagramPacket(tampon,tampon.length,adresse,50000);

// Crée un socket UDP (le port est choisi par le système)


socket=new DatagramSocket();

// Envoie le datagramme UDP


socket.send(envoi);
}

XV.2.2.5. Exemple de programme qui reçoit un datagramme

Classe UDPRecieveDatagram.java

package ga.esgis.l3iirtsrs.inet;
import java.net.*;
import java.io.*;
class UDPRecieveDatagram {
public static void main(String argv[]) throws SocketException, IOException {
byte[] tampon = new byte[1000];
String texte;

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 31


ESGIS L3/IIRT Semestre 5

// Crée un socket UDP qui attend des datagrammes sur le port 50000
DatagramSocket socket =new DatagramSocket(50000);

// Crée un objet pour stocker les données du datagramme attendu


DatagramPacket reception = new DatagramPacket(tampon, tampon.length);

// Attend puis récupère les données du datagramme


socket.receive(reception);

// récupère la chaîne de caractère reçue


// Note: reception.getLength() contient le nombre d’octets reçus
texte=new String(tampon, 0, reception.getLength());
System.out.println("Reception de la machine "+
reception.getAddress().getHostName()+
" sur le port "
+reception.getPort()+" :\n"+
texte );
} //main
} //class

XV.2.2.6. Exemple de programme qui envoie et reçoit des datagrammes avec le multicasting
IP

Classe UDPMultiCastingIP.java

package ga.esgis.l3iirtsrs.inet;
import java.net.*;
import java.io.*;

public class UDPMulticastingIP {

public static void main(String argv[]) throws SocketException, IOException {


String msg = "Bonjour le monde!";

// On traveillera avec l’adresse multicast 228.5.6.7


InetAddress groupe = InetAddress.getByName("228.5.6.7");

// Crée le socket utilisé pour émettre et recevoir les datagrammes


// il utilisera le port 50000
MulticastSocket s = new MulticastSocket(50000);

// S’abonne à l’adresse IP multicast


s.joinGroup(groupe);

// Crée l’objet qui stocke les données du datagramme à envoyer


DatagramPacket envoi = new DatagramPacket(msg.getBytes(), msg.length(), groupe,
50000);

// envoie le datagramme a tout le monde


s.send(envoi);

while (true) {
byte[] tampon = new byte[1024];
DatagramPacket reception = new DatagramPacket(tampon, tampon.length);
// Attend les réponses
s.receive(reception);
String texte=new String(tampon, 0, reception.getLength());
System.out.println("Reception de la machine "+

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 32


ESGIS L3/IIRT Semestre 5

reception.getAddress().getHostName()+
" sur le port "
+reception.getPort()+" :\n"+
texte );
}
// si la boucle n’était pas infinie on pourrait écrire:
// s.leaveGroup(groupe);
} //main
} //class

Programmation réseau en Java – PARTIE 2 : La programmation réseau en Java 33

Vous aimerez peut-être aussi