Programmation réseaux avec le langage Java Février 2015 Ivan Madjarov Partie I Introduction à la programmation Java réseau IvMad, 2002-2015 2 Introduction • Le modèle OSI (Open System Interconnexion) IvMad, 2002-2015 3 Introduction • Routage et Passerelle Routage IvMad, 2002-2015 4 Introduction • Échange d'informations entre client et serveur IvMad, 2002-2015 5 Package Java • Le package java.net contient toutes les classes orientées réseau bas niveau de l'API JAVA. IvMad, 2002-2015 6 Interface de programmation réseau • Un langage de programmation "moderne" offre une interface de programmation réseau – Java, C#, Python, etc. • Java propose le paquetage java.net. Il fournit des facilités pour la programmation réseau par des Sockets en implémentant les protocoles TCP et UDP. – Le protocole UDP permet d'établir une connexion, sur une Socket, en mode non connecté • Transmission de données en mode datagramme. – Le protocole TCP permet d'établir une connexion en mode connecté. • Transmission de données en mode connecté IvMad, 2002-2015 7 La Socket • • La Socket (connecteurs réseau) représente une interface de programmation pour les communications entre processus. Il existe généralement quatre types de sockets : – Une Socket datagram permet une bidirectionnelle qui n'est pas séquencée. • Ce type de processus peut recevoir les données dans un ordre différent de l'ordre de départ. C'est le protocole UDP. – Une Socket Stream permet bidirectionnelle, sûre et séquencée • communication une communication Ce flux de données est sans duplication et peut entraîner une fragmentation des paquets transmis. Il s'agit du protocole TCP. – Une socket raw et une socket sequenced packet. IvMad, 2002-2015 8 La Socket • Le rôle des Sockets: – – – – – Connexion à une machine distante Envoie‐Réception de données Fermeture d'une connexion Attachement à un port Acceptation d'une demande de connexion à un port local • • A un port est attribué un numéro allant de 1 à 65535 Les ports de 1 à 1023 sont réservés aux services: – FTP (21), HTTP (80), SMTP (25) – Attente de demandes de connexion IvMad, 2002-2015 9 Les ports • • • Un service réseau est accessible par un port installé par un programme serveur sur une machine distante. Un port est identifié sur une machine par un nombre entier (16 bits) Les numéros de port réservés de 0 à 1023: – • ports réservés aux services standard assignés par l'IANA (Internet Assigned Numbers Authority) Les numéros de port supérieur à 1024 sont disponibles pour placer un service applicatif défini par l'utilisateur. IvMad, 2002-2015 10 Le processus Socket Selon les transparents de Rémy Courdier IvMad, 2002-2015 11 Le processus Socket Selon les transparents de Rémy Courdier IvMad, 2002-2015 12 Le processus Socket Selon les transparents de Rémy Courdier IvMad, 2002-2015 13 Le processus Socket Selon les transparents de Rémy Courdier IvMad, 2002-2015 14 Le processus Socket Selon les transparents de Rémy Courdier IvMad, 2002-2015 15 Le processus Socket Selon les transparents de Rémy Courdier IvMad, 2002-2015 16 Partie II Programmation réseau en Java par Socket en mode non connecté : Le protocole UDP (RFC 768) (User Datagram Protocol) IvMad, 2002-2015 17 Mode datagramme (UDP) • Le service, offert par la couche IP, fait l'envoi (et surtout le routage) de datagrammes de l'émetteur vers le destinataire, en mode non connecté – les datagrammes sont indépendants entre eux, même lorsqu’ils font partie d’un même message. – la remise du datagramme au destinataire n'est pas garantie! – La figure montre la structure d'un datagramme IvMad, 2002-2015 18 Mode datagramme (UDP) • Les fonctionnalités assurées par le protocole UDP sont fournies par le package java.net qui dispose de deux classes pour réaliser la programmation réseau en mode datagramme : – DatagramPacket – DatagramSocket • Les données sont mises dans un objet de type DatagramPacket qui est envoyé sur le réseau par le biais d’un objet de type DatagramSocket. IvMad, 2002-2015 19 Mode datagramme (UDP) • Le principe de la programmation réseau en mode datagramme en Java se base: – (1) sur l'envoie des datagrammes – (2) la réception des datagrammes. • Pour envoyer des datagrammes en Java on suit les étapes suivantes : 1. Obtenir l’adresse du destinataire et la mettre dans une instance de la classe InetAddress. 2. Mettre les données et l’adresse dans une instance de la classe DatagramPacket. 3. Créer une instance de la classe DatagramSocket et lui confier l’envoi du datagramme. IvMad, 2002-2015 20 Mode datagramme (UDP) • Pour recevoir des datagrammes en Java il faut suivre les étapes suivantes : 1. Créer une instance de la classe DatagramSocket qui attend l’arrivée de données par le réseau. 2. Créer une instance de la classe DatagramPacket qui reçoit les données par l’instance de DatagramSocket. IvMad, 2002-2015 21 Mode datagramme (UDP) • La classe DatagramPacket fournit deux constructeurs : – un pour les paquets à recevoir, – l'autre pour les paquets à envoyer. 1. Construire un objet pour recevoir un datagramme. – public DatagramPacket(byte buffer[], int taille) ‐ buffer correspond à la zone de réception ‐ taille maximale des datagrammes à recevoir. Les données dépassant la taille de stockage sont perdues! 2. Construire un objet pour envoyer un datagramme. – public DatagramPacket(byte buffer[], int taille, InetAddress adresse, int port) ‐ buffer correspond à la zone d'envoie ‐ taille correspond à la taille du datagramme à envoyer ‐ adresse destinataire de la datagramme ‐ port du UDP IvMad, 2002-2015 22 Mode datagramme (UDP) • Trouver l’adresse IP correspondant à un nom de machine import java.net.*; import java.io.*; public class ResoudreNom { public static void main(String[] args) { InetAddress adresse; try { adresse = InetAddress.getByName(args[0]); System.out.println("Nom : "+args[0]+", IP: " + adresse.getHostAddress()); } catch(UnknownHostException e) { System.err.println(args[0]+" est inconnu\n"); } } } IvMad, 2002-2015 23 Émetteur UDP • Le programme "Emetteur" permet l’envoi vers le programme "Recepteur" des messages par le réseau. • En première on résout le nom de la machine destinatrice (passé en argument) en adresse réseau. – adr = InetAddress.getByName(args[0]); • Ensuite une chaîne de caractères est transformée en suite d’octets pour les transmettre sur le réseau. – String message = "Démonstration du mode datagramme"; – byte[] tampon = new byte[message.length()]; • Un tableau de byte est créé à la taille du message. • Une transformation en byte se fait par la méthode getBytes() de la classe String. – tampon = message.getBytes(); IvMad, 2002-2015 24 Émetteur UDP • On construit un "datagram" avec la classe DatagramPacket en indiquant l’emplacement des données à transmettre (tempon), leur longueur (tampon.length), l’adresse du destinataire (adr) et le port d'écoute (port) sur le Recepteur. – DatagramPacket paquet = new DatagramPacket(tampon, tampon.length, adr, port); • On instancie la classe DatagramSocket pour utiliser sa méthode send() qui envoie le contenu du "datagram". – DatagramSocket sock = new DatagramSocket(); – sock.send(paquet); IvMad, 2002-2015 25 Émetteur UDP IvMad, 2002-2015 26 Récepteur UDP • Le programme "Recepteur" se charge d'afficher le message reçu de l'Emetteur. • Une zone mémoire tampon pour recevoir les données. – byte[] tampon = new byte[200]; • On instancie un DatagramSocket pour écouter sur le port annoncé du Recepteur en attente de données. – DatagramSocket sock = new DatagramSocket(port); • L’attente se fait par la méthode receive() – sock.receive(paquet); • La classe DatagramPacket se charge de placer les données dans un tampon de reception. – DatagramPacket paquet = new DatagramPacket(tampon, tampon.length); IvMad, 2002-2015 27 Récepteur UDP Le message reçu de l'Emetteur est converti en majuscules IvMad, 2002-2015 28 Mode datagramme (UDP) • On installe en premier le "Recepteur" qui écoute un port en attente du message de l'Emetteur et l'affiche à son écran. • Le programme "Emetteur" en voie un message à l'adresse du Recepteur. IvMad, 2002-2015 29 Déroulement de l'exécution • IvMad, 2002-2015 30 Partie III Programmation en Java par Socket en mode connecté (TCP) (Transmission Control Protocol) IvMad, 2002-2015 31 Le mode connecté (TCP) • Fonctionnement en mode connecté – Données envoyées dans un "tuyau" et non pas par paquet – Flux de données (Stream) – Fiable : la couche TCP assure que: • Les données envoyées sont toutes reçues par la machine destinataire • Les données sont reçues dans l'ordre où elles ont été envoyées IvMad, 2002-2015 32 Le mode connecté (TCP) • Le mode est assuré au niveau de la couche de transport selon le modèle OSI par le protocole TCP (Transmission Control Protocol). • Le paquetage java.net fourni les classes: – Socket(host, port); – ServerSocket(port); pour travailler avec le mode connecté (TCP). • Le mode connecté est une interconnexion stable entre un client et un serveur. IvMad, 2002-2015 33 Le mode connecté (TCP) • Les étapes côté Serveur: 1. Instancier la classe ServerSocket et l’instruire à écouter sur un port supérieur à 1024. 2. Accepter les connexions par la méthode accept() et créer un objet Socket pour référencer la nouvelle connexion. 3. Passer la nouvelle connexion au programme approprié. 4. Fermer la connexion par la méthode close(). • Les étapes côté Client: 1. Se connecter au service approprié en instanciant la classe Socket et en lui passant comme paramètres l’adresse du Serveur et le port écouté. 2. Lorsque l’échange est terminé fermer la connexion par la méthode close(). IvMad, 2002-2015 34 Le mode connecté (TCP) • Le Client et le Serveur en mode connecté IvMad, 2002-2015 35 Les Sockets (connecteurs réseau) • Une application Client se connecte par une adresse IP sur un numéro de port. • Le serveur accepte la connexion et fournit une nouvelle socket avec un nouveau port de communication pour continuer à écouter sur la socket originale. • Du côté du client, si la connexion est acceptée, une socket est créée pour assurer la communication avec le serveur. IvMad, 2002-2015 36 Les Sockets (connecteurs réseau) • Classe java.net.Socket propose: – Méthodes d'émission et de réception de données – Contrairement aux sockets UDP, les sockets TCP n'offre pas directement de services pour émettre‐recevoir des données • On récupère les flux d'entrée‐sorties associés à la socket OutputStream getOutputStream() • Retourne le flux de sortie permettant d'envoyer des données via la socket InputStream getInputStream() • Retourne le flux d'entrée permettant de recevoir des données via la socket – Fermeture d'une socket • public close() • Ferme la socket et rompt la connexion avec la machine distante IvMad, 2002-2015 37 Les Sockets (connecteurs réseau) • Mise en œuvre du modèle Client‐Serveur: – La Socket est créé sur le client. – Le ServerSocket fonctionne sur le serveur en attente de connexion ( méthode accept() ). – La Socket tente de se connecter sur le serveur distant. – Connexion établie, le ServerSocket génère une Socket pour communiquer avec le client. – La connexion établie, le système Client et Serveur établit un canal de communication par flux à partir de leur Sockets pour échanger des données. – Après fin des échanges, l'un des interlocuteurs clôt le canal de communication. IvMad, 2002-2015 38 Les Sockets (connecteurs réseau) • Constructeurs: – public Socket(String host, int port) throws UnknownHostException, IOException; – public ServerSocket(int port) throws IOException; • Méthodes: – host (String) : nom de la machine vers laquelle la socket est créée. – addresse (InetAddress) : adresse IP de la machine vers laquelle la socket est créée. – port (int) : numéro du port sur lequel la socket est créée. – localAddr (InetAddress) : adresse IP locale à la quelle la socket est associée. – localPort (int) : numéro du port local auquel la socket est associée. – public void close() throws IOException : ferme la socket. IvMad, 2002-2015 39 Les Sockets (connecteurs réseau) – public inputStream getInputStream() throws IOException : retourne le flux d'entrée associé à la socket. – public OutputStream getOutputStream() throws IOException : retourne le flux de sortie associé à la socket. – public void close() throws IOException : ferme la ServerSocket. – public Socket accept() throws IOException : place le ServerSocket en attente de requête d'ouverture de socket. • Cette attente est bloquante. Une socket est automatiquement générée et retournée lors de cette requête. IvMad, 2002-2015 40 Les Sockets (connecteurs réseau) • Réaliser un Client TCP en Java : – ouverture d’une socket(new socket(host,port)), – ouverture d’un flot d’entrée et de sortie sur la socket(in = new BufferReader(...)) out = new PrinterWritter(...) – lecture et écriture sur les flots en accord avec les protocoles du serveur in.readLine(...), out.println(...), – fermeture des flots: in.close(), out.close(), – fermeture de la socket : socket.close(); IvMad, 2002-2015 41 Les Sockets (connecteurs réseau) • Réaliser un Serveur TCP avec la classe java.net.ServerSocket : – ouverture d’une socket serveur, – attente de connexion et ouverture d’une socket client, – ouverture d’un flot d’entrée et de sortie sur la socket client, – lecture et écriture sur les flots en accord avec les protocoles du client (présenté précédemment), – fermeture des flots, fermeture de la socket serveur et de la socket client. IvMad, 2002-2015 42 Serveur d'heure TCP IvMad, 2002-2015 43 Le Client TCP IvMad, 2002-2015 44 Le client TCP émet un message IvMad, 2002-2015 45 Serveur TCP traite le message IvMad, 2002-2015 46 Le format d'une requête HTTP 1.0 • Une requête HTTP est une ligne de trois éléments séparés par un espace: 'Méthode' 'URL' 'Protocole' – La méthode (GET, POST, …) – L'URL (Uniform Resource Locator) du fichier demandé – La version du protocole utilisé par le client (HTTP/1.0) • Les champs d'en‐tête de la requête: lignes facultatives permettant de donner des informations sur la requête et/ou le client (Navigateur, système d'exploitation, ...). • Le corps de la requête: lignes optionnelles séparées une ligne vide et permettant un envoi de données par une commande POST lors de l'envoi de données par un formulaire. IvMad, 2002-2015 47 Serveur monoHTTPD IvMad, 2002-2015 48 Serveur HTTPD Le côté Serveur La page 'index.html' Le fichier 'index.html' IvMad, 2002-2015 49 Partie IV Programmation en Java par Socket TCP et Threads IvMad, 2002-2015 50 Threads et processus • Un thread est une portion de code capable de s'exécuter en parallèle à d'autres traitements. • Un thread n'est pas un processus. • Les threads partagent la même mémoire contrairement aux processus. • Les threads sont utiles pour: – faire des traitements en tâche de fond; – exécuter plusieurs instances d'un même code pour accélérer le traitement; – autoriser plusieurs connexions simultanées sur un serveur HTTP, FTP ou un Chat; – les threads s'exécutent en temps partagé. IvMad, 2002-2015 51 Les Threads Java • Lorsqu'un programme est exécuté sur un système multitâche, l'OS crée un processus dédié, disposant de certaine ressources (mémoire, ...). • Un thread est une unité d'exécution plus "petite" qu'un processus. – Les threads issus d'un même processus partagent le même espace mémoire chacun doté d'une certaine priorité. – Un système multiprocesseur peut exécuter les threads d'un programme simultanément, un sur chaque processeur. – On utilise les threads pour améliorer la réactivité d'un système: pour traiter séparément une connexion réseau et un calcul en mémoire ou pour améliorer la réactivité d'une interface graphique. IvMad, 2002-2015 52 Cycle de vie des Threads Java • Un thread peut être dans un des cinq états suivants: – création : le thread vient d'être créé, mais il n'a pas encore été exécuté; – exécutable : le thread est candidat à l'exécution, il attend que le système lui alloue le processeur pendant une certaine durée, appelée quantum de temps; – en cours d'exécution : le thread est en cours d'exécution par le processeur (sur un système monoprocesseur, un seul thread peut se trouver dans cet état); – bloqué : le thread a provoqué une opération bloquante ou s'est "endormi" volontairement pour une certaine durée; – détruit : le thread a fini son exécution ou a été arrêté par un autre thread. IvMad, 2002-2015 53 Cycle de vie des Threads Java IvMad, 2002-2015 54 Manipulation des Threads en Java • Un thread est un objet en Java. 1. Pour utiliser des threads dans un programme, il suffit d'hériter de la classe Thread et de redéfinir la méthode run() – La méthode run() est automatiquement appelée au moment où le thread est démarré. 2. On peut procéder aussi par l'implémentation de l'interface Runnable et instancier un objet Thread avec l'implémentation de cette interface. IvMad, 2002-2015 55 Manipulation des Threads en Java • Pour tester les threads on peut créer une classe gérant un constructeur et un String en paramètre pour spécifier le nom du thread. • La classe comprend la méthode getName() pour retourner ce nom du thread en cours. • La classe Thread se trouvant dans le package java.lang, alors aucune instruction import n'est nécessaire. • Java utilise un ordonnanceur qui détermine l'ordre d'exécution, qui s'avère souvent aléatoire. – Lorsque l'ordonnanceur passe d'un thread à un autre, le thread interrompu est mis en sommeil tandis que l'autre est en éveil IvMad, 2002-2015 56 Manipulation des Threads en Java L'ordre d'exécution est souvent aléatoire IvMad, 2002-2015 57 TCP en plusieurs clients IvMad, 2002-2015 58 Le MonoHTTPD passe en multiHTTPD IvMad, 2002-2015 59 Serveur HTTPD multiThread Serveur Multi Thread avec interface Runnable IvMad, 2002-2015 60