Télécharger la présentation
La présentation est en train de télécharger. S'il vous plaît, attendez
Publié parDamien Cloutier Modifié depuis plus de 7 années
1
Badr Benmammar badr.benmammar@gmail.com
Master Réseaux et Systèmes Distribués (RSD) Algorithmique des systèmes et applications réparties Programmation réseau en Java : Socket Badr Benmammar
2
Plan Définition Modes de communication Exemple de communication
Lecture directe du stream d’un socket Ecriture directe dans le stream d’un socket Lecture et écriture de plus haut niveau Transmission d’objet par les sockets Communications entre un applet Java et un serveur à l’aide des sockets Serveur multi-threads avec les sockets
3
Socket réseaux Définition : un socket réseaux est un modèle permettant la communication et la synchronisation interprocessus afin de permettre à divers processus de communiquer aussi bien sur une même machine qu’à travers un réseau. Les sockets sont mis au point par l’université de Berkeley (University of California) en 1986. L’interface originelle de Berkeley était pour le langage C, mais depuis les sockets ont été implémentées dans de nombreux langages. Implémentation de Sun pour Java Class Socket dans le package java.net à partir de J2SE 1.4 (6 février 2002).
4
Modes de communication
Les sockets utilisent directement les services de la couche transport du modèle OSI (protocoles UDP ou TCP), elle-même utilisant les services de la couche réseau (protocole IP). Les sockets permettent à deux processus de communiquer entre eux à travers d’une liaison identifiée par une adresse IP et un numéro de port. Mode connecté (comparable à une communication téléphonique), utilisant le protocole TCP. Dans ce mode de communication, une connexion durable est établie entre les deux processus, de telle façon que l’adresse de destination n’est pas nécessaire à chaque envoi de données. Mode non connecté (analogue à une communication par courrier), utilisant le protocole UDP. Ce mode nécessite l’adresse de destination à chaque envoi, et aucun accusé de réception n’est donné.
5
Communication par socket
La communication nécessite 2 sockets : 1 pour chacun des 2 programmes communicants via le réseau. 1 socket pour le client. 1 socket pour le serveur (il existe un deuxième socket pour la connexion coté serveur). A chaque mode de communication IP utilisé : UDP ou TCP, correspond un type de socket.
6
Implémentation des Sockets en Java
En Java, chaque instance de la classe Socket est associé à un objet de la classe InputStream (pour lire sur le socket) et à un objet de la classe OutputStream (pour écrire sur le socket).
7
Côté du serveur Le serveur utilisera deux types de sockets.
Le premier, appelé socket de connexion sert à attendre un client. En Java, créer un socket de connexion peut se faire simplement en instanciant un objet de la classe ServerSocket du package java.net. ServerSocket conn = new ServerSocket(10080); 4 constructeurs pour ServerSocket. Le second, appelé socket de communication sert à dialoguer avec le client. Une fois le socket de connexion créé, il suffit de lui demander d’attendre un client et de récupérer le socket de communication qui permettra de dialoguer avec le client. Socket comm = conn.accept(); On peut ensuite communiquer avec le client en utilisant les flux d’entrée et de sortie associés au socket.
8
Class ServerSocket Implémente les sockets de connexion du côté du serveur. ServerSocket (numeroPort) : crée un objet ServerSocket sur ce numéro de port. accept() : attend une connexion d’une machine cliente, à l’arrivée d’une demande de connexion d’une machine cliente, un socket est crée pour connecter ce client au serveur. C’est l’objet retourné par la méthode bloquante accept(). Avant et après la méthode accept() :
9
Quelques méthodes de ServerSocket
ServerSocket (numeroPort, int backlog) : crée un objet ServerSocket sur ce numéro de port avec une queue d’attente de connexion de taille spécifiée par l’entier backlog. Par défaut, la taille est 50. Les demandes de connections, quand la queue est pleine, sont rejetées et provoque une exception du coté du client. accept() : attend une connexion d’une machine cliente. close() : ferme le ServerSocket et toutes les sockets en cours obtenus par sa méthode accept. isClosed() : indique si le socket est fermé. getLocalPort() : retourne le numéro de port local. InetAddress getInetAddress() : retourne l’adresse du serveur. InetAddress représente une adresse IP et éventuellement le nom de la machine. Quelques méthodes : getHostName() : retourne le nom d’hôte. getHostAdress() : retourne l’IP sous forme de String.
10
Exemple avec InetAddress
Objectif : trouver l’adresse IP correspondant à un nom de machine passé comme argument sur la ligne de commande. import java.net.* ; public class ResoudreNom{ public static void main(String[] args){ InetAddress adresse ; try { adresse=InetAddress.getByName(args[0]); System.out.println(adresse.getHostAddress()) ; }catch(UnknownHostException e) { } } Deux méthodes de la classe InetAddress sont illustrées dans cet exemple : getByName() : permet de résoudre l’adresse IP d’une machine étant donné son nom. getHostAddress() : permet de retourner sous forme de chaîne de caractères l’adresse IP mémorisé dans l’objet de type InetAddress. Exécution : java ResoudreNom localhost java ResoudreNom
11
Côté du client Contrairement au serveur, le client n’utilise qu’un seul socket : le socket de communication. Connexion au serveur et obtention d’un socket de communication. Socket comm = new Socket ("localhost", 10080). Le constructeur Socket est une méthode bloquante coté client. On peut ensuite communiquer avec le serveur en utilisant les flux d’entrée et de sortie associés au socket.
12
Class Socket 9 constructeurs dont 2 « Deprecated », donc 7 constructeurs, parmi eux : Socket (String host, int port) Socket (InetAddress address, int port) Utilise l’adresse IP : InetAdress Quelques méthodes : close() : ferme proprement le socket est susceptible de lever une exception UnknownHostException. getOutputStream() : retourne un flux de sortie OutputStream pour le socket. getInputStream() : retourne un flux d’entrée InputStream pour le socket. getPort() : retourne le numéro de port distant auquel le socket est connecté. InetAddress getInetAddress() : retourne l’adresse de la machine distante.
13
Quelques méthodes de Socket
isClosed() : indique si le socket est fermé. isConnected() : retourne l’état de la connexion du socket. connect(SocketAddress adresseSocket) : connecte le socket au serveur. connect(SocketAddress adresseSocket, int timeout) : connecte le socket au serveur avec une valeur d’expiration en millisecondes. Lève une SocketTimeoutException si le délai à expiré. SocketAddress est une classe abstraite. InetSocketAddress hérite de SocketAddress est une classe représentant une InetAddress et un port. InetSocketAddress(InetAddress ina, int port) InetSocketAddress(String hostName, int port) getAddress() getHostname() getPort()
14
Créer un socket avec un timeout en utilisant connect
Socket sock = null; try { int port = XYZ; int timeOut = 3000; SocketAddress sockAddr = new InetSocketAddress("host", port); sock = new Socket(); // Le constructeur de Socket crée un socket sans connexion. sock.connect(sockAddr, timeOut); // Le délai est en millisecondes donc 3 secondes. } catch (UnknownHostException e) { } catch (SocketTimeoutException e) { } catch (IOException e) { } Une demande de connexion bloque jusqu’à ce que la connexion soit établie ou que le délai d'expiration est écoulé, si le délai à expiré, une SocketTimeoutException est levée.
15
Exemple de communication par socket
Une boucle : Le client envoie un message au serveur. Le serveur confirme la réception et demande le mot suivant. Pour se déconnecter, le client envoie le caractère « q ». bonjour recu :bonjour suivant ? Client Serveur
16
Exemple de communication par socket
sockOut = new PrintWriter(sock.getOutputStream(), true) pour émission //forcer l’écriture sockIn = new BufferedReader(new InputStreamReader(sock.getInputStream())) pour réception sockOut = new PrintWriter(sock.getOutputStream(), true) pour émission //forcer l’écriture sockIn = new BufferedReader(new InputStreamReader(sock.getInputStream())) pour réception Client Serveur sockOut.println(message) recu = sockIn.readLine() String recu = sockIn.readLine() System.out.println("serveur -> client :" + recu) System.out.println("recu :"+recu) sockOut.println("suivant ? ")
17
Serveur Réception : synchrone Emission : asynchrone Pour les sockets :
import java.net.*; import java.io.*; class ServerEcho { public static void main(String args[]) { ServerSocket server = null; try { server = new ServerSocket(7777); // socket de connexion while (true) { Socket sock = server.accept(); // en attente System.out.println("connecte"); PrintWriter sockOut = new PrintWriter(sock.getOutputStream(), true); BufferedReader sockIn = new BufferedReader(new InputStreamReader(sock.getInputStream())); String recu; while ((recu = sockIn.readLine()) != null) { System.out.println("recu :"+recu); sockOut.println("suivant ? "); } //fin while sockOut.close(); sock.close(); } //fin while (true) } catch (IOException e) { try {server.close();} catch (IOException e2) {} } // fin premier catch }// fin main } // fin classe Serveur Lire le message du client Afficher le message du client Envoyer le message "suivant ? " au client Réception : synchrone Emission : asynchrone Pour les sockets :
18
import java.io.*; import java.net.*; import java.util.Scanner; public class ClientEcho { public static void main(String[] args) throws IOException { Socket sock = null; PrintWriter sockOut = null; BufferedReader sockIn = null; try {sock = new Socket("localhost", 7777); // le socket de communication. sockOut = new PrintWriter(sock.getOutputStream(), true); //forcer l’écriture sockIn = new BufferedReader(new InputStreamReader(sock.getInputStream())); } catch (UnknownHostException e) { System.err.println("host non atteignable : localhost"); System.exit(1); } catch (IOException e) { System.err.println("connection impossible avec : localhost"); } System.out.println("tapez q pour terminer"); Scanner scan = new Scanner(System.in); String message = scan.next().toLowerCase(); while (! message.equals("q")) { sockOut.println(message); String recu = sockIn.readLine(); System.out.println("serveur -> client :" + recu); message = scan.next().toLowerCase(); sockOut.close(); sockIn.close(); sock.close(); }} Client Envoyer le message au serveur Lecture de la réponse du serveur Afficher la réponse du serveur PS : l’émission sans contraintes (asynchrone), la réception (synchrone) : il faut attendre la réponse du serveur (dans ce cas).
19
Exemple de communication par socket
~/BadrCours10_Socket java ServerEcho connecte recu :bonjour recu :bye ~/BadrCours10_Socket java ClientEcho tapez q pour terminer bonjour serveur -> client :suivant ? bye q
20
Exemple de communication par socket
Le programme crée un serveur de socket sur son port 7777. Puis l’appel à accept() met le serveur en attente d’une connexion d’un client. A la réception d’une connexion d’un client, un socket est crée pour assurer la communication. Lorsque le client a fini, le programme ferme le socket avec ce client et se remet en boucle d’attente d’une connexion d’un client.
21
Autre exemple Client Client Serveur Client Serveur
Le client envoie un entier Le serveur répond par la table de multiplication de cet entier Client Client Serveur Client 5 5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 5*6=30 5*7=35 5*8=40 5*9=45 5*10=50 Serveur
22
Caractère transmis et caractère Java (byte et char)
Pour les caractères, le langage JAVA utilise le type « char » basé sur l’Unicode codé sur 16 bits. La transmission sur les réseaux est basé sur l’octet : 8 bits. Les méthodes de télécommunication de Java sont donc basées sur le transfert d’octets (byte). Convertir un String en byte[ ] : String chaine = "ABCD"; byte[ ] message=chaine.getBytes(); Convertir un byte[ ] en String : chaine = new String(message); String byte[ ]
23
Lecture directe du stream d’un socket
InputStream sockIn = socket.getInputStream(); // On récupère le flux de lecture InputStream du socket. byte[ ] buffer = new byte[1024]; int lu; try { lu = sockIn.read(buffer); // lire le flux et le stocker dans buffer. Retourne le nombre de byte lu. System.out.write(buffer, 0, lu); // afficher le buffer sur la sortie standard. } catch (IOException e) {} La fin de flot peut être normale (écriture close) ou accidentelle (déconnection ou fin de processus ecrivain). Les opérations de lecture peuvent lever une IOException.
24
Ecriture directe dans le stream d’un socket
OutputStream sockOut = socket.getOutputStream(); // On récupère le flux d’écriture OutputStream du socket. // On l’utilise directement pour écrire des bytes. byte[ ] buffer = new byte[1024]; buffer = "ABCD".getBytes(); try { sockOut.write(buffer); // write(buffer) écrit tous les bytes du buffer. sockOut.flush(); // flush() devrait forcer l’écriture du contenu du tampon sur le flot. N’attends pas le remplissage du tampon. sockOut.write(buffer, 0, 2); // write(buffer, pos, nbre) écrit nbre bytes à partir de la position indiquée. } catch (IOException e) {} Les opérations d’écriture et flush peuvent lever une IOException en particulier, une tentative d’écriture sur un flot fermé.
25
Lecture et écriture de plus haut niveau
Lecture ligne par ligne de texte d’un socket : try{ BufferedReader sockReader = new BufferedReader(new InputStreamReader(socket.getInputStream())) String ligne; while ((ligne = sockReader.readLine()) != null) System.out.println(ligne); } catch (IOException e) {} On crée un BufferedReader attaché au flux InputStream. On peut lire alors directement des chaînes de caractères par readLine(). readLine() renvoie la ligne lue sans le/les caractères de fin de ligne et null si la fin de flot est atteinte.
26
Lecture et écriture de plus haut niveau
Ecriture de texte dans un socket : PrintWriter sockWriter = new PrintWriter(socket.getOutputStream())); sockWriter.print("chaine String"); sockWriter.print(1234); sockWriter.print(12.34); sockWriter.println(true); On crée un PrintWriter attaché au flux OutputStream. On peut lire alors directement n’importe quel type java par print ou println. Toutes ces méthodes ne génèrent pas d’Exception.
27
Lecture et écriture de plus haut niveau
Lecture de données Java à partir d’un socket : DataInputStream permet de lire tous les types primitifs java sur tous les systèmes. DataInputStream sockDataIn = null; try { sockDataIn = new DataInputStream(socket.getInputStream()); byte by = sockDataIn.readByte(); // retourne le prochain octet. char c = sockDataIn.readChar(); // retourne le prochain caractère. boolean bo = sockDataIn.readBoolean(); // lit un octet et retourne false si l’octet est == 0. int i = sockDataIn.readInt(); // lit 4 octets et retourne l’entier correspondant. double d = sockDataIn.readDouble(); // lit 8 octets et retourne le double correspondant. String s = sockDataIn.readUTF(); // décode les octets en caractère et retourne le String ainsi formé. } catch (EOFException e) { } catch (IOException e) { } Toutes les méthodes ci-dessus lèvent l’exception EOFException si la fin de flot est atteinte.
28
Lecture et écriture de plus haut niveau
Ecriture de données Java dans un socket : DataOutputStream permet d’écrire tous les types primitifs java sur tous les systèmes. DataOutputStream sockDataOut = null; try { sockDataOut = new DataOutputStream(socket.getOutputStream()); sockDataOut.writeByte(6); //écrit le premier octet de l’entier. sockDataOut.writeChar('c'); //écrit le caractère correspondant aux 2 premiers octets. sockDataOut.writeBoolean(true); //écrit le booléen sur un octet. sockDataOut.writeInt(-1234); // écrit l’entier sur 4 octets. sockDataOut.writeDouble(12.34); // écrit le double sur 8 octets. sockDataOut.flush(); // devrait forcer l’écriture du contenu du tampon sur le flot, s’il y a un tampon. sockDataOut.writeUTF("chaine String"); // écrit le String en l’encodant en UTF-8 modifié. } catch (IOException e) { }
29
Lecture et écriture de plus haut niveau
Transmission de données en passant par une chaîne de caractères : try { OutputStream sockOut = socket.getOutputStream(); byte[] buffer = new byte[1024]; String envoi = "chaine String"+" "+(-1234)+" " " "+true; buffer = envoi.getBytes(); sockOut.write(buffer, 0, envoi.length()); sockOut.flush(); } catch (IOException e) {}
30
Transmission d’objet par les sockets
Exemple : un client qui se connecte sur un serveur pour connaître les caractéristiques d’un objet (exemple : un chien). Un tableau de chien est stocké coté serveur. Un client se connecte sur le serveur et souhaiterais connaître les caractéristique d’un chien. Il doit envoyer au serveur le nom du chien. Le serveur lit le nom, confirme la réception, parcours le tableau pour trouver le chien et enfin sauvegarde (enregistre) l’objet chien. Cet objet est envoyé au client en utilisant les sockets. L’objet est lu par le client (restaurer). Le client affiche les caractéristique de l’objet. L’objet transmis via le réseau doit être sérialisable. implements Serializable.
31
Transmission d’objet par les sockets
import java.io.Serializable; public class Chien implements Serializable{ String nom; String aboiement; int nombrePuce; Chien (String s, String a, int i) { nom = s; aboiement = a; nombrePuce = i; } String getNom() { return nom; public String toString() { return "Le chien est : "+nom+" aboie "+aboiement+" et a "+nombrePuce+" puces."; La classe Chien est partagée entre le client et le serveur
32
Coté serveur Lire le nom envoyé par le client Confirmer la réception
import java.net.*; import java.io.*; class ServerChien { public static void main(String args[]) { Chien[ ] tabChien = { new Chien ("medor", "wouf", 3), new Chien ("milou", "wouah", 0), new Chien ("cerbere", "grrr", 12)}; ServerSocket server = null; try { server = new ServerSocket(7777); while (true) { Socket sock = server.accept(); System.out.println("connecte"); ObjectOutputStream sockOut = new ObjectOutputStream(sock.getOutputStream()); BufferedReader sockIn = new BufferedReader(new InputStreamReader(sock.getInputStream())); String recu; while ((recu = sockIn.readLine()) != null) { System.out.println("recu :"+recu); String nom = recu.trim(); for (int i=0; i<tabChien.length; i++) if (tabChien[i].getNom().equals(nom)) {sockOut.writeObject(tabChien[i]); break; } sockOut.close(); sock.close(); } catch (IOException e) { try {server.close();} catch (IOException e2) {} }// fin main }// fin classe Coté serveur Tableaux de chiens Lire le nom envoyé par le client Confirmer la réception Parcourir le tableau pour trouver le chien Enregistrer l’objet Chien afin de l’envoyer au client
33
Coté client Envoyer le nom du chien au serveur
import java.io.*; import java.net.*; public class ClientChien { public static void main(String[] args) throws IOException { String hostName = "localhost"; String Nomchien = "milou"; Socket sock = null; PrintWriter sockOut = null; ObjectInputStream sockIn = null; try { sock = new Socket(hostName, 7777); sockOut = new PrintWriter(sock.getOutputStream(), true); sockIn = new ObjectInputStream(sock.getInputStream()); } catch (UnknownHostException e) {System.err.println("host non atteignable : "+hostName); System.exit(1); } catch (IOException e) {System.err.println("connection impossible avec : "+hostName); System.exit(1);} sockOut.println(Nomchien); Object recu = sockIn.readObject(); if (recu == null) System.out.println("erreur de connection"); else { Chien chien = (Chien)recu; System.out.println("serveur -> client : " + chien); } } catch (ClassNotFoundException e) {System.err.println("Classe inconnue : "+hostName); System.exit(1);} sockOut.close(); sockIn.close(); sock.close(); Coté client Envoyer le nom du chien au serveur Restaurer l’objet chien reçu du serveur Afficher les caractéristiques du chien
34
Transmission d’objet par réseau
~/BadrCours10_Socket java ServerChien connecte recu :milou recu :medor recu :cerbere java ClientChien (avec Nomchien="milou") serveur -> client : Le chien est : milou aboie wouah et a 0 puces. java ClientChien (avec Nomchien="medor") serveur -> client : Le chien est : medor aboie wouf et a 3 puces. java ClientChien (avec Nomchien="cerbere") serveur -> client : Le chien est : cerbere aboie grrr et a 12 puces.
35
Autre exemple Client Serveur
Objet de type Compte Client Le client envoie le nom du titulaire d’un compte bancaire : DD DD 4 6000 Le serveur répond par les infos du compte (titulaire, numéro et solde) Serveur DD, son identifiant est 4 et son solde est 6000 DA
36
Communications entre un applet Java et un serveur à l’aide des sockets
Exemple : recu: 4 Serveur Client Communication par les sockets
37
Code du serveur import java.io.*; import java.net.*;
import java.util.*; public class NetServer { public static void main(String[] args) { try{ ServerSocket serverSocket = new ServerSocket(8765); Socket clientSocket = serverSocket.accept(); BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); while (true) { Integer numb = new Integer(in.readLine()); System.out.println("recu: " + numb.intValue()); out.println(numb.intValue()+1); } }catch(IOException ex){System.err.println(ex);} Convertir le String en Integer Récupérer l’entier Incrémenter l’entier et l’envoyer au client
38
Code du client Les attributs import java.applet.Applet;
import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; public class NetApplet extends Applet implements ActionListener { TextField numbField; Label display; Socket socket; public void init() { try { socket = new Socket("localhost",8765); } catch (UnknownHostException e) {System.out.println("Unknown host");} catch (IOException e) { System.out.println("IO Exception");} numbField = new TextField(6); add(numbField); Button button = new Button("Envoyer"); add(button); button.addActionListener(this); display = new Label("Pas de nombre"); add(display); } Les attributs
39
Code du client public void actionPerformed(ActionEvent e) {
int numb = 0; String numbStr = null; BufferedReader in = null; PrintWriter out = null; String actionCommand = e.getActionCommand(); if (e.getSource() instanceof Button) if (actionCommand.equals("Envoyer")){ try {numb = Integer.parseInt(numbField.getText());} catch (NumberFormatException ex) {System.out.println("Number Format Exception");} try { in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out = new PrintWriter(socket.getOutputStream(), true); } catch (IOException ex) {System.out.println("IO Exception");} out.println(numb); try {numbStr = in.readLine();} catch (IOException ex) {System.out.println("Applet receive failed:");} display.setText(numbStr); }// fin de la classe Récupérer la saisie dans la zone de texte sous forme d’un entier Envoyer l’entier au serveur Lire la réponse du serveur Utiliser le label pour afficher la réponse
40
Autre exemple Applet Client Serveur
Objet de type Compte aa 2 2000 Le client envoie le numéro d’un compte bancaire Banque organisée sous forme d’un tableau Le serveur envoie le solde du client concerné Serveur
41
Serveur multi-threads avec les sockets
import java.io.IOException; import java.net.*; public class Client1 { public static void main(String[] args){ Socket socket; try { socket= new Socket("localhost",2014); socket.close(); } catch (IOException e) { } } import java.io.IOException; import java.net.*; public class Client2 { public static void main(String[] args){ Socket socket; try { socket= new Socket("localhost",2015); socket.close(); } catch (IOException e) { } }
42
Serveur multi-threads avec les sockets
import java.io.IOException; import java.net.*; public class Serveur { public static void main(String[] args){ ServerSocket socket1, socket2; String nom1="RSD",nom2="GL"; try { socket1 = new ServerSocket(2014); socket2 = new ServerSocket(2015); T[ ] tab={new T(socket1,nom1),new T(socket2,nom2)}; for (int i=0;i<2;i++) tab[i].start(); } catch (IOException e) {} }
43
Serveur multi-threads avec les sockets
class T extends Thread { private ServerSocket socketserver; private Socket socket; public T(ServerSocket s, String nom){ super (nom); socketserver = s; } public void run() { try { while(true){ socket = socketserver.accept(); // attente d'un client System.out.println("Mon client est connecte, je suis le thread "+getName()); socket.close(); } // fin while } catch (IOException e) {} } // fin run
44
Serveur multi-threads avec les sockets
class T extends Thread { private ServerSocket socketserver; private Socket socket; public T(ServerSocket s, String nom){ super (nom); socketserver = s; } public void run() { try { while(true){ socket = socketserver.accept(); // attente d'un client System.out.println("Mon client est connecte, je suis le thread "+getName()); socket.close(); } // fin while } catch (IOException e) {} } // fin run Mon client est connecte, je suis le thread RSD Mon client est connecte, je suis le thread GL
Présentations similaires
© 2024 SlidePlayer.fr Inc.
All rights reserved.