Programmation client/serveur

publicité
Programmation
client/serveur
(sockets
(sockets sur
sur TCP/IP)
TCP/IP)
java.net
© Philippe GENOUD
UJF
Novembre 2006
1
Communications
Communications sur
sur Internet
Internet
Pour communiquer sur Internet les ordinateurs utilisent différents protocoles :
TCP (Transfert Control Protocol) protocole destiné aux applications nécessitant
une communication fiable et robuste. Permet d’établir une connexion fiable
entre deux machines
pas de perte d’information
respect de l’ordre dans lequel les informations sont envoyées et reçues
les applications sont prévenues si la communication est interrompue
UDP (User Datagram Protocol) protocole qui permet l’envoi de paquets
indépendants (datagrammes) d’un ordinateur à un autre sans garantie quand à
leur arrivée
plus rapide mais moins fiable
© Philippe GENOUD
UJF
Novembre 2006
2
1
Applications
Applications réseau
réseau Java
Java
Application Java
Applications
HTTP, ftp, telnet, …
java.net
Transport
Package standard qui permet aux
programmes Java de réaliser des
communications réseau de façon
indépendante du système
TCP, UDP, …
De nombreuses applications
se basent sur ces protocoles
Réseau
IP, …
Couche de base
Object
Device driver
Couche Physique
Ethernet, …
InetAdress
Représente une
adresse IP
Socket
DatagramSocket
URL
ServerSocket
Connexions TCP/IP
DatagramPacket
Connexions UDP
URLConnection
Connexions à un
serveur HHTP
HttpURLConnection
© Philippe GENOUD
Novembre 2006
UJF
3
Sockets
Sockets et
et applications
applications Client/Serveur
Client/Serveur
Serveur
Serveur
port
1) Le programme serveur tourne sur une machine hôte spécifique
Client
Client
Le programme serveur possède un « socket » associé
à un numéro de port spécifique
Le serveur est en attente d’une demande de connexion
Serveur
Serveur
port
2) Le client effectue une demande de connexion
demande de
connexion
Client
Client
Le client connaît la machine hôte
(hostname ou numéro IP) et le
numéro de port auquel est connecté
le serveur
nn
ex
ion
Attribution d’un nouveau socket (et
d’un nouveau numéro de port)
© Philippe GENOUD
Client
Client
Attribution d’un socket
(et d’un numéro de port)
co
port
port
Serveur
Serveur
port
3) Le serveur accepte la connexion
2 flots de données sont établis entre les deux machines :
Le client et le serveur peuvent communiquer en écrivant ou en
lisant dans leur socket
UJF
Novembre 2006
4
2
Sockets
Sockets TCP
TCP dans
dans java.net
java.net
Assymétrie des connexions
Deux classes pour les sockets en mode connecté (TCP)
ServerSocket
Encapsule le socket du serveur
Pour s’initialiser un ServerSocket a besoin d’un numéro de port
Attente et acceptation des demandes de connexion
Socket
Encapsule le socket du client
Pour s’initialiser un Socket a besoin d’une adresse IP et d’un
numéro de port
Demande de connexion avec le serveur
© Philippe GENOUD
5
Novembre 2006
UJF
Client
Client // Serveur
Serveur avec
avec java.net
java.net :: principe
principe
(1) Le serveur
enregistre
son service
(2) Le serveur se
met en attente de
connexion
Serveur
Le client doit être démarré après le serveur.
Si le serveur n’a pas encore démarré, levée
d’une exception après un time-out
ServerSocket svs =
new ServerSocket(port#)
Client
(3) Etablir la
connexion
Socket sc =
new Socket(host, port#)
svs.accept()
Sortie de accept
retour d’un objet
Socket
(4) Utilisation
du socket
(4) Utilisation
du socket
Socket s =
InputStream
OutputStream
OutputStream
socket
Canal TCP
socket
InputStream
(5’) Fermer la
connexion
(5) Fermer la
connexion
s.close()
sc.close()
(6) Fermer le
service
svs.close()
close() ferme (détruit) le socket côté
client comme côté serveur
© Philippe GENOUD
UJF
Novembre 2006
6
3
Echanges
Echanges entre
entre client
client et
et serveur
serveur
Pour échanger des données le serveur et le client utilisent les flux d’entrée/sortie
fournis par leur socket :
Un objet java.io.InputStream pour la lecture retourné par la méthode
getInputStream() de Socket
Un objet java.io.OutputStream pour l’écriture retourné par la méthode
getOutputStream() de Socket
InputStream et OutputStream sont les classes du package java.io
proposant les primitives de base pour la lecture et l’écriture sur un flux d’entrée ou
de sortie
Deux types d’échanges sont possibles
Échanges en mode ligne (chaînes de caractères)
Echanges en mode bloc d’octets (bytes)
© Philippe GENOUD
UJF
7
Novembre 2006
Les
Les classes
classes d'entrées/sorties
d'entrées/sorties
Quelques classe du package java.io
Flux de sortie
Flux d'entrée
Flux d'octets
Flux de caractères
Reader
InputStream
FilterInputStream
FileInputStream
ByteArrayInputStream
BufferedInputStream
InputStreamReader
FileReader
Writer
OutputStream
FilterOutputStream
BufferedReader
FileOutputStream
ByteArrayOutputStream
BufferedOutputStream
InputStreamWriter
BufferedWriter
FileWriter
© Philippe GENOUD
UJF
Novembre 2006
8
4
Echanges
Echanges en
en mode
mode ligne
ligne
Requêtes et réponses sont constituées d’une ou plusieurs lignes de texte
(ASCII 7 bits, UTF-8, ISO-8859-1 (Latin-1) …)
Exemple : HTTP, SMTP, …
Utilisation des classes d’entrées/sorties du package java.io
BufferedReader
BufferedWriter
Attention :
Variation des terminateurs de ligne selon les OS
LF '\n' , CR '\r' , CRLF '\r' '\n'
Encodage n’est pas supporté par tous les langages
Certains protocoles (HTTP, SMTP …) limitent la longueur des lignes
© Philippe GENOUD
Novembre 2006
UJF
9
Echanges
Echanges en
en mode
mode ligne
ligne
Le flux d’entrée
1) Obtention d’un flux (stream) d’entrée simple :
définit les opérations de base
InputStream in = maSocket.getInputStream();
2) Création d’un stream convertissant
les octets (bytes) reçus en char
InputStreamReader isReader = new InputStreamReader(in);
BufferedReader
String
buffReader = new BufferedReader(isReader);
3) Création d’un stream de lecture avec
tampon pour lire ligne par ligne dans
un stream de caractères
line = buffReader.readLine();
4) Lecture d’une ligne (chaîne de
caractères)
© Philippe GENOUD
UJF
Novembre 2006
10
5
Echanges
Echanges en
en mode
mode ligne
ligne
Le flux de sortie
1) Obtention d’un flux (stream) de sortie simple :
définit les opérations de base
OutputStream out = maSocket.getOutputStream();
2) Création d’un stream convertissant
chaînes de caractères en octets (bytes)
PrintWriter writer = new PrintWriter(out);
writer.println(line);
3) Envoi d’une ligne (line est une String)
writer.flush();
4) Force l’envoi effectif sur le réseau
(force le « vidage » du buffer d’E/S)
© Philippe GENOUD
UJF
Novembre 2006
11
Echanges
Echanges en
en mode
mode bloc
bloc de
de données
données
Les données échangées sont des blocs d’octets (bytes)
Les blocs sont d’une taille et d’un format connus des deux partenaires
(le serveur et le client)
un bloc peut avoir un entête qui contient un code d’opération et la
longueur des données (talle du bloc)
Exemple : RPC (Remote Procedure Call), RMI (Remove Method
Invocation), …
En Java, possibilité d’utiliser les classes
java.io.DataInputStream
java.io.DataOutputStream
© Philippe GENOUD
UJF
Novembre 2006
12
6
Protocole
Protocole d’échange
d’échange
Un protocole d’échange spécifiant la structure des requêtes et réponses
échangées par le client et le serveur doit être fixé.
Le client et le serveur doivent respecter ce protocole
Exemples de problèmes possibles
Format de données incorrect :
le client envoie un entier alors que le serveur attend un flottant
Interblocage :
le client attend des données du serveur et le serveur attend des
données du client
Hétérogénéité des plateformes client et serveur
différence de codage des données sur le serveur et le client
© Philippe GENOUD
13
Novembre 2006
UJF
Classes
Classes d’exceptions
d’exceptions de
de java.net
java.net
C Coté client
Principales classes d’exceptions de java.net
S Coté serveur
java.lang.Exception
C S
Problème générique de
connexion
Erreur du protocole TCP/IP
(problème de configuration
De la pile TCP/IP)
java.io.IOException
C S
SocketException
ProtocolException
UnknownHostException
ConnectException
C Erreur du DNS : L’adresse
BindException
IP de l’hôte ne peut être
déterminée
NoRouteToHostException
C
Refus de connexion par
l’hôte (aucun service
associé au numéro de port)
S
Un service est
déjà associé à
ce numéro de
port
© Philippe GENOUD
C
UJF
Novembre 2006
L’hôte n’est pas joignable.
Le routeur ne trouve pas le
serveur ou le serveur est
protégé par un firewall
14
7
Servir
Servir plusieurs
plusieurs clients
clients
ServeurSocket sSock = new ServeurSocket(4444);
Ne permet de servir qu’un
seul client
Socket s = sSock.accept();
// création d’une socket quand un demande de connexion a été acceptée
// traiter le client associé à cette connexion
…
Si plusieurs demandes de connexion arrivent simultanément, une seule est
acceptée, les autres sont mises en attente jusqu’au accept suivant (modulo
les time-out)
ServeurSocket sSock = new ServeurSocket(4444);
boolean arretServeur = false;
Sert plusieurs clients
MAIS consécutivement
while (! arretServeur) {
Socket s = sSock.accept();
// création d’une socket quand un demande de connexion a été acceptée
// traiter le client associé à cette connexion
…
}
Pour accepter et traiter plusieurs connexions simultanées, il faut multithreader le serveur
© Philippe GENOUD
UJF
Novembre 2006
15
Serveur
Serveur Multithreadé
Multithreadé
ServeurSocket sSock = new ServeurSocket(4444);
boolean arretServeur = false;
while (! arretServeur) {
Socket s = sSock.accept();
création d’une socket quand un demande de connexion a été acceptée
//
// traiter le client associé à cette connexion
…
Créer et Lancer un thread pour traiter ce client
}
Thread dispatcher
Attente demande
de connexion
Récupération de la socket
Dédiée à la connexion
Création et lancement
d’un thread de service
Thread de service Client 1
Prise en charge
charge du
Prise
Prise en
en charge du
du
dialogue avec
avec le client
client 1
dialogue
dialogue avec le
le client 1
1
Attente demande
de connexion
Récupération de la socket
Dédiée à la connexion
Création et lancement
d’un thread de service
Attente demande
de connexion
Thread de service Client 2
Prise en
en charge
charge du
du
Prise
dialogue
dialogue avec
avec le
le client
client
…
© Philippe GENOUD
UJF
Novembre 2006
16
8
Serveur
Serveur Multithreadé
Multithreadé
...
ServeurSocket sSock = new ServeurSocket(4444);
boolean arretServeur = false;
while (! arretServeur) {
Socket sock = sSock.accept();
// création d’une socket quand un demande de connexion a été acceptée
// traiter le client associé à cette connexion
// créer un thread pour traiter le client
…
ServiceClient sc = new ServiceClient(sock);
Thread threadService = new Thread(sc);
threadService.start();
}
...
<interface>
Runnable
ServiceClient
+ run()
+ ServiceClient(Socket s)
+ run()
Le traitement du
client
© Philippe GENOUD
UJF
Novembre 2006
17
Client
Client Multitread
Multitread
public class ServiceClient implements Runnable {
private Socket s;
private BufferedReader in;
private PrintWriter out;
private boolean termine = false;
...
public ServiceClient(Socket s) {
this.s = s;
in = new BufferedReader(
new InputStreamReader((s.getInputStream()));
out = new PrintWriter(s.getOutputStream());
...
}
Création des flux
d’entrée/sortie
pour communiquer
avec le serveur
public void run() {
Le traitement du
try {
client
while (! termine) {
String line = in.readLine();
...
Une gestion plus fine des
out.println(...);
exceptions est possible
}
Quel que soit le cas de figure
}
on essaye de fermer le
catch (IOException ioe) { ... }
socket avant de terminer le
finally {
traitement du client
try { s.close(); } catch (IOException ioe) { ... }
}
}
...
}
© Philippe GENOUD
UJF
Novembre 2006
18
9
Exercice
Exercice
(1) Ecrire une application client serveur minimale
Le client lit une chaîne au clavier qu’il envoie vers le serveur
Le serveur affiche la chaîne lue et renvoie un accusé de
réception au client qui l’affiche
Pour terminer sa session le client envoie la chaîne "fin"
(2) Modifier le programme de façon à avoir plusieurs clients
© Philippe GENOUD
UJF
Novembre 2006
19
10
Téléchargement