Blog ENI : Toute la veille numérique !
🐠 -25€ dès 75€ 
+ 7 jours d'accès à la Bibliothèque Numérique ENI. Cliquez ici
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
  1. Livres et vidéos
  2. Développement informatique
  3. Programmation réseau
Extrait - Développement informatique Apprenez à concevoir avant de programmer
Extraits du livre
Développement informatique Apprenez à concevoir avant de programmer
3 avis
Revenir à la page d'achat du livre

Programmation réseau - Architecture 3-tiers

Objectifs du chapitre

  • Concevoir et développer un serveur d’objets sérialisables.

  • Développer des applications clientes de ce serveur.

Un objet sérialisable peut être écrit sur un flux par la méthode writeObject() de la classe ObjectOutputStream. Un algorithme dit de sérialisation permet de le coder. On obtient une succession d’octets, qu’il est possible de décoder et de retransformer sous forme d’objet. C’est ce que fait la méthode readObject() de la classe ObjectInputStream. En Java, un objet sérialisable est un objet d’une classe qui implémente l’interface Serializable.

Définitions

1. Serveur

Un serveur est une application qui "écoute" le réseau. Il est capable de lire les requêtes d’un programme client et de lui répondre.

Cette notion de serveur est parfois ambigüe. Pour un développeur, il s’agit d’un programme. Pour un administrateur réseau, le terme serveur peut désigner la machine qui héberge le programme serveur.

2. Protocole

Un client et un serveur peuvent échanger des messages. Encore faut-il qu’ils se comprennent ! S’ils ne parlent pas la même langue, ils communiqueront mal !

C’est pourquoi on définit des protocoles qui permettent de standardiser les messages. Les protocoles définissent la syntaxe des messages échangés par un client et un serveur.

Ainsi, des messages envoyés à un serveur web doivent respecter le protocole HTTP. En retour, le serveur web répond dans un langage qui est compris et interprété par un navigateur web, en général HTML.

Programmation des "sockets"

1. Présentation

La programmation des sockets permet à une application de communiquer avec une autre application, qui s’exécute éventuellement sur un autre ordinateur.

Par des ordres d’écriture, on peut envoyer des messages. Par des ordres de lecture, on peut lire des messages.

Une application cliente peut envoyer des requêtes à un serveur et lire ses réponses. Une application serveur peut lire les requêtes d’un client et lui envoyer les réponses.

2. Programme d’accès à un serveur web

Le programme suivant communique avec un serveur web installé localement sur le port 8080.

Un port permet d’identifier différents programmes informatiques qui tournent sur un ordinateur. Un port est distingué par son numéro.

Le programme :

  • se connecte au serveur web,

  • envoie au serveur une requête au format HTTP,

  • affiche dans la console le code HTML de la page retournée par le serveur, en réponse à la requête.


