Chapitre4-Les Sockets
Chapitre4-Les Sockets
Chapitre4-Les Sockets
d’Application Client-Serveur
1
Rappel sur les réseaux
2
Rappel sur les réseaux
Modèle OSI-TCP/IP
3
Rappel sur les réseaux
Couche réseau (internet) :
Fonctions principales :
Routage et adressage des paquets.
Contrôle de flux des paquets.
IP (Internet Protocol) : Protocole de commutation de paquets.
Chaque machine reliée à un réseau IP se voit attribuer une adresse, dite
« adresse IP ».
Exemple : 172.168.13.4
Paquet IP :
Entête IP Données
L'en-tête contient :
L'adresse IP de la machine source.
L'adresse IP de la machine destination.
La taille du paquet.
4
Rappel sur les réseaux
IP ne garantit pas que les paquets émis soient reçus par leur
destinataire. Deux protocoles évolués ont été bâtis au-dessus d'IP :
UDP (User Datagram Protocol)
TCP (Transmission Control Protocol)
Couche Transport :
S’occupe de l’acheminement de l’information. Ce transport doit être
transparent.
Le protocole UDP :
Protocole très simple.
Non fiable (les segments UDP peuvent être perdus).
Sans connexion (chaque segment UDP est traité indépendamment
des autres).
Ajoute deux fonctionnalités au-dessus d'IP :
L'utilisation de numéros de ports par l'émetteur et le destinataire.
Contrôle d'intégrité sur les paquets reçus. 5
Rappel sur les réseaux
Le protocole TCP :
Etablis un canal bidirectionnel entre deux processus.
Protocole fiable.
Orienté connexion.
Permet l'acheminement sans erreur de paquets.
Contrairement à UDP,
TCP gère lui-même le découpage des données en
paquets, le recollage des paquets dans le bon ordre et
la retransmission des paquets perdus si besoin.
TCP s'adapte également à la bande passante
disponible en ralentissant l'envoi des paquets.
6
Rappel sur les réseaux
Paquet UDP ou TCP :
Composé de deux parties :
L'en-tête TCP ou UDP : contient les numéros de ports ainsi que le
code de contrôle d'intégrité.
Le contenu du paquet.
Datagramme UDP
Datagramme TCP 7
Rappel sur les réseaux
9
Rappel sur les réseaux
10
Rappel sur les réseaux
La couche application :
Contient tous les protocoles de haut niveau.
HTTP (HyperText Transport Protocol) : Protocole du web (Echange
de requête/réponse entre un client et un serveur web)
FTP (File Transfer Protocol) : Protocole de manipulation de fichiers
distants (Transfert, suppression, création, …)
TELNET (TELetypewriter Network Protocol) : Système de terminal
virtuel (ouverture d'une session distante)
SMTP (Simple Mail Transfer Protocol) : Service d'envoi de courrier
électronique
DNS (Domain Name System) : Assure la correspondance entre un
nom symbolique et une adresse IP
SNMP (Simple Network Management Protocol) : Protocole
d'administration de réseau (interrogation, configuration des
équipements, …) 11
Les sockets
12
Introduction aux sockets
13
Introduction aux sockets
14
Introduction aux sockets
Une socket est une paire: [ adresse IP, numéro de port ].
Disponible dans différents langages (C, Java, VB, ...)
Cette interface permet la programmation d’applications
client/serveur.
Il existe différents types de sockets associées aux différents services de
transport:
Stream sockets (TCP) :
Etablir une communication en mode connecté.
Si connexion interrompue : applications informées.
Datagram sockets (UDP) :
Etablir une communication en mode non connecté.
Données envoyées sous forme de paquets indépendants de toute
connexion.
Plus rapide, moins fiable que TCP.
Raw sockets :
Utilise directement IP ou ICMP (ex. ping).
15
Utilisation de Socket avec TCP
(mode connecté)
16
Utilisation de Socket avec TCP
(mode connecté)
1. Pour que le client puisse contacter le
serveur:
Le processus serveur doit déjà tourner.
Le serveur doit avoir créé au préalable une
socket pour recevoir les demandes de
connexion des clients.
17
Utilisation de Socket avec TCP
(mode connecté)
2. Le client contacte le serveur :
En créant une socket locale au client.
En spécifiant une adresse IP et un numéro de
port pour joindre le processus serveur.
18
Utilisation de Socket avec TCP
(mode connecté)
3. Le client demande alors l'établissement d'une
connexion avec le serveur.
4. Si le serveur accepte la demande de connexion :
Il crée une nouvelle socket "socket service client"
permettant le dialogue avec ce client.
Ceci permet au serveur de dialoguer avec plusieurs clients.
Les deux sockets client et socket service clients sont
connectées entre elles.
19
Utilisation de Socket avec TCP
(mode connecté)
20
Utilisation de Socket avec TCP
(mode connecté)
21
Utilisation de Socket avec TCP
(mode connecté)
Attention : les émissions/réceptions ne sont
pas synchrones
read(m) : lecture d'au plus m caractères
write(m) : écriture de m caractères
22
Utilisation de Socket avec UDP
(mode non connecté)
Étapes de communication:
1. Pour que le client puisse contacter le serveur :
il doit connaître l'adresse du socket du serveur
le serveur doit avoir créé la socket de réception
2. Le client envoie sa requête en précisant, lors de chaque envoi,
l'adresse du socket destinataire.
3. Le datagramme envoyé par le client contient l'adresse du socket
émettrice (port, @IP).
4. Le serveur traite la requête et répond au client en utilisant l'adresse
du socket émettrice de la requête.
23
Utilisation de Socket avec UDP
(mode non connecté)
24
Utilisation de Socket avec UDP
(mode non connecté)
25
Récupérer une adresse IP en Java (
classe InetAddress)
Le package java.net de la plate-forme Java fournit une classe InetAddress
qui permet de récupérer et manipuler des adresses IP. Cette classe n'a pas
de constructeur, pour pouvoir avoir une instance de cette classe on a
besoin des méthodes de classe suivantes :
getLocalHost() : retourne un objet qui contient l'adresse IP de la
machine locale. Equivalent à getByName (null) ou getByName
("localhost").
getByName(String nom_machine) : retourne un objet qui contient
l'adresse IP de la machine dont le nom est passé en paramètre.
getAllByName(String nom_machine) : retourne un tableau d'objets qui
contient l'ensemble d'adresses IP de la machine qui correspond au nom
passé en paramètre.
Méthodes applicables à un objet de cette classe :
getHostName() : retourne le nom de la machine dont l'adresse est stockée
dans l'objet.
getAddress() : retourne l'adresse IP stockée dans l'objet sous forme d'un
tableau de 4 octets. 26
Récupérer une adresse IP en Java (
classe InetAddress)
Exemple de programme:
public class Adressage {
public static void main(String[] args) {
InetAddress LocaleAdresse ;
InetAddress ServeurAdresse;
try {
LocaleAdresse = InetAddress.getLocalHost();
System.out.println("L'adresse locale est : " +
LocaleAdresse );
ServeurAdresse = InetAddress.getByName("www.google.fr");
System.out.println("L'adresse du serveur du site google
est : " + ServeurAdresse);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
27
Création de socket TCP en JAVA
28
Création de socket TCP en Java
37
Socket TCP en Java
échange de messages
Exemple de programme (échange de message entre le client et le serveur)
Serveur2.java
public class Serveur2 {
public static void main(String[] args) {
ServerSocket s ;
Socket so;
PrintWriter out;
try {
s = new ServerSocket(2022);
System.out.println("Le serveur est à l'écoute du port
"+s.getLocalPort());
so = s.accept();
System.out.println("Un Client s'est connecté");
out = new PrintWriter(so.getOutputStream());
out.println("Vous êtes connecté Client !");
out.flush();
So.close();
s.close();
}catch (IOException e) {
e.printStackTrace();
}
}
}
38
Socket TCP en Java
échange de messages
Client2.java
public class Client2 {
public static void main(String[] args) {
Socket s1;
BufferedReader in;
try {
s1 = new Socket(InetAddress.getLocalHost(),2022);
System.out.println("Demande de connexion");
in = new BufferedReader (new InputStreamReader
(s1.getInputStream()));
System.out.println(in.readLine());
s1.close();
} catch (UnknownHostException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
}
} 39
Socket TCP en Java
Serveurs concurrents (Utilisation des threads)
Le type du serveur précédent est dit itératif (un client à la
fois), parce que les demandes de connexion sont satisfaites
l'une après l'autre. Si chaque connexion doit être durable
(avec un dialogue entre client et serveur, ou bien un temps
de calcul du serveur important), il faut plutôt réaliser un
serveur concurrent (plusieurs clients simultanément) à l'aide de
threads.
Après avoir créer un objet ServerSocket par le serveur, on
le place comme paramètre à un constructeur de la classe qui
implémente l’interface Runnable ou étend la classe Thread.
Chaque demande de connexion acceptée par le serveur provoque
la création et le lancement d'un nouveau thread qui prend en
charge la communication avec le client (on parle de socket TCP
non bloquant):
40
Socket TCP en Java
Serveurs concurrents (Utilisation des threads)
41
Socket TCP en Java
Serveurs concurrents (Utilisation des threads)
Exemple:
Serveur3.java
public class Serveur3 {
public static void main(String[] args) {
ServerSocket s;
try{
s = new ServerSocket(2022);
Thread t = new Thread(new AccepterClients(s));
t.start();
System.out.println(" Serveur concurrent prêt :");
}catch (IOException e){
e.printStackTrace();
}
}
}
42
Socket TCP en Java
Serveurs concurrents (Utilisation des threads)
Exemple: (suite)
public class AccepterClients implements Runnable{
private ServerSocket so;
private Socket sock;
private int nbrclient = 1;
public AccepterClients(ServerSocket s1){
so = s1;
}
public void run() {
try{
while(true){
sock = so.accept();
System.out.println("Le client numéro "+nbrclient+ " est
connecté !");
nbrclient++;
sock.close();
}
}catch(IOException e){
e.printStackTrace();
}
} 43
}
Socket TCP en Java
Serveurs concurrents (Utilisation des threads)
Exemple:
Client3.java
public class Client3 {
public static void main(String[] args) {
Socket soc;
try {
soc = new Socket("localhost",2022);
soc.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
44
Socket TCP en Java
échange d’objets
Une classe Sérializable:
public class Produit implements Serializable {
private int num;
private String designation;
private float prix;
public Produit(int num, String designation, float prix) {
this.num=num;
this.designation=designation;
this.prix=prix;
}
public String toString() {
return num+" -- "+designation+" -- "+prix;
}
} 45
Socket TCP en Java
échange d’objets
Pour sérialiser un objet (envoyer un objet vers le client)
OutputStream os=s.getOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(os);
Produit p=new Produit(1, "Table", 500);
oos.writeObject(p);
Pour lire un objet envoyé par le serveur( désérialisation)
InputStream is=s.getInputStream();
ObjectInputStream ois=new ObjectInputStream(is);
Produit p=(Produit)ois.readObject();
46
Création de socket UDP en JAVA
47
Création de Socket UDP en Java
49
Création de Socket UDP en Java
Classe DatagramPacket :
Permet de manipuler les datagrammes (structure des données en
mode UDP) échangés entre les correspondants.
Constructeurs :
public DatagramPacket (byte [] buf, int length,
InetAddress address, int port)
Crée un objet employé pour l’envoi d’un datagramme.
Paramètres :
buf : tableau d’octets contenant les données à envoyer.
length : taille du tableau ou des données à envoyer. (ne pas
préciser une taille supérieure à celle de buf).
address : adresse IP de la machine destinataire du datagramme.
port : port de destination.
50
Création de Socket UDP en Java
Exemple : (coté émetteur).
String message="BTS DSI";
byte [] data = message.getBytes( );
InetAddress adr ="192.168.1.22" ;
DatagramPacket paquet = new DatagramPacket(data,
data.length, adr, 2000);
Constructeur: public DatagramPacket (byte[ ] buf, int length)
Crée un objet employé pour la réception d’un datagramme.
Paramètres :
buf : tableau d’octets permettant la réception des données.
length : taille du tableau ou des données à recevoir (si la taille du tableau est
insuffisante, les données seront tronquées).
Exemple : Préparation du paquet de réception.
byte[] tampon =new byte[1024];
DatagramPacket paquet=new DatagramPacket (tampon,
tampon.length);
51
Création de Socket UDP en Java
Méthodes de la classe DatagramPacket :
public synchronized InetAddress getAddress ()
Retourne l'adresse stockée dans le paquet.
public synchronized int getPort ()
Retourne le port stocké dans le paquet.
public synchronized byte[] getData ()
Retourne les données stockées dans le paquet.
public synchronized int getLength ()
Retourne la taille des données stockées dans le paquet.
public synchronized void setAddress(InetAddress iaddr)
Modifie ou affecte l'adresse de destination.
public synchronized void setPort(int iport)
Modifie ou affecte le port de destination.
public synchronized void setData(byte ibuf[])
Modifie ou affecte la référence de la zone contenant les données.
public synchronized void setLength(int ilength) 52
Modifie ou affecte la taille de la zone contenant les données.
Création de Socket UDP en Java
Emission/Réception de datagrammes : (méthodes de la classe
DatagramSocket)
public void send (DatagramPacket p) throws IOException
Envoie un datagramme passé en paramètre.
Lève l’exception IOException en cas d’erreur.
Paramètre :
DatagramPacket p : datagramme prêt à l’envoi.
public void receive (DatagramPacket p) throws IOException
Attends la réception d’un datagramme et remplie le datagramme passé en
paramètre par les données reçues (cette méthode est bloquante).
Lève l’exception IOException en cas d’erreur.
Paramètre :
DatagramPacket p : datagramme vide prêt à recevoir les données
Il est possible de spécifier un délai d'attente maximal en réception. Pour
cela, il faut positionner une variable de timeout sur la socket au moyen
de la méthode setSoTimeout (int timeout).
53
Création de Socket UDP en Java
Fermeture de la Socket:
public void close () throws IOException
Ferme la socket et libère les ressources qui lui sont associées. La socket
ne pourra plus être utilisée ni pour envoyer, ni pour recevoir des
datagrammes.
Exemple de programmes : (communication UDP entre un client et
un serveur)
Dans cet exemple :
Le serveur attend une chaîne de caractères et la retourne.
Le client envoi une chaîne de caractères, attend que le serveur la lui
retourne et l'affiche.
54
Socket UDP en Java
Serveur.java :
public class Serveur{
final static int port = 8532;
final static int taille = 1024;
final static byte buffer[] = new byte[taille];
public static void main(String args[ ]) throws Exception{
DatagramSocket socket = new DatagramSocket(port);
socket.setSoTimeout(10000);
while(true){
DatagramPacket data = new DatagramPacket(buffer,buffer.length);
socket.receive(data);
String msg = new String(data.getData(),0,data.getLength());
if (msg.equals("fin")) break;
System.out.println("Le message suivant : " + msg) ;
System.out.println("à été reçu et renvoyé vers : " +
data.getAddress());
socket.send(data);
}
socket.close() ;
} 55
}
Socket UDP en Java
Client.java :
public class Client{
final static int taille = 1024;
static byte buffer[] = new byte[taille];
public static void main(String args[]) throws Exception{
BufferedReader InClavier = new BufferedReader(new InputStreamReader(System.in));
InetAddress adrServeur = InetAddress.getByName("127.0.0.1");
System.out.println("Tapez votre message : ");
String message = InClavier.readLine();
buffer = message.getBytes();
int lg = buffer.length;
DatagramPacket dataSent = new DatagramPacket(buffer,lg,adrServeur,8532);
DatagramSocket socket = new DatagramSocket();
System.out.println("Port local utilisé : " + socket.getLocalPort());
socket.send(dataSent);
DatagramPacket dataRecieved = new DatagramPacket(new byte[lg],lg);
socket.receive(dataRecieved);
System.out.println("Données reçues : " + new String(dataRecieved.getData()));
System.out.println("De : " + dataRecieved.getAddress() + " : " +
dataRecieved.getPort());
socket.close();
}
}
56
Socket UDP en Java
Remarque :
Si le serveur doit envoyer un message propre au client, Il doit tirer les informations
nécessaires (adresse et port du client) à partir du datagramme reçu du client.
Serveur.java :
class Serveur{
final static byte buffer[] = new byte[1024];
public static void main(String args[]) throws Exception{
DatagramSocket socket = new DatagramSocket(8532);
while(true){
DatagramPacket data = new DatagramPacket(buffer,buffer.length);
socket.receive(data);
String msg = new String(data.getData(),0,data.getLength());
System.out.println("Le message : " +msg+" à été reçu à partir de : " +
data.getAddress());
String confirmation = "Message reçu";
byte [ ]tampon = confirmation.getBytes();
InetAddress adr = data.getAddress();
int portClient = data.getPort();
DatagramPacket dataConf = new DatagramPacket(tampon,tampon.length,adr,portClient);
socket.send(dataConf);
}
}
57
}
Création de socket UDP Multicast
en Java
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).
Constructeurs :
Les constructeurs de cette classe sont identiques à ceux
de la classe DatagramSocket.
Abonnement/résiliation :
Pour pouvoir recevoir des datagrammes UDP envoyés
grâce au multicasting IP il faut s’abonner à une adresse
multicast. 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.
58
Création de socket UDP Multicast
en Java
public void joinGroup(InetAddress adresseMulticast)
throws IOException
Cette méthode permet de s’abonner à l’adresse multicast donnée.
Note : une 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 la socket n’était pas abonnée à cette adresse ou si il y
a un problème de configuration réseau.
59
Création de socket UDP Multicast
en Java
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ée à
l’émetteur du datagramme. Cela permet d’éviter que des datagrammes
tournent infiniment à l’intérieur d’un réseau IP.
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. 60
Création de socket UDP Multicast
en Java
Exemple: programme qui envoie et reçoit des datagrammes avec le multicasting IP
public class MulticastingIP{
public static void main(String args[ ]) throws SocketException, IOException{
String msg = "Bonjour ";
InetAddress groupe = InetAddress.getByName("228.5.6.7");
MulticastSocket s = new MulticastSocket(50000);
s.joinGroup(groupe);
DatagramPacket envoi = new DatagramPacket(msg.getBytes(), msg.length(),
groupe, 50000);
s.send(envoi);
while (true){
byte[] buf = new byte[1024];
DatagramPacket reception = new DatagramPacket(buf, buf.length);
s.receive(reception);
String texte=new String(buf, 0, reception.getLength());
System.out.println("Reception de : "+ reception.getAddress().getHostName()+
" sur le port "+reception.getPort()+" :\n"+ texte );
}
}
}
61
Création de socket UDP Multicast
en Java
Remarque :
Il est possible de créer un programme qui :
Offre le même service en UDP et en TCP sur le même
numéro de port.
Ou encore, d’inventer un protocole client/serveur qui
dialogue en UDP, et qui ouvre de temps en temps des
liaisons TCP pour transmettre de longs flux ; ou
inversement, qui ouvrent un canal TCP, et qui échangent
des informations de signalisation en UDP.
Exemple : (programme serveur recevant un message en
mode TCP, envoi confirmation vers l’expéditeur et transmet
le message reçu aux autres clients en mode multicast UDP).
62
Création de socket UDP Multicast
en Java
public class Serveur{
public static void main(String[ ] args) {
ServerSocket s ;
Socket soc ;
try {
s = new ServerSocket(2000);
soc = s.accept();
PrintWriter out = new
PrintWriter(soc.getOutputStream(),true);
BufferedReader in = new BufferedReader(new
InputStreamReader(soc.getInputStream()));
String message = in.readLine();
System.out.println(" Message reçu du client "+
soc.getInetAddress()+" : " + message);
out.println("Message reçu.");
soc.close();
s.close(); 63
Création de socket UDP Multicast
en Java
byte[ ] buffer = message.getBytes();
InetAddress groupe =
InetAddress.getByName("228.5.6.7");
MulticastSocket sm = new MulticastSocket(50000);
sm.joinGroup(groupe);
DatagramPacket paquet = new
DatagramPacket(buffer,buffer.length,groupe,50000);
sm.send(paquet);
}catch (IOException e){
e.printStackTrace();
}
}
}
64
65