Outils pour utilisateurs

Outils du site


developpement:java:reseaux

Programmation réseau

Lorsqu'il y a deux applications communicantes, il faut d'abord établir la communication entre les deux applications, et ensuite, la communication proprement dite, avec des flux d'entrée/sortie (java.io.*).

Ensuite, puisqu'il y a une partie écoute et communicante et que ceux-ci peuvent être dupliquées, c'est-à-dire qu'il peut y avoir plusieurs communications simultanées, il faut ajouter un concept de multithreading.

Architectures logicielles

L'informatique centralisée

  • Un ordinateur central qui effectue tous les traitements (logique

d'affaires, bases de données, etc).

  • Des terminaux comme clients.

Dans la classification actuelle, ce type d’architecture est appelée « architecture 1-tier ».

Le client-serveur

  • Un ordinateur qui gère l’accès aux données et effectue une partie des traitements de la logique d’affaires.
  • Des ordinateurs clients qui gèrent l’interface avec les utilisateurs et effectuent une partie des traitements de la logique d’affaires.

La proportion de répartition de la logique d’affaire entre le client et le serveur dépend des besoins de l’application. Ce type d’application est caractérisé par la nécessité d’effectuer des installations sur chaque poste client, ce qui complique les mises à jour et pose des problème au niveau de la gestion des versions (on parle de client lourd – fat client).

Dans la classification actuelle, ce type d’architecture est appelée « architecture 2-tiers ».

L'architecture 3-tiers

  • Des ordinateurs clients (navigateurs web) qui s’occupent uniquement de la présentation des données aux clients.
  • Les traitements de la logique d’affaires s’effectuent au niveau du serveur (web).
  • Un serveur de base de données s’occupe de la gestion de l’accès aux données.

Dans cette architecture, aucun traitement n'est fait au niveau du client, qui s'occupe uniquement d’afficher les données aux clients. La génération de l'interface est pilotée par le serveur. Les modifications apportées à l'application ne nécessitent aucune intervention au niveau du client, puisqu’il n’y a aucune installation au niveau du client (on parle de client léger – thin client).

L'architecture n-tiers

Avec le développement des technologies réseau pour l'Internet, il est devenu possible de déléguer au serveur des traitements complexes. Les applications tendent à devenir des services offerts sur un réseau global : Internet.

L'utilisation de langages et techniques de programmation coté client (HTML, DHTML, XML, javascript, CSS, flash, etc) permettent d’étoffer les interfaces utilisateurs. Le contenu est généré dynamiquement à l’aide de langages et techniques de programmation coté serveur.

Le 3ème tier de l’architecture 3-tiers, c’est à dire le serveur, est éclaté en plusieurs composants qui coopèrent pour réaliser les fonctionnalités de l’application. Certains composants, comme les servlets et les JSP, s'occupent de la présentation : c’est la couche présentation. Ces composants pilotent la génération d’une l'interface utilisateur sur mesure pour le client. D'autres composants, comme les EJB (Enterprise JavaBeans), implémentent la logique d’affaires, appelée aussi logique métier. D'autres composants s’occupent d’autres tâches comme la persistance des objets, la messagerie, la gestion des transaction, la sécurité et autres services réseau.

Le nombre de composants dans cette architecture n'est pas fixé a priori. Il dépend des besoins. C'est pour cela qu’on parle d'architecture n-tiers, où n est censé être supérieur à 3.

Modes de communication

Mode connecté

L'utilisateur se connecte (« se logue ») et reste connecté jusqu’à ce qu’il se déconnecte.

Mode non connecté

Basé sur des requêtes et des réponses. C'est le client qui initie la connexion pour envoyer une requête. Le serveur répond à la requête et ferme la connexion. Ce mode est aussi appelé « mode sans état ». HTTP est un exemple de protocole fonctionnant en mode non connecté. C'est cette caractéristique qui nous oblige aujourd'hui à utiliser des techniques de programmation coté serveur pour simuler et gérer des sessions sur Internet.

Serveur d'application

  • Weblogic (BEA/Oracle)
  • WebSphere (IBM)
  • JBoss
  • iPlanet
  • GlassFish
  • Netweaver (SAP)

Applications communicantes avec les sockets

Les données qui transitent sur Internet sont organisés en paquets appelés datagrammes. Chaque datagramme contient une partie des données à laquelle est rajoutée une en-tête. L’en-tête contient des informations nécessaires pour assurer l'acheminement du paquet jusqu'à sa destination, pour reconstituer les données à l'arrivée, pour vérifier si des données n’ont pas été corrompues ou perdues pendant la transmission.

Tout ce travail, qui aurait nécessité un effort de programmation supplémentaire non négligeable, est fait pour nous par les sockets. Les sockets ont été inventées à l'Université Berkeley dans le but de rendre les connexions réseaux aussi simples et transparentes qu’un flux d’entrée/sortie sur un fichier.

Les applications qui communiquent à l'aide de sockets le font selon deux étapes fondamentales :

  • Connexion → le serveur doit être à l'écoute. Le client envoie une demande de connexion. Une fois que le serveur a accepté la requête, la connexion est établie et les 2 applications peuvent communiquer. Une fois la connexion établie, chacune des 2 parties dispose d’un objet Socket qui encapsule les informations sur l'autre partie.
  • Communication → elle consiste simplement à utiliser les flux d'entrée/sortie. Chacun des 2 objets Socket permet d’ouvrir des flux vers l'autre partie.

Java propose les classes java.net.ServerSocket et java.net.Socket pour représenter les sockets au niveau du serveur et au niveau de client.

La procédure est simple. L'application serveur crée un objet ServerSocket sur un port donné :

ServerSocket serveurSock = new ServerSocket(num_port);

num_port est un entier indiquant le numéro du port par lequel le serveur va écouter. Deux serveurs ne peuvent pas écouter sur le même port. Il y a des ports réservés (par exemple : 80 et 81 pour les serveurs HTTP, 21 pour les serveurs FTP, etc). Il est recommandé d’éviter d’utiliser des numéros inférieurs à 1024 car ils sont déjà utilisés ou réservés pour un usage futur.

L'objet ServerSocket utilise sa méthode accept() pour se mettre à l'écoute d’une éventuelle demande de connexion sur le port spécifié. Dès qu'un client se voit accepté sa demande de connexion, la méthode accept() retourne un objet Socket qui encapsule les informations sur le client connecté :

Socket sock = serveurSock.accept();

Pour le serveur, l’objet Socket représente la connexion vers le client. Cet objet sera utilisé, en particulier, pour ouvrir des flux vers ce client. La nature du flux dépend de la nature de l'information échangée (flux d’octets, de données ou d’objets). De plus, le serveur ouvrira un flux en sortie pour envoyer des informations vers le client et un flux en entrée pour récupérer des informations en provenance du client. Par exemple :

BufferedInputStream is = new BufferedInputStream(sock.getInputStream()); 
PrintWriter os = new PrintWriter(sock.getOutputStream());

De manière similaire, le client va utiliser un objet Socket pour envoyer une requête de connexion à un serveur. Il doit fournir l’adresse IP du serveur et le numéro du port sur lequel ce dernier écoute :

Socket sock = new Socket(adr_serveur,num_port); 

L'objet Socket ainsi créé va encapsuler les informations sur le serveur. Comme pour le serveur, il représente la connexion vers ce dernier et sera utilisé, en particulier, pour ouvrir des flux en sa direction.

GRAPHIQUE

En nous limitant à ces techniques, un client peut monopoliser le serveur, ce qui va empêcher les autres clients de s’y connecter. Pour remédier à cette limite, on utilise le multi-threading : chaque connexion est prise en charge par un thread séparé.

L'exemple constitué des deux fichiers ServerChat.java et ClientChat.java illustre la plupart de ces concepts.

Remarquez bien que dans cet exemple, le serveur n'accepte pas plus de un client (comme on le voit dans le constructeur, une fois que la méthode accept() a accepté une connexion, elle n'est plus ré-exécutée). Le thread utilisé par le serveur permet simplement de réaliser en parallèle les tâches de réception et d'envoi de messages.

