Programmation par Sockets. Sockets en Java.

publicité
Programmation par Sockets.
Sockets en Java.
Andrey SADOVYKH
[email protected]
http://sadovykh.free.fr/cnam/
CNAM Réseaux C3 – 2005 - ©Andrey Sadovykh
2
Plan du cours
Principes de Sockets
Sockets en Java
TD - Carnet d’Adresses partagé – Sockets
TCP
Principes de Sockets
CNAM Réseaux C3 – 2005 - ©Andrey Sadovykh
4
Plans
Principes de Sockets
Définition de sockets
Protocoles Internet TCP et UDP
Format réseaux de données
Sockets UDP
Sockets TCP
Problème de Blocage
5
Principes des sockets
Socket == Fichier
write() pour envoyer
read() pour recevoir
Client
Server
Donnes-moi la page
Index.html
ports
ports
yahoo.fr
80 HTTP
6
Définition des sockets
Une socket = {une famille ; un mode de
communication ; un protocole}
Exemple de familles de sockets :
Exemple de modes de communication :
processus sur la même station Unix : sockets locales (AF_UNIX en
C)
processus sur des stations différentes à travers Internet : sockets
Internet (AF_INET en C)
Datagrames – ou mode non connecté
Flux de données – ou mode connecté
Etc.
Exemple de protocoles de sockets : IP, UDP, TCP,
…
7
Protocoles Internet
Application
AF_INET: UDP, TCP
IP
TCP:
1 2 3 4
1
Mode avec connexion:
Envoie par séquences
L’ordre d’envoie est respecté
La livraison est garantie
La perte de connexion est détecté
2
3
4
UDP:
Ethernet
1 2 3 4
2 1 3 4
Mode sans connexion:
Envoie par paquets
Réception par des plusieurs destinataires est possible
Ni livraison ni l’ordre de séquence ne sont pas garantis,
même si la probabilité est 10-6
8
Format Réseau –
Little / Big Endians
short /* (2 Octets) */ long /* (8 Octets) */
Exemple: short n=3; /* 11 en binaire*/
Motorola
Intel
00…0 0…11
0…11 00…0
host byte order
Big Endians
host byte order
Little Endians
Réseau
00…0 0…11
network byte order
Big Endians
Un des problèmes d’interopérabilité le plus connu.
Les représentation de donnée sur chaque
d’extrémités peuvent être différentes.
En C, une conversion vers format réseau (network byte
order) est nécessaire.
9
Sockets UDP
Étapes d’utilisation de sockets lors de communication
client-serveur en UDP :
le serveur et le client ouvrent chacun une « socket »
le serveur la nomme (il l’attache à un de ses ports (un port précis))
le client ne nomme pas sa socket (elle sera attachée
automatiquement à un port lors de l’émission)
le client et le serveur dialogue : write(…) et read(…)
finalement toutes les sockets doivent être refermées
Les deux extrémités n’établissent pas une connexion :
elles ne mettent pas en oeuvre un protocole de maintien de
connexion
si le processus d’une extrémité meurt l’autre n’en sait rien !
10
Étapes d’utilisation de sockets mode UDP:
serveur reçoit les données
Initialisation:
Serveur
Client
socket ()
socket ()
bind()
attribution d’un port
Dialogue:
read()
write()
Fermeture:
close()
close()
11
Sockets TCP
Étapes d’utilisation de sockets lors de communication
client-serveur en TCP :
le serveur et le client ouvrent chacun une « socket »
le serveur la nomme (il l’attache à un de ses ports (un port précis))
le client n’est pas obligé de la nommer (elle sera attachée
automatiquement à un port lors de la connexion)
le serveur écoute sa socket nommée
le serveur attend des demandes de connexion
le client connecte sa socket au serveur et à un de ses ports (précis)
le serveur détecte la demande de connexion
une nouvelle socket est ouverte automatiquement
le client et le serveur dialogue sur la nouvelle socket (read, write)
le serveur attendre de nouvelles demandes de connexions
finalement toutes les sockets doivent être refermées
12
Étapes d’utilisation de sockets mode TCP:
serveur reçoit les données
Initialisation:
Serveur
Client
socket ()
socket ()
bind()
attribution d’un port
listen()
mode d’écoute
Connexion:
Dialogue:
Fermeture:
accept()
connect ()
une nouvelle socket !!!
read()
write()
Communication
sur la nouvelle socket
Communication
sur la nouvelle socket
close()
close()
13
Problème de blocage
Serveur
Client
socket ()
socket ()
bind()
attribution d’un port
listen()
mode d’écoute
Blocage:
Blocage:
accept()
connect ()
read()
write()
Communication
sur la nouvelle socket
Communication
sur la nouvelle socket
close()
close()
14
Solution: nouveau processus
Processus
Principal:
Serveur:
accept()
Processus
Secondaires: Traitement
de communication
une nouvelle socket !!!
while(…)
fork()
…
socket1
read()
send()
…
socket2
read()
send()
…
Client1
données
données
Client2
15
Sockets TCP non bloquant
Étapes d’utilisation de sockets lors de communication
client-serveur en TCP :
le serveur et le client ouvrent chacun une « socket »
le serveur la nomme (il l’attache à un de ses ports (un port précis))
le client n’est pas obligé de la nommer (elle sera attachée automatiquement à un port lors de la
connexion)
le serveur écoute sa socket nommée
le serveur attend des demandes de connexion
le client connecte sa socket au serveur et à un de ses ports (précis)
le serveur détecte la demande de connexion
une nouvelle socket est ouverte automatiquement
le serveur crée un processus pour dialoguer avec le client
le nouveau processus continue le dialogue sur la nouvelle
socket
le serveur attende en parallèle de nouvelles demandes de
connexions
finalement toutes les sockets doivent être refermées
Programmation par sockets
en Java
CNAM Réseaux C3 – 2005 - ©Andrey Sadovykh
17
Plan
Les prérequis:
Flux de données Java Sockets TCP
Sérialisation Préparation de données
Optionnellement: Threads Serveur TCP nonbloquant (voir les support )
Spécificités
Sockets UDP en Java
Sockets TCP en Java
18
Pré requis
java.io - les entrées-sorties (pp. 72-80)
java.io.File – opérations sur les fichiers (pp. 8183)
InputStream / OutputStream – flux et opérations sur les
flux de données
BufferedInputStream/BufferedOutputStream
DataInputStream/DataOutputStream
FileInputStream / FileOutputStream (voir les corrections)
Sérialisation (pp. 97-102)
Interface java.io.Serializable (voir les corrections)
ObjectInputStream/ObjectOutputStream (voir les
corrections)
19
Spécificités
Il existe toujours des socket UDP et TCP
Les sockets TCP doivent être associées à des «
flux » (in et out)
Les principes sont les mêmes
Les sockets sont des objets (bien sur!)
facilité de lecture et d’écriture
Certaines opérations sont devenues implicites
De nouvelles opérations sur des « flux »
apparaissent
Bibliothèque java.net.*
20
Spécificités: Initialisation
client
UDP
TCP
serveur
client
serveur
DatagramSocket()
DatagramSocket(port)
Socket(ServerName, ServerPort)
ServerSocket(port)
21
Sockets UDP en Java
class DatagramSocket : (coté client et coté serveur)
Constructeur :
Méthodes :
DatagramSocket() : creation d’une socket UDP, libre
close() : ferme la socket.
receive(DatagramPacket p) : reçoit un « DatagramPacket » de cette
socket.
send(DatagramPacket p) : envoit un « DatagramPacket » sur cette
socket.
class DatagramPacket :
Constructeur :
DatagramPacket(byte[] buf, int InetAddress address,int port) :
creation d’un packet à destination d’une machine et d’un port spécifiés
…
22
Sockets TCP en Java (client)
class Socket : (coté client, et coté serveur en
partie)
Constructeur :
connect()
est implicite
Méthodes :
Socket(String host, int port) : creation d’une socket TCP
connectée sur le port et la machine hôte spécifiés.
close() : ferme la socket.
OutputStream getOutputStream() : revoie un flux de sortie
pour cette socket.
IntputStream getIntputStream() :revoie un flux d’entrée pour
cette socket.
class OutputStream :
Méthodes :
write(byte[] buffer) : écrit
dans le flux.
close() : ferme flux.
class InputStream :
Méthodes :
read(byte[] buffer) :
lit le flux.
close() : ferme flux.
23
Sockets TCP en Java (serveur)
class ServerSocket : (coté serveur)
Constructeur :
bind()
est implicite
ServerSocket(int port) : creation d’une socket TCP connectée
sur le port spécifié de la machine hôte.
Méthodes :
close() : ferme la socket.
OutputStream getOutputStream() : revoie un flux de sortie
pour cette socket.
IntputStream getIntputStream() : revoie un flux d’entrée pour
cette socket.
Socket accept() : écoute la socket et attend une requête de
connection, retourne une nouvelle socket sur laquelle écouter le
nouveau client (et lui seul)
listen()
est implicite
Exemple – Sockets en Java
CNAM Réseaux C3 – 2005 - ©Andrey Sadovykh
25
Développement d’une application
socket – une approche
Définition d’un protocole d’application
1.
2.
3.
Définition d’opérations (fonctions)
Définition de messages d’entrée et de sorti, qui sont
associés aux opérations
Définition de tailles des messages
Définition de moyennes de distinction des messages
(codes de message, port différant, …)
Implémentation de sérialisation/dessérialisation
des messages.
Déploiement des mécanismes réseaux (sockets)
Exemple : Server Echo TCP.
1 opération
Description : Client envoie une chaîne de caractères au Serveur.
Serveur la renvoie en y ajoutant « C’est l’écho ».
Opérations : Echo
Message d’entrée - String echoString de
taille variable, ce que nécessite envoie de taille actuelle avant de chaque message.
Message de sortie – String reponse = « C’est l’écho :» + echoString
26
taille variable, ce que nécessite envoie de taille actuelle avant de chaque message.
Distinction de messages : Pas nécessaire, car un seul messages d’entrée et un
seul message de sortie sont possible. De plus, opération est la seule.
Sérialisation :
OutputByteStream obs = new OutputByteStream ();
obs. write (echoString.getBytes());
Dessérialisation :
InputByteStream ibs = new InputByteStream ();
Ibs. read(echoString.getBytes());
Exemple : Implantation socket
coté Serveur
Serveur:
ouvre port 8080
ServerSocket server = new ServerSocket (8080);
attend une connexion;
Socket nouvelleSocket = server.accept();
lit une chaîne de caractères;
InputStream fluxEntree = nouvelleSocket.getInputStream();
byte taille [] = new byte[1];
fluxEntree.read(taille);
byte buffer [] = new byte [taille[0]];
fluxEntree.read(buffer);
renvoie cette chaîne en y ajoutant « C’est l’écho ».
String echo = "C'est l'echo:"+ new String (buffer);
OutputStream fluxSortie = nouvelleSocket.getOutputStream();
byte taille2 = (byte) echo.getBytes().length;
fluxSortie.write(taille2);
fluxSortie.write(echo.getBytes());
ferme toutes les connexions
nouvelleSocket.close();
server.close();
27
Exemple : Implantation socket
coté Client
Client
Crée une connexion avec Serveur
Socket client = new Socket (« localhost »,8080);
Envoie une chaîne de caractères
String request = "Salut!";
byte taille = (byte)request.getBytes().length;
OutputStream fluxSortie = client.getOutputStream();
fluxSortie.write(taille);
fluxSortie.write(request.getBytes());
Reçoit une chaîne de caractères
InputStream fluxEntree = client.getInputStream();
byte [] taille2 = new byte[1];
fluxEntree.read(taille2);
byte [] buffer = new byte [taille2[0]];
fluxEntree.read(buffer);
Ferme toutes la connexions
client.close();
28
29
Exemple : Source Serveur
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class EchoServer {
public static void main(String[] args) {
try {
//
nouvelle socket sur le port 8080
ServerSocket server = new ServerSocket(8080);
System.out.println("Serveur est demarre...");
//
accepter les demandes de connexion
Socket nouvelleSocket=server.accept();
//
lire les donnees
InputStream fluxEntree = nouvelleSocket.getInputStream();
byte taille [] = new byte[1];
fluxEntree.read(taille);
byte buffer [] = new byte [taille[0]];
fluxEntree.read(buffer);
System.out.println("Echo request:"+new String(buffer));
//
preparer la reponse
String echo = "C'est l'echo:"+ new String (buffer);
//
ecrire les donnee
OutputStream fluxSortie = nouvelleSocket.getOutputStream();
byte taille2 = (byte) echo.getBytes().length;
fluxSortie.write(taille2);
fluxSortie.write(echo.getBytes());
//
fermer nouvelleSocket
nouvelleSocket.close();
//
fermer socket principale
server.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
30
Exemple : Source Client
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class EchoClient {
public static void main(String[] args) {
try {
// creer et connecter une Socket cliente
Socket client = new Socket ("localhost",8080);
// ecire les donnees
String request = "Salut!";
byte taille = (byte)request.getBytes().length;
OutputStream fluxSortie = client.getOutputStream();
fluxSortie.write(taille);
fluxSortie.write(request.getBytes());
// lire
InputStream fluxEntree = client.getInputStream();
byte [] taille2 = new byte[1];
fluxEntree.read(taille2);
byte [] buffer = new byte [taille2[0]];
fluxEntree.read(buffer);
System.out.println("Response:"+new String(buffer));
// fermer socket cliente
client.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Complément : Sérialisation en
Java – Puissance de Java
CNAM Réseaux C3 – 2005 - ©Andrey Sadovykh
32
Principe
Java défini une interface java.io.Serializable pour rendre
les objet sérialisable
Il suffit que votre classe à sérialiser implante
java.io.Serializable, car tous les types est presque toutes
les classe de bibliothèques Java sont sérialisable.
Utilisez ObjectOutputStream.writeObject(Object
votreObjetSerializable) pour écrier dans le flux sortant.
et ObjectInputStream.readObject(Object obj) pour lire le
flux entrant.
Attention Interopérabilité : Cette approche n’est que
utilisable si les deux extrémités sont des Applications
Java
33
Utilité pour les sockets
!!! La transmission de la taille d’un Objet est
géré automatiquement.
Lecture:
Récupérez le flux d’entrée
InputStream socketInput =mySocket.getInputStream();
Convertissez le en un flux d’Objet
ObjectInputStream myStream = new ObjectInputStream (socketInput );
Lisez votre Objet
MyClass myObj = new MyClasse();
myObj = (MyClasse) myStream.readObject();
Voir ExempleSocket2
34
Exemple 2: Source Serveur
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class EchoServer {
public static void main(String[] args) {
try {
//
nouvelle socket sur le port 8080
ServerSocket server = new ServerSocket(8080);
System.out.println("Serveur est demarre...");
//
accepter les demandes de connexion
Socket nouvelleSocket=server.accept();
//
lire les donnees
InputStream is = nouvelleSocket.getInputStream();
ObjectInputStream fluxEntree= new ObjectInputStream(is);
String request;
request=(String)fluxEntree.readObject();
System.out.println("Echo request:"+request);
String echo = "C'est l'echo:"+ request;
//
ecrire les donnee
OutputStream os = nouvelleSocket.getOutputStream();
ObjectOutputStream fluxSortie = new ObjectOutputStream(os);
fluxSortie.writeObject(echo);
//
fermer nouvelleSocket
nouvelleSocket.close();
//
fermer socket principale
server.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
35
Exemple 2: Source Client
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
public class EchoClient {
public static void main(String[] args) {
try {
// creer et connecter une Socket cliente
Socket client = new Socket("localhost", 8080);
// ecire les donnees
String request = "Salut!";
OutputStream os = client.getOutputStream();
ObjectOutputStream fluxSortie = new ObjectOutputStream(os);
fluxSortie.writeObject(request);
// lire les donnes
String response;
InputStream is = client.getInputStream();
ObjectInputStream fluxEntree = new ObjectInputStream(is);
response = (String) fluxEntree.readObject();
System.out.println("Response:" + response);
// fermer socket cliente
client.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Téléchargement