Université Paris 7
IUP 2
Réseaux
Année 2003-2004

Aide TP 8 - Communication réseau en mode non connecté en Java

Objectif

Réaliser un couple d'applications client/serveur communiquant en mode non connecté à travers Internet.

Le client saisit des chaînes de caractères au clavier, les envoie au serveur qui les renvoie en leur ajoutant ``OK''. Le client reçoit et affiche la réponse. La communication se termine quand le client envoie une chaîne de caractères convenue comme par exemple Over&Out.

Un serveur est capable de répondre à plusieurs clients.

Commencer par une version dont le serveur et le client tournent sur une même machine. Tester avec plusieurs clients. Ensuite faire en sorte que le serveur et les clients puissent être sur différentes machines, et puissent fonctionner avec différents numéros de port (voir plus bas). Essayez avec les serveurs d'autres groupes de TP.

Généralités

Les sockets

Les communications entre processus (au moins dans le système unix) utilisent le concept de socket pour désigner le point d'entrée ou de sortie de l'information. L'information va d'un socket à l'autre. De ce fait, un socket est une sorte d'adresse postale (on parle parfois de ``boîte aux lettres'').

Un socket est décrit par

Modes de communication

Les communications entre processus peuvent se faire selon deux modes: connecté et non connecté. L'analogie communément faite pour différencier ces deux modes est celle du téléphone et du courrier. Avec le téléphone, les deux interlocuteurs se mettent d'accord pour communiquer, et utilisent un circuit permanent pour le faire tant que la conversation dure. Toute information émise par une partie est reçue par l'autre. Avec le courrier, l'information est confiée par une partie aux bon soins du transporteur, et on ne sait pas quand ni si elle arrive, ni si elle est lue par le destinataire.

Chacun des deux modes a ses avantages, selon l'application qui est visée.

Le mode non connecté

Le mode non connecté utilise le protocole UDP de l'Internet. Un processus envoie un paquet autonome d'information (datagramme) à destination d'un autre en spécifiant son adresse (numéro de machine et numéro de port). Réciproquement, un processus peut recevoir des datagrammes sur un port. Le datagramme contiendra les informations envoyées par l'émetteur, ainsi que son adresse. Il n'est donc pas nécessaire de connaître à l'avance les numéros de machine et de port de ses correspondants.

Contrairement au mode connecté, aucune procédure de connexion n'est nécessaire. Par contre, il n'y a aucune garantie que les datagrammes arrivent à destination. Si un datagramme est perdu, par exemple parce que personne n'est là pour le recevoir, l'émetteur n'est pas averti.

Le mode connecté

Dans le mode connecté, une sorte de tuyau est établi entre les deux sockets des deux processus. Un processus peut écrire de l'information à un bout et l'autre la lit à l'autre bout. Le mécanisme est similaire en fonctionnalité à celui des entrées/sorties de Unix: c'est un flot de données (en anglais: stream). Le mode connecté utilise le protocole TCP de l'Internet.

Pour établir ce tuyau, il doit y avoir un processus qui prend l'initiative d'établir la connexion, et un autre qui accepte cette connexion. Le processus appelant est qualifié de client et l'autre de serveur. On assimile donc souvent le mode connecté à l'architecture client/serveur. Cependant, une fois que la communication est établie, il n'y a plus aucune asymétrie dans les échanges d'information.

Interface de programmation socket en Java

Le ``package'' java.net fournit les objets nécessaires aux communications par réseau en Java. On l'utilise en incluant au début du fichier de la classe la ligne

import java.net.*;

Pour les communications par socket en mode non connecté, les classes à utiliser sont:
DatagramSocket (le socket) et DatagramPacket (le paquet ou datagramme).

Un socket se déclare simplement par:

DatagramSocket socket = new DatagramSocket( port );

ou bien, si le numéro de port n'a pas d'importance:
DatagramSocket socket = new DatagramSocket();

Un paquet à envoyer se déclare par:

paquet = new DatagramPacket( buf, buf.length, destAddr, destPort);

L'adresse est de type InetAddress et le numéro de port est un entier.

La difficulté est que buf est de type byte[] et non pas String. Il faut donc faire des conversions entre les objets String et byte[]. Par exemple

byte[] buf = s.getBytes();
s = new String( buf, 0, buf.length );

L'envoi se fait par:
socket.send( paquet );

Un paquet à recevoir se déclare par (par exemple):

byte[] inBuf = new byte[1024];
DatagramPacket paquet = new DatagramPacket( inBuf, inBuf.length );

Le paquet se reçoit par
socket.receive( paquet );

La classe DatagramPacket possède des méthodes pour obtenir ses caractéristiques:

Trucs et astuces