/** 
 Fichier : ServerChat.java 
 Auteur  : A. Toudeft 
 Date    : 15/05/2002 
 Sujet   : Exemple de communication avec des sockets  
 Role    : Programme serveur. 
*/ 
import java.io.*; 
import java.net.*; 
import java.awt.*; 
import javax.swing.*; 
import java.awt.event.*; 
 
public class ServerChat extends JFrame implements KeyListener { 
  int     port; 
  ServerSocket   serveurSock; 
  Socket   sock; 
  PrintWriter   os; 
  BufferedInputStream  is; 
  JTextArea   txaMessages; 
  JTextField   txfChat; 
 
  public ServerChat(int p) {  
    port = p; 
    try { 
      serveurSock = new ServerSocket(port); 
    } 
    catch(IOException e){
      System.out.println(e);
    } 
 
    this.getContentPane().setLayout(new BorderLayout()); 
    txaMessages = new JTextArea(); 
    this.getContentPane().add(txaMessages, BorderLayout.CENTER); 
 
    txfChat = new JTextField(); 
    txfChat.addKeyListener(this); 
    this.getContentPane().add(txfChat,BorderLayout.NORTH); 
    this.setTitle("SERVEUR"); 
 
    try { 
      sock = serveurSock.accept(); 
      is = new BufferedInputStream(sock.getInputStream()); 
      os = new PrintWriter(sock.getOutputStream()); 
      (new ThreadServerChat(this)).start(); 
    } 
    catch (IOException e) { 
      System.out.println(e); 
    } 
  } 
 
  public void lireSocket() { 
    byte []buf = new byte[200]; 
    String message; 
 
    try { 
      is.read(buf); 
      message = (new String(buf)).trim(); 
      txaMessages.append("\n>>" + message); 
    } 
    catch(IOException e) { 
      System.out.println(e); 
    } 
  } 
 
  public void keyPressed(KeyEvent e) { 
    if(e.getKeyCode() == KeyEvent.VK_ENTER) { 
      os.print(txfChat.getText()); 
      os.flush(); 
      txaMessages.append("\nMOI>> " + txfChat.getText());  
      txfChat.setText(""); 
    } 
  } 
 
  public void keyReleased(KeyEvent e) {} 
  public void keyTyped(KeyEvent e) {} 
 
 public static void main(String args[]) 
  { 
  if(args.length==1) 
   { 
    System.out.println("Attente d'une connection"); 
ServerChat sc = new ServerChat( 
Integer.parseInt(args[0])); 
    sc.setSize(300,300); 
    sc.setVisible(true); 
   } 
  else 
  System.out.println("Usage: ServerTest [port]"); 
  } 
 } 
 
class ThreadServerChat extends Thread 
 { 
 ServerChat ref; 
 
 public ThreadServerChat(ServerChat r) 
  { 
  ref = r; 
  } 
 
 public void run() 
  { 
  while(true) 
   { 
   try 
    { 
    while(ref.is.available() == 0) 
     { 
     try 
      { 
      Thread.sleep(1000); 
      } 
     catch(InterruptedException e) 
      { 
      System.out.println(e); 
      } 
     } 
    ref.lireSocket(); 
    } 
   catch(IOException e) 
    { 
    System.out.println(e); 
    } 
    } 
  } 
} 

Applications communicantes avec les sockets

Deux étapes :

  1. Établissement de la connexion
  2. Communication (avec les flux d'entrée/sortie)

Deux classes sont importantes disponibles dans java.net

  1. ServerSocket → une fois une connexion établie, représentera le client qui s'est connecté.
  2. Socket → une fois une connexion établie, représentera le serveur vers lequel il s'est connecté.

Sur le serveur :

ServerSocket ss = new ServerSocket(8989);  // numéro du port 8989
Socket s = ss.accept();   // opération bloquante
OutputStream os = s.getOutputStream();
DataOutputStream ds = new DataOutputStream(os);

Sur le côté client :

Socket s = new Socket("148.192.9.125", 8989);
InputStream is = s.getInputStream();
developpement/java/reseaux.txt · Dernière modification : 2022/02/02 00:42 de 127.0.0.1