3. Définition générale
2
Lorsqu’on veut passer de la programmation classique à la
programmation distribuée, l’outil de base est les sockets
Un Socket est un point de communication
bidirectionnelle entre applications
4. Définition générale
Introduit dans Unix dans les années 80
Un Socket est un point de communication
bidirectionnelle entre applications permettant d’utiliser
l’interface de transport (TCP-UDP).
Représentation point à point d’un flux de données
A B
Application
Socket Write
Write
Read
Read
4
5. Définition plus détaillée
Un socket est
Un point d'accès aux couches transport TCP/UDP
Liée localement à un port
Adressage de l'application sur le réseau : son couple @IP:port
Elle permet la communication avec un port distant sur une
machine distante : c'est-à-dire avec une application distante
5
6. Un socket est associé à un port de communication
pour différencier les applications réseau sur une
même machine
L’API java fourni un package java.net pour l’utilisation
des packages
java.net.Socket pour l’implémentation coté client
java.net.ServerSocket pour l’implémentation coté serveur
Définition plus détaillée
5
7. Notion de « port »
Alphabet et langage
7
Port : ~BAL dans laquelle un processus dépose et récupère ses
données
Chaque processus a un n° de port : identité logique
Application répartie
port pour processus en local (port local ou entrant)
pour pour processus distant (port distant ou sortant)
8. Propriétés des sockets (1/2)
Un socket peut-être lié
Sur un port précis à la demande du programme
Sur un port quelconque libre déterminé par le système
Le numéro de port varie entre 1 et 65535
<1024 : ports réservés pour les applications et les
protocoles systèmes (80 http, 21 ftp, etc.)
>= 1024 : ports utilisateurs
8
9. Propriétés des sockets (2/2)
Le client a l’initiative de la communication et le serveur doit
être à l’écoute
Le client doit connaître la référence du serveur [adresse IP,
n° de port]
Le serveur peut servir plusieurs clients (1 thread unique
ou 1 thread par client)
Un socket ne peut se connecter qu’à une seule machine
Un socket ne peut pas se reconnecter après la fermeture
de connexion
4 fonctions principales:
Se connecter à une machine distante
Envoyer des données
Recevoir des données
Fermer la connexion
9
11. Principe de fonctionnement
Le serveur crée un "socket serveur" (associé à un port
bien précis) et se met en attente
Le client se connecte au socket serveur
deux sockets sont alors créés : un "socket client", côté
client, et un "socket service client" côté serveur. Ces sockets
sont connectés entre eux.
11
13. Utilisation du mode connecté
Caractéristiques
Établissement préalable d'une connexion : le client
demande au serveur s'il accepte la connexion.
Fiabilité assurée par le protocole (TCP).
Mode d’échange par flot d'octets : le récepteur n'a pas
connaissance du découpage des données effectué par
l'émetteur.
Après initialisation, le serveur est "passif" : il est activé
lors de l'arrivée d'une demande de connexion du client.
Un serveur peut répondre aux demandes de service de
plusieurs clients : les requêtes arrivées et non traitées
sont stockées dans une file d'attente.
13
14. Utilisation du mode connecté
Contraintes
Le client doit avoir accès à l’adresse du serveur (adresse IP,
n° de port).
Modes de gestion des requêtes
Itératif : le processus traite les requêtes les unes après les
autres.
Concurrent : création d'un processus fils (ou thread) pour
chaque client. (serveur multi-threadé)
14
15. Programmation socket en
mode connecté
15
Le client doit contacter le
serveur
Le serveur est lancé
Il a créé un socket et est en
attente
Le client contacte le serveur
par :
La création d’un socket TCP
locale
La spécification d’une @ IP et
du n° de port du processus
serveur
Quand le client crée un
socket le client TCP établit
une connexion avec le
serveur TCP
Sur requête du client, le
serveur TCP crée un nouveau
socket pour que le processus
serveur communique avec le
client
Permet à un serveur de parler à
de multiples clients «en même
temps»
16. Serveur itératif
en mode connecté
Client ouvre connexion avec le serveur avant
d’adresser des appels, puis ferme la connexion à la fin
Délimitation temporelle des échanges
Maintien de l'état de connexion pour la gestion des
paramètres de qualité de service
Traitement des pannes, propriété d'ordre.
16
17. Utilisation du mode
non connecté
Caractéristiques
Pas d'établissement préalable d'une connexion.
Pas de garantie de fiabilité.
Adapté aux applications pour lesquelles les réponses aux
requêtes des clients sont courtes (1 message).
Le récepteur reçoit les données selon le découpage
effectué par l’émetteur.
17
18. Utilisation du mode
non connecté
Contraintes
Le client doit avoir accès à l'adresse du serveur
(adresse IP, port).
Le serveur doit récupérer l'adresse de chaque client
pour lui répondre
Mode de gestion des requêtes
Itératif (requêtes traitées l’une après l’autre).
Concurrent (1 processus ou thread par client).
18
19. Serveur itératif en mode
non connecté
Le client peut envoyer une requête au serveur à tout
moment.
Mode léger permettant
Le traitement non ordonné des appels.
L'absence de mémorisation entre requêtes successives
(serveur sans données rémanentes et sans état).
19
21. Socket en mode connecté
Représente une connexion fiable TCP/IP entre 2
processus (~machines)
La connexion est fiable (contrôle d'erreur, …)
2 flots de données sont établis entre les deux machines
Connexion est asymétrique
Une machine est serveur : classe ServerSocket
Elle attend les demandes de connexion et les acceptent.
Une machine est client : classe Socket
Elle demande l'établissement de la connexion avec le serveur.
21
22. Serveur TCP
Crée le ServerSocket :
ServerSocket listenSocket = new ServerSocket(port);
Attend les demandes de connexion et crée un socket pour le dialogue :
Socket clientSocket = listenSocket.accept();
Récupère les flux d'entrée et de sortie :
InputStream in = clientSocket.getInputStream();
OutputStream out = clientSocket.getOutputStream();
Dialogue avec le client.
22
23. Client TCP
Crée le Socket :
Socket server = new Socket(host,port);
Récupère les flux d'entrée et de sortie :
InputStream in = server.getInputStream();
OutputStream out = server.getOutputStream();
Dialogue avec le serveur.
23
25. Remarques (1/2)
Les constructeurs et la plupart des méthodes peuvent générer
une IOException
Le serveur doit être démarré avant le client. Dans le cas
contraire, si le client se connecte à un serveur inexistant, une
exception sera levée après un time-out
Après la fermeture de la connexion, le serveur se met en
attente de la nouvelle connexion du même client ou d'un
autre.
Si plusieurs demandes de connexion arrivent simultanément,
une seule est acceptée et les autres sont mises en attente.
Pour accepter et traiter plusieurs connexions simultanées →
Multi-threader le serveur
25
26. Remarques (2/2)
Le client et le serveur doivent respecter un protocole
valide d'échange des données
Le client envoie un entier mais le serveur attend un flottant.
Le client attend des données du serveur qui lui même attend
des données du client → interblocage !
Attention à l'hétérogénéité des plateformes client et
serveur
Un client sur Intel envoie un entier little-endian,
Le serveur sur Sparc reçoit cet entier et le traite en big-endian.
26
27. Échange de données
2 types d'échanges possibles :
Échange en mode Ligne (chaînes de caractères)
Requêtes et réponses : une ou plusieurs lignes de texte (ASCII,
UTF-8, UniCode, ...)
En JAVA (Utilisation des Classes BufferedReader /
BufferedWriter )
Exemples: HTTP, SMTP,…
Échange en mode Bloc d'octets (de bytes)
Requêtes et réponses : blocs d'octets d'une taille et d'un format
connus de l'autre
En JAVA(Utilisation possible des Classes DataInputStream /
DataOutputStream )
Exemples : RPC, RMI, CORBA,...
27
28. Exemple : code serveur
public class EchoServer {
public static void main(String[] args) {
try {
ServerSocket listenSocket = new ServerSocket(Integer.parseInt(args[0]));
while(true)
{ Socket clientSocket = listenSocket.accept();
doService(clientSocket);
clientSocket.close(); } }
catch (Exception e) { ... }
static void doService(Socket clientSocket) throws IOException
{BufferedReader in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
PrintStream out = new PrintStream(clientSocket.getOutputStream());
while(true)
{ String theLine=in.readLine();
If(theLine==null) break;
out.println(theLine); } } // doService
} // class EchoServer
28
29. Exemple : code client
public class EchoClient {
public static void main(String[] args) {
Socket theSocket = null;
BufferedReader theInputStream = null;
BufferedReader userInput = null;
PrintStream theOutputStream = null;
String theLine = null;
try {
theSocket = new Socket(args[0], Integer.parseInt(args[1]));
theOutputStream = new PrintStream(theSocket.getOutputStream());
theInputStream = new BufferedReader(
new InputStreamReader(theSocket.getInputStream()));
userInput = new BufferedReader(
new InputStreamReader(System.in));
29
31. Exemple 2 : code client
Alphabet et langage
31
Le client lit du clavier (stream
inFromUser), et envoie au
serveur via la socket (stream
outToServer)
Le serveur lit le flux
provenant de la socket
Il convertit les données en les
mettant en majuscule et les
renvoit au client
Le client lit et affiche les
données modifiées lui arrivant
via la socket (stream
inFromServer)
32. Exceptions
java.net.BindException
Erreur de liaison à une adresse locale (le port est peut être déjà utilisé)
java.net.ConnectException
Refus de connexion par l'hôte (aucun "process" écoute le port, …)
java.net.NoRouteToHostException
L'hôte n'est pas joignable
java.net.ProtocolException
Erreur du protocole (TCP, …)
java.net.SocketException
Erreur du protocole (TCP, …)
java.net.UnknownHostException
Erreur de DNS
32
33. Gestion du parallélisme sur le
serveur
1er Cas: 1 seul processus serveur
Si clients sont multiples →traités en séquence
La longueur maximale de la file d’attente peut être
spécifiée lors de la création du socket serveur.
2ème cas: un schéma "multi-threads" :
Thread veilleur (serveur) doit créer explicitement un
nouveau thread exécutant (servant) à chaque nouvelle
connexion d'un client
Un socket différent "service client" est créé pour chaque
client
Le thread veilleur se remet ensuite en attente.
33
38. Socket en mode non connecté
Principe
Avant toute communication en mode UDP, il est nécessaire de
créer une socket aussi bien du coté client que du coté serveur.
L'émetteur envoie un datagramme (paquets de données sur
un socket que le récepteur écoute.
La classe java.net.DatagramSocket
Représente le socket local ou distant en mode non connecté.
La classe java.net.DatagramPacket
Représente un datagramme à envoyer ou reçu.
38
39. Client UDP (emetteur)
Crée le DatagramSocket
DatagramSocket ms = new DatagramSocket();
Construit un DatagramPacket
int len = 5;
byte[] data = new byte[len];
// data doit être "rempli" :
String message= " Hello "
data = message.getByte();
DatagramPacket outputPacket = new DatagramPacket(data,
data.length, receiverInetAddress, port);
Envoie le DatagramPacket au serveur
ms.send(outputPacket);
39
40. Serveur UDP (récepteur)
Crée le DatagramSocket lié à un port d ’écoute
DatagramSocket theSocket = new DatagramSocket(port);
Construit un DatagramPacket pour la réception
byte[] incomingData = new byte[MAXLEN];
// ce buffer est vide
DatagramPacket incomingPacket = new DatagramPacket
(incomingData , incomingData.length );
Réception du paquet puis utilisation
theSocket.receive(incomingPacket);
40
42. Code de l’emetteur: UDPSender
import java.net.*; import java.io.*;
public class UDPSender {
public static void main(String[] args) {
try {
InetAddress receiver = InetAddress.getByName(args[0]);
int port = Integer.parseInt(args[1]);
DatagramSocket theSocket = new DatagramSocket();
DataInputStream userInput = new DataInputStream(System.in);
while (true) {
String theLine = userInput.readLine();
if (theLine.equals(".")) break;
byte[] data = new byte[theLine.length()];
data=theLine.getBytes();
DatagramPacket theOutput =
new DatagramPacket(data, data.length, receiver, port);
theSocket.send(theOutput);
}} catch (Exception e) { System.err.println(e);}
42
43. Code du récépteur: UDPReceiver
import java.net.*; import java.io.*;
public class UDPReceiver {
public static void main(String[] args) {
try {// construction d'un DatagramSocket
int port = Integer.parseInt(args[0]);
DatagramSocket ds = new DatagramSocket(port);
// construction d'un DatagramPacket
int len = Integer.parseInt(args[1]);
byte[] buffer = new byte[len];
DatagramPacket incomingPacket = new DatagramPacket(buffer, buffer.length);
while (true) {
ds.receive(incomingPacket);
String s = new String(incomingPacket.getData(), 0, incomingPacket.getLength());
System.out.println(incomingPacket.getAddress()
+ " at port " + incomingPacket.getPort() + " says " + s); }
} catch (Exception e) { System.err.println(e); } } }
43
44. 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. Pour cela Java propose
trois constructeurs :
public DatagramSocket () throws SocketException
Crée un objet de type socket et l'attache à un port disponible de la machine locale.
Ce constructeur doit être utilisé dans les clients pour lesquels le port d'attachement
n'a pas besoin d'être connu.
public DatagramSocket (int port) throws SocketException
Crée un objet de type socket et l'attache au port UDP local passé en paramètre. En
particulier, ce constructeur doit être utilisé dans les serveurs pour lesquels le port
d'attachement a besoin d'être fixé préalablement afin qu'il soit connu des clients.
public DatagramSocket(int port, InetAddress laddr) throws SocketException
Crée un objet de type socket, l'attache au port UDP local passé en paramètre et à
une adresse spécifique de la machine locale. Ce constructeur n'est utile que si la
machine locale dispose de plusieurs adresses Internet.
44
45. Classe DatagramPacket (1/2)
Fournit deux constructeurs : un pour les paquets à recevoir,
l’autre pour les paquets à envoyer.
public DatagramPacket(byte buffer[], int taille)
Construit un objet pour recevoir un datagramme.
buffer correspond à la zone de réception
taille maximale des datagrammes à recevoir.
public DatagramPacket(byte buffer[], int taille,
InetAddress adresse, int port)
Construit un objet pour envoyer un datagramme.
buffer correspond à la zone d'envoie
taille correspond à la taille du datagramme à envoyer
adresse destinataire de la datagramme
port du UDP
45
46. Classe DatagramPacket (2/2)
Cette classe propose plusieurs méthodes pour
obtenir ou mettre à jour les informations sur le
paquet encapsulé.
46
Méthode Rôle
InetAddress getAddress () Renvoie l'adresse du serveur
byte[] getData() Renvoie les données
contenues dans le paquet
int getPort () Renvoie le port
int getLength () Renvoie la taille des données
contenues dans le paquet
setData(byte[]) Mettre à jour les données
contenues dans le paquet
47. Exercice
Ecrire un programme Java qui affiche sur l’écran les ports
d’écoute d’une machine distante donnée (en ligne de
commandes)
Rappel: les ports TCP d’une machine peuvent aller de 0 à
65535
47
48. Exercice
Ecrire un programme java qui affiche le contenu d’une page web
distante en utilisant son URL
Quelques indications
Instanciation de l’url: URL u = new URL(args[i]);
u.getPort() pour récupérer le port TCP
u.getProtocol() pour récupérer le protocole de l’url
(on accepte que http)
u.getHost() pour récupérer l’hôte distant
u.getFile() pour récupérer le nom de la page demandée
Requête HTTP
"GET " + u.getFile() + " HTTP/1.0rn“
"Accept: text/plain, text/html, text/*rn“
"rn"
48