Java : Socket et Réseaux 20/11/2018 Brigitte Groléas
Problématique Un programme serveur veut mettre des données à la disposition de programmes clients. 20/11/2018 Brigitte Groléas
Quelques mots sur les réseaux Adresse IP et nom de machine unicité sur un réseau donné Internet / réseaux locaux Ports de communication numéros logiques de communication ports 'bien connus' et ports libres critères de choix d'un numéro de port 20/11/2018 Brigitte Groléas
Quelques mots sur les réseaux Famille d'adresses AF_INET (adresse IP + port) AF_UNIX (nom arborescence Unix) AF_NS Mode Connecté (SOCK_STREAM) TCP Non connecté (SOCK_DGRAM) UDP 20/11/2018 Brigitte Groléas
Client / serveur Passif (serveur) Attendre les connexions port d'attente serveur Actif (client) : Contacter l'application distante et s'y connecter 20/11/2018 Brigitte Groléas
Communication implique ... Création de la socket (socket) et choix du mode de connexion Etablissement de la communication Echange de données Fermeture de la connexion 20/11/2018 Brigitte Groléas
Les Classes Java l'API des sockets se trouve dans le package java.net. *. Classes qui établissent la connexion Utilisation standard ou spécification 20/11/2018 Brigitte Groléas
Principe du serveur Sur le serveur : lancement d'une méthode qui attend le client par la méthode accept(). Quand un client se présente, accept() renvoie une socket de communication qui contient un canal in et un canal out pour dialoguer avec le client que le serveur vient d'accepter la socket serveur reste donc libre pour les futurs autres clients 20/11/2018 Brigitte Groléas
La classe ServerSocket Cette classe implante un objet ayant un comportement de serveur via une interface par socket. public class java.net.ServerSocket Une alternative existe à l'utilisation standard de la classe ServerSocket, elle consiste à utiliser une classe java.net.SocketImpl. . 20/11/2018 Brigitte Groléas
La classe ServerSocket La principale méthode de la classe est l'acceptation d'une connexion d'un client : public Socket accept() throws IOException Cette méthode est bloquante Elle renvoie une socket de service connectée au client. 20/11/2018 Brigitte Groléas
Principe du client Demander l'établissement d'une connexion avec un serveur d'adresse ip xx, sur un port yy Une fois que la connexion est établie : transfert des données sur 2 flux, (entrée/ sortie) Fermeture de la connexion par le client La classe java.net.Socket est utilisée pour la programmation des sockets connectés, côté client 20/11/2018 Brigitte Groléas
Opérations de la classe Socket public InputStream getInputStream() throws IOException défini un canal de lecture des données provenant du serveur public OutputStream getOutputStream() throws IOException défini un canal d'écriture pour envoyer des données sur le serveur 20/11/2018 Brigitte Groléas
Autres méthodes public InetAddress getInetAddress() fournit l'adresse IP distante public InetAddress getLocalAddress() fournit l'adresse IP locale public int getPort() fournit le port distant public int getLocalPort() fournit le port local 20/11/2018 Brigitte Groléas
Bufferisation des entrées Une fois les sockets établies, l'API des entrées-sorties (java.io) prend le relai pour l'écriture et lecture de données Bufferisation des entrées 20/11/2018 Brigitte Groléas
Exemple : un chat MESS Bonjour Client (pierre) connexion 1 1 (paul) connexion 2 (jean) connexion 3 Client 1 2 3 Liste Connectés Ecrire à tous Serveur MESS Bonjour MESS Pierre: Bonjour MESS Pierre:Bonjour Programmes Clients Programme 20/11/2018 Brigitte Groléas
Première modélisation du "chat" Thread Socket fluxEntree fluxSortie Serveur ServerSocket port Ecouteur code ActionListener WindowAdapter Dialogue zoneAffichage zoneSaisie PopupPseudo JFrame JDialog GUI Client 1 * Connexion Pseudo 20/11/2018 Brigitte Groléas
Principe du client chat Initialiser la partie graphique et les écouteurs Initialiser la connexion avec le serveur Boucle infinie lire une ligne sur le canal d'entrée l'afficher dans la textArea fin Sur événement envoyé : lire le contenu du JTextField et l'envoyer au serveur 20/11/2018 Brigitte Groléas
Initialisation du client Socket soc = new Socket( hote, port); canalOut = new PrintStream( soc.getOutputStream()); canalIn = new BufferedReader(new InputStreamReader(soc.getInputStream())); 20/11/2018 Brigitte Groléas
Boucle de lecture while( true) { ecran.append(canalIn.readLine()+"\n"); } 20/11/2018 Brigitte Groléas
Le listener du client while( true) { ecran.append(canalIn.readLine()+"\n"); Client.canalOut.println(pseudo+"--> "+Client.saisie.getText()); } 20/11/2018 Brigitte Groléas
Principe du serveur de chat Créer une socket serveur sur le port choisi Faire toujours · socket <- attendre le client · créer un objet pour communiquer avec CE client Classe de communication instanciée pour chaque client Initialiser la communication avec le client Faire toujours Envoyer à tous les clients du serveur ce qui est reçu ce client · . 20/11/2018 Brigitte Groléas
Encapsuler les données Facilité les communications en encapsulant les données canalOut = new PrintStream( soc.getOutputStream()); canalIn = new BufferedReader(new InputStreamReader(soc.getInputStream())); 20/11/2018 Brigitte Groléas
Le serveur ServerSocket ecoute; ecoute = new ServerSocket( port ); while( true ) { Socket client = ecoute.accept(); Connexion con = new Connexion( client); con.start(); } 20/11/2018 Brigitte Groléas
La connnexion : thread try { while(true) { ligne = canalIn.readLine(); for( int i =0; i<Serveur.nbCon; i++) Serveur.tabCon[i].println(ligne); } 20/11/2018 Brigitte Groléas
Ajouter des messages privés Définir un protocole réseau projet Type de messages Signification S C C S MESS bonjour tout le monde Message à tout le monde X PRIV Paul comment vas tu ? Message privé à « Paul » LIST Pierre Paul Jean Liste des utilisateurs USER Jacques Connexion d’un utilisateur OK / POK Accusé de réception pseudo 20/11/2018 Brigitte Groléas
Extensions possibles du serveur Connexion pseudo Salon nom theme Thread Serveur Socket fluxEntree fluxSortie ServerSocket port * 1 Ajout des salons de discussions sur le serveur chaque élève adapte le projet 20/11/2018 Brigitte Groléas
Extensions possibles du client Fenêtres messages privés / salon de discussion PopupPrivé zoneAffichage zoneSaisie pseudo Dialogue listeConnectés PopupPseudo PopupSalon listeSalons Client Socket fluxEntree fluxSortie JFrame Ecouteur code ActionListener ItemListener WindowAdapter JDialog GUI 1 * 20/11/2018 Brigitte Groléas
La Classe statique Serveur private static Vector salons private static Vector connexions private static ServerSocket ss private static final int port = 50000 public static void main( String argv[] ) public static void ajouter ( Connexion c ) public static void supprimer( Connexion c ) public static boolean verifierPseudo( String pseudoTest ) public static void creerSalon( String nomSalon ) public static Salon chercherSalon( String nomSalon ) public static void joindreSalon( Salon s, Connexion c ) public static void quitterSalon( Connexion c ) public static void envoyerSalons( Connexion c ) 1..* 1 0..* de Connexion vers Salon vers Connexion 1 de Salon 20/11/2018 Brigitte Groléas
Les classes Connexion & Salon private Vector connexions private String nom private String theme public Salon( String nom ) public void fixeTheme( String theme ) public String theme( ) public void ajouter ( Connexion c ) public void supprimer( Connexion c ) public Connexion chercher( String pseudo ) public void ecrireTous( String text ) public void envoyerPseudos( ) 0..* Connexion extends thread private String pseudo private Salon salle private PrintStream fluxSortie private BufferedReader fluxEntree public Connexion( Socket s ) public void run ( ) public void ecrire( String ligne ) public String pseudo( ) 1 20/11/2018 Brigitte Groléas
Exemple d’utilisation 20/11/2018 Brigitte Groléas
Les threads Programmation Multitâches : Une thread est une tâche indépendante qui s’exécute parallèlement à d’autres. L’interpréteur Java exécute toutes les threads d’une application à tour de rôle, en tenant compte de leurs priorités respectives. 20/11/2018 Brigitte Groléas
Implémentation Etendre la classe java.lang.Thread Cette classe (qui implémente l’interface runnable) possède une implémentation vide de la méthode « run() » qu’il convient de redéfinir pour fixer le code exécutable de la thread. class Tache extends Thread { public void run() { // code exécutable de la thread } 20/11/2018 Brigitte Groléas
Instanciation et lancement La méthode « start() » de la classe « java.lang.Thread » permet de démarrer une nouvelle thread. public class Programme { public static void main( String argv[] ) { Tache p1, p2; p1 = new Tache(); p2 = new Tache(); p1.start(); p2.start(); } 20/11/2018 Brigitte Groléas
Implémenter l’interface Runnable Pour définir un objet de type thread, au lieu d’étendre la classe prédéfinie « Thread », on peut implémenter l’interface « java.lang.Runnable ». class Tache implements Runnable { public void run() { // code de la thread } 20/11/2018 Brigitte Groléas
Instanciation et lancement public class Programme { public static void main( String argv[] ) { Tache p1, p2; Thread t1, t2 ; p1 = new Tache(); p2 = new Tache(); t1 = new Thread( p1 ); t2 = new Thread( p2 ); p1.start(); p2.start(); } 20/11/2018 Brigitte Groléas
cycle de vie d'une thread Nouveau Mort start() Exécutable Courant Bloqué 20/11/2018 Brigitte Groléas
Ordonnancement des Threads Multitâche préemptif Agir sur l’ordonnancement de la thread courante int getPriority(); void setPriority( int prio ) throws IllegalArgumentException; static void sleep( long milli ) throws InterruptedException; static void yield(); 20/11/2018 Brigitte Groléas
Synchronisation Eviter les télescopages Les threads de Java partagent le même espace mémoire. Ainsi plusieurs threads peuvent accéder simultanément à un même objet C’est au programmeur de décider quelles sont les méthodes ou les instructions qui n’ont pas le droit de s’exécuter en parallèle. Méthodes d’instance synchronisées 20/11/2018 Brigitte Groléas
Synchronisation Le principe consiste à poser un verrou sur l’objet. Lorsque l’objet est verrouillé par une thread, aucune autre thread ne peut accéder à cet objet au travers d’une méthode « synchronized » tant que la première thread n’a pas relâché le verrou. Attention, il est bien sur possible d’accéder à l’objet via des méthodes non synchronisées ou directement à ses composantes données (variable d’instance ou de classe) si celles-ci ne sont pas déclarées « private ». 20/11/2018 Brigitte Groléas
Le mot clé synchronized public class File { private Element tete = null; private Element fin = null; public synchronized void ajoute( Object obj ) { ... } public synchronized Object retire() { 20/11/2018 Brigitte Groléas
Méthodes de classe synchronisées Les méthodes de classe (méthodes statiques) peuvent également être déclarées « synchronized ». Dans ce cas, une thread invoquant une méthode de classe, provoque la pose d’un verrou au niveau de la classe. Une autre thread ne peut pas lancer une méthode statique synchronized sur la même classe tant que le verrou est actif. 20/11/2018 Brigitte Groléas
Héritage de méthodes synchronisées Si une classe fille étend une classe mère qui possède des méthodes synchronisées, les méthodes héritées sont synchronisées Si la classe fille redéfini une méthode synchronisée, la nouvelle méthode peut être synchronisée ou pas Si la redéfinition de la méthode n’est pas synchronisée, la méthode de la super classe reste synchronisée si elle est invoquée par la syntaxe « super.methode() ». 20/11/2018 Brigitte Groléas
Interblocages Problème classique de synchronisation : l’interblocage (deadlock) class X { public static synchronized void foo {) { Y.bar(); } class Y { public static synchronized void bar() { X.foo(); 20/11/2018 Brigitte Groléas
Rendez-vous terminal La méthode join() Une thread peut attendre qu’une autre se termine en appliquant la méthode « join() » sur la thread dont on veut attendre la mort. Quand une thread meurt, son objet ne disparaît pas, on peut ainsi accéder à son contenu. 20/11/2018 Brigitte Groléas
À vous … vrai ou faux Les threads ont un espace mémoire partagé Pour créer un Thread, on peut étendre la classe prédéfinie « Thread », Pour créer un Thread, on peut implémenter l’interface « Runnable ». L’interface « Runnable » possède une méthode abstraite « run() » prévue pour définir le code exécutable du thread. 20/11/2018 Brigitte Groléas
À vous … vrai ou faux La classe Socket est utilisée uniquement par le programme client La classe ServerSocket est utilisée uniquement par le programme serveur La méthode accept(), permet au serveur d'attendre qu'un client se connecte La méthode accept(), s'applique sur une Socket et retourne une ServerSocket La méthode accept(), s'applique sur une ServerSocket et retourne une Socket Dans une application client/serveur, l'ouverture d'une communication avec un client nécessite la création d'un thread sur le serveur La méthode getLocalHost permet d'obtenir l'adresse de son ordinateur 20/11/2018 Brigitte Groléas