public class SocketWeb 
{ 
    public static void main(String argv[]) 
    { 
        Socket socketClient; 
        BufferedReader entree; 
        PrintWriter sortie; 
        String ligne; 
 
        try 
  ...

Implémentation de serveurs d’applications

1. Choix de dénomination des variables

Dans tous les exemples suivants, nous avons réalisé des programmes "serveur" et des programmes "client". Le programme "serveur" possède un objet de type ServeurSocket qui "écoute" le réseau et attend les connexions des clients. Le programme "serveur" et le programme "client" communiquent par des objets Socket.

Nous avons dû faire des choix de noms de variables :

Dans le programme serveur :

  • l’objet ServeurSocket est nommé "serveur", car c’est lui qui "écoute",

  • l’objet Socket est nommé "socketServeur".

Dans le programme client :

  • l’objet Socket est nommé "socketClient"

2. ServerSocket

Un objet ServerSocket attend les requêtes qui arrivent sur le réseau. Le programme serveur instancie un objet ServerSocket :


. . . 
ServerSocket serveur = new ServerSocket(8189); 
. . .
 

Le programme serveur est accessible sur le port 8189 de la machine. Il attend qu’un client se connecte grâce à la méthode accept() de la classe ServerSocket :


. . . 
Socket socketServeur = serveur.accept(); 
. . .
 

Cette méthode bloque le programme jusqu’à ce qu’un client se connecte. Elle retourne alors la référence d’un objet Socket qui permet de dialoguer avec le client.

Un programme client se connecte au serveur en exécutant l’instruction :


Socket socketClient = new Socket("localhost", 8189);
 
images/captureP641a.PNG

L’objet socketClient du programme client et l’objet socketServeur du programme serveur correspondent.

  • Le flux de sortie du client correspond au flux d’entrée du serveur.

  • Le flux d’entrée du client correspond au flux de sortie du serveur.

images/captureP641b.PNG

3. Un serveur simple et son client

a. Le serveur

Le programme serveur suivant a le comportement ci-après :

  • Il instancie l’objet ServerSocket.

  • Il attend une connexion du client : accept().

  • Quand un client se connecte, il lui envoie un message de bienvenue.

  • Il lit alors un message du client, et s’arrête. Les textes échangés sont codés en UTF-8.

  • Si le client ne se connecte pas dans les 10 secondes, le serveur s’arrête.


public class ServeurSimple 
{ 
  ...

Travail pratique : Projet ServeurObjets

1. Objectifs

  • Concevoir et développer en Java un serveur d’application connecté à une base de données.

  • Développer une application dans une architecture 3 tiers.

2. Architecture du projet : 3-tiers

images/02155a.png

L’intérêt de cette architecture est que les clients se connectent au serveur d’objets au lieu de se connecter directement au serveur base de données.

Le serveur de données est isolé des clients, qui ne le connaissent pas.

  • La sécurité des données est ainsi plus facile à assurer.

  • Seul le serveur d’objets se connecte à la base, ce qui allège le travail du serveur de données.

3. Sujet

a. Fenêtre graphique du serveur

À partir du serveur multithread de la section précédente, développer un serveur d’objets qui présente la vue suivante :

images/02155b.png

Le bouton ON/OFF permet de démarrer et d’arrêter le serveur. La zone de texte permet de suivre les connexions et les requêtes des clients.

b. Fonctionnement du serveur

Quand le serveur est allumé :

  • Il attend une connexion du client : accept().

  • Quand un client se connecte, le serveur lance un thread "client" pour dialoguer avec lui.

  • Le thread "client" :

  • Lit la requête envoyée par le client.

  • Envoie la réponse au client.

  • S’arrête.

c. Protocole d’échange entre le client et le serveur

La requête du client est un objetString. Elle contient un texte au format SQL

Exemple : SELECT * FROM CONTACT

La réponse envoyée au client est constituée de deux objets :

  • Un premier objet de type Integer, qui peut prendre les valeurs 0, 1 ou 2.

  • Un deuxième objet dont le type dépend de la valeur du premier :

  • Si le premier objet vaut 0, c’est une String qui contient un message d’erreur.

  • Si le premier objet vaut 1, c’est un JeuResultat contenant le résultat du SELECT

  • Si le premier objet vaut 2, c’est un Integer contenant le nombre de lignes modifiées (UPDATE, INSERT, DELETE).

d. Programme fourni

Le programme ClientServeurObjets permet de tester le serveur.


public class ClientServeurObjets 
{ 
    public static void main(String argv[]) 
    { 
        Socket socketClient; 
  ...

Travail pratique : Projet GestionContactReseau

1. Objectif

  • Créer un client graphique qui reçoit des informations du serveur d’objets.

2. Écrans du client et du serveur

images/02156a.png

3. Sujet

a. Présentation

L’application GestionContactJdbc du chapitre JDBC - Mapping Objet/Relationnel accède directement à la base de données. Elle utilise pour cela les classes BaseDeDonnees et AccesBase du package utilitairesMG.jdbc.

L’application GestionContactReseau accède au serveur d’objets.

  • La classe PriseServeur remplace BaseDeDonnees.

Un objet de la classe PriseServeur référence un serveur d’objets. Son constructeur reçoit l’adresse IP et le port du serveur.

  • La classe AccesServeur remplace AccesBase. Elle possède les méthodes suivantes :

  • AccesServeur(PriseServeur prise)

  • PriseServeur getPrise()

  • Socket getConnection() throws IOException

  • void closeConnection() throws IOException

  • JeuResultat executeQuery(String select) throws IOException, ClassNotFoundException

  • Integer executeUpdate(String requete) throws IOException, ClassNotFoundException

Attention : à chaque appel d’une méthode de AccesServeur, on doit ouvrir et fermer la connexion au serveur. En effet, le serveur ouvre une Socket à la réception de la requête du client, exécute la requête, envoie le résultat, et ferme la Socket. On ne peut garder la connexion !

b. Travail

Les suggestions suivantes ont pour objectif de limiter le travail à effectuer.

  • Recopier les classes de l’application GestionContactJdbc dans l’application GestionContactReseau.

  • Grâce à la conception MVC, la fenêtre de l’application est inchangée.

  • Les contrôleurs et les classes DAO sont modifiés.

  • Dupliquer le package utilitairesDivers.daoJdbcMapping en utilitairesDivers.daoServeurObjets.

  • Écrire les classes PriseServeur et AccesServeur et les ajouter au package utilitairesDivers.daoServeurObjets.

  • Les classes ContactDAO, VersementDAO, SecteurDAO doivent être adaptées pour lire les données à partir du serveur d’objets : remplacer les références de type AccesBase par des références de type AccesServeur. Il faudra aussi remplacer les SQLException générées par les méthodes de AccesBase par les IOException, ClassNotFoundException...