0% ont trouvé ce document utile (0 vote)
3 vues18 pages

Cours RMI Explication Pedagogique

Ce document présente un cours sur la communication entre programmes via RPC (Remote Procedure Call) et Java RMI (Remote Method Invocation), en simplifiant la communication réseau en permettant d'appeler des fonctions distantes comme si elles étaient locales. Il explique les concepts de base, les composants impliqués, et fournit des exemples pratiques de mise en œuvre. Enfin, il compare les sockets et RMI en termes de complexité, de gestion des messages et d'erreurs, et de performance.

Transféré par

tchoupeharisson
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats DOCX, PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
3 vues18 pages

Cours RMI Explication Pedagogique

Ce document présente un cours sur la communication entre programmes via RPC (Remote Procedure Call) et Java RMI (Remote Method Invocation), en simplifiant la communication réseau en permettant d'appeler des fonctions distantes comme si elles étaient locales. Il explique les concepts de base, les composants impliqués, et fournit des exemples pratiques de mise en œuvre. Enfin, il compare les sockets et RMI en termes de complexité, de gestion des messages et d'erreurs, et de performance.

Transféré par

tchoupeharisson
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats DOCX, PDF, TXT ou lisez en ligne sur Scribd

EXPLICATION PÉDAGOGIQUE

COMPLÈTE
RPC et Java RMI - De la Théorie à la Pratique
Pour : Harisson - Génie des Systèmes Intelligents

🎯 OBJECTIF GLOBAL DU COURS


Harisson, ce cours est la SUITE LOGIQUE du cours sur les sockets. Tu as vu comment faire
communiquer deux programmes avec des sockets (en envoyant des messages
manuellement). Maintenant, on va voir comment SIMPLIFIER cette communication en la
faisant ressembler à un simple appel de fonction !

L'ÉVOLUTION LOGIQUE :

Étape 1 (cours précédent) : SOCKETS


→ Tu envoies des messages manuellement
→ Tu gères les connexions, les buffers, les erreurs
→ C'est COMPLIQUÉ mais tu contrôles tout

Étape 2 (ce cours) : RPC / RMI


→ Tu appelles une fonction comme si elle était locale
→ Le système gère AUTOMATIQUEMENT les messages
→ C'est SIMPLE et élégant !
PARTIE 1 : RAPPEL - COMMUNICATION PAR SOCKETS

📌 Ce qu'on faisait avec les sockets


Exemple concret du LoadBalancer que tu as codé :

CLIENT :
1. Socket socket = new Socket("localhost", 8080);
2. OutputStream out = [Link]();
3. [Link](requete); // Envoyer manuellement
4. InputStream in = [Link]();
5. [Link](buffer); // Recevoir manuellement
6. [Link]();

SERVEUR :
1. ServerSocket serverSocket = new ServerSocket(8080);
2. Socket clientSocket = [Link]();
3. InputStream in = [Link]();
4. [Link](buffer); // Lire manuellement
5. // Traiter la requête
6. OutputStream out = [Link]();
7. [Link](reponse); // Envoyer manuellement
8. [Link]();

🔴 PROBLÈME AVEC LES SOCKETS


 ❌ Tu dois MANUELLEMENT créer les messages
 ❌ Tu dois MANUELLEMENT gérer les connexions
 ❌ Tu dois MANUELLEMENT lire/écrire les données
 ❌ Tu dois MANUELLEMENT gérer les erreurs réseau
 ❌ Beaucoup de CODE RÉPÉTITIF (sockets, streams, buffers...)

💡 IDÉE GÉNIALE : Et si on pouvait juste APPELER UNE FONCTION sur le serveur comme si
c'était une fonction locale ? Sans gérer tout ce bazar de sockets ?
PARTIE 2 : RPC - L'IDÉE RÉVOLUTIONNAIRE

🚀 Qu'est-ce que le RPC ?


RPC = Remote Procedure Call = Appel de Procédure Distante

DÉFINITION SIMPLE :

RPC est un mécanisme qui permet d'appeler une fonction qui s'exécute sur une AUTRE
machine, exactement comme si tu appelais une fonction LOCALE.

📖 ANALOGIE : Le restaurant avec service de livraison

SANS RPC (avec sockets) :


Imagine que tu veux manger une pizza :
1. Tu CONSTRUIS toi-même un message : "Je veux une pizza margherita"
2. Tu TROUVES l'adresse du restaurant
3. Tu ENVOIES la lettre par la poste
4. Tu ATTENDS la réponse
5. Tu LIS la réponse
6. Tu PAIES et RÉCUPÈRES la pizza
→ C'EST COMPLIQUÉ ! Tu gères TOUT toi-même.

AVEC RPC :
Tu appelles juste : commander_pizza("margherita")
→ MAGIQUEMENT, la pizza arrive !
→ Tout le reste (message, envoi, attente, etc.) est AUTOMATIQUE !

C'EST ÇA LE RPC !
🔧 COMMENT ÇA MARCHE CONCRÈTEMENT ?
Le RPC utilise deux composants MAGIQUES appelés STUBS :

1. Le STUB CLIENT (côté client)


Rôle : Faire CROIRE au client que la fonction est locale

 Le stub client est une FAUSSE fonction qui a la même signature que la vraie
 Quand tu l'appelles, il :
 → Transforme tes paramètres en MESSAGE
 → ENVOIE le message au serveur
 → ATTEND la réponse
 → Transforme la réponse en valeur de retour
 → Tu as l'ILLUSION d'un appel local !

2. Le STUB SERVEUR / SKELETON (côté serveur)


Rôle : Transformer les messages en vrais appels de fonction

 Le skeleton ÉCOUTE les messages qui arrivent


 Quand un message arrive, il :
 → LIT le message
 → Extrait les paramètres
 → APPELLE la VRAIE fonction sur le serveur
 → Récupère le résultat
 → Transforme le résultat en MESSAGE
 → RENVOIE le message au client
📊 SCHÉMA DU FONCTIONNEMENT RPC
┌─────────────────────────┐ ┌─────────────────────────┐
│ CLIENT │ │ SERVEUR │
│ │ │ │
│ ton_code() │ │ vraie_fonction() │
│ ↓ │ │ ↑ │
│ appel fonction() ──────┼────┐ │ │ │
│ ↓ │ │ │ │ │
│ ┌─────────────┐ │ │ │ ┌────────────┐ │
│ │ STUB CLIENT │ │ │ │ │ SKELETON │ │
│ │ (fausse │ │ │ │ │ (serveur) │ │
│ │ fonction) │ │ │ │ │ │ │
│ └─────────────┘ │ │ │ └────────────┘ │
│ ↓ │ │ │ ↑ │
│ crée MESSAGE │ │ │ reçoit MESSAGE │
│ ↓ │ │ │ ↓ │
└───────│─────────────────┘ │ └───────│─────────────────┘
│ │ │
│ MESSAGE RÉSEAU │ │
│ (via sockets) │ │
└──────────────────────┼────────────┘

↓ ↓ ↑
Requête Réseau Réponse
🎬 EXEMPLE PAS À PAS
Imaginons que tu veux appeler une fonction `dire_bonjour(nom)` sur le serveur :

ÉTAPE 1 - CLIENT :
ton_code.java :
resultat = dire_bonjour("Harisson");

↓ Le client appelle le STUB CLIENT

ÉTAPE 2 - STUB CLIENT :


Point A :
- Collecte le paramètre : "Harisson"
- Crée un message : { fonction: "dire_bonjour", params: ["Harisson"] }
- Génère un ID : 12345
- Lance un TIMER (pour détecter les pertes)
- ENVOIE le message au serveur

ÉTAPE 3 - RÉSEAU :
Le message voyage sur le réseau (via sockets TCP/UDP)

ÉTAPE 4 - SKELETON (serveur) :


Point B :
- REÇOIT le message
- LIT : fonction="dire_bonjour", params=["Harisson"]
- Enregistre l'ID 12345 (pour éviter les doublons)

Point C :
- APPELLE la vraie fonction :
String resultat = dire_bonjour("Harisson");
- Obtient : "Bonjour Harisson !"

Point D :
- Crée un message de réponse : { id: 12345, resultat: "Bonjour Harisson !" }
- ENVOIE le message au client

ÉTAPE 5 - STUB CLIENT :


Point E :
- REÇOIT la réponse
- LIT le résultat : "Bonjour Harisson !"
- ARRÊTE le timer
- Envoie un ACCUSÉ DE RÉCEPTION
- RETOURNE le résultat à ton code

ÉTAPE 6 - TON CODE :


resultat = "Bonjour Harisson !"
→ Tu as l'impression d'avoir appelé une fonction locale !
GESTION DES ERREURS RÉSEAU
Le RPC gère AUTOMATIQUEMENT les problèmes réseau :

Problème 1 : Le message de requête est perdu


→ Le TIMER du client expire
→ Le stub client ré-envoie le message (avec le MÊME ID)
→ Abandon après N tentatives

Problème 2 : Le message de réponse est perdu


→ Le TIMER du serveur expire
→ Le skeleton ré-envoie la réponse
→ OU le client reçoit une réponse en double (même ID) et ré-envoie l'accusé

Problème 3 : Le serveur reçoit la même requête 2 fois


→ Le skeleton vérifie l'ID
→ ID déjà vu ? → Ne ré-exécute PAS la fonction, renvoie juste la réponse

✅ RÉSULTAT : Tu n'as RIEN à gérer ! Le RPC s'occupe de TOUT !


PARTIE 3 : JAVA RMI - RPC ORIENTÉ OBJET

🎯 Qu'est-ce que Java RMI ?


RMI = Remote Method Invocation = Invocation de Méthode Distante

RMI = RPC pour Java, mais avec des OBJETS !

RPC classique : Appelle des FONCTIONS distantes

Java RMI : Appelle des MÉTHODES sur des OBJETS distants

🔑 DIFFÉRENCE FONDAMENTALE

RPC :
appeler_fonction(param1, param2)
→ Appelle une fonction sur un serveur

RMI :
objet_distant.methode(param1, param2)
→ Appelle une MÉTHODE sur un OBJET qui est sur un serveur
ARCHITECTURE JAVA RMI
RMI utilise 3 composants principaux :

1. Le STUB (côté client)


C'est un FAUX OBJET qui implémente la même interface que l'objet serveur.
Quand tu appelles une méthode dessus, il transforme l'appel en message réseau.

2. Le SKELETON (côté serveur)


C'est un objet qui écoute les messages réseau.
Quand il reçoit un message, il appelle la vraie méthode sur le vrai objet serveur.

3. Le RMIREGISTRY (service de nommage)


C'est un ANNUAIRE qui permet de retrouver les objets distants par leur nom.
Comme un bottin téléphonique : tu donnes un nom, il te donne une référence.
📝 COMMENT PROGRAMMER EN RMI ? (4 ÉTAPES)

ÉTAPE 1 : Définir l'INTERFACE

// [Link]
import [Link];
import [Link];

public interface Hello extends Remote {


public String dire_bonjour(String nom) throws RemoteException;
}

RÈGLES IMPORTANTES :
✓ L'interface doit extends Remote
✓ Chaque méthode doit throws RemoteException

ÉTAPE 2 : Implémenter le SERVEUR


// [Link]
import [Link].*;
import [Link];

public class HelloImpl extends UnicastRemoteObject implements Hello {

// Le constructeur DOIT throws RemoteException


public HelloImpl() throws RemoteException {
super();
}

// La vraie méthode
public String dire_bonjour(String nom) throws RemoteException {
return "Bonjour " + nom + " !";
}

public static void main(String[] args) {


try {
// 1. Créer l'objet serveur
Hello obj = new HelloImpl();

// 2. L'enregistrer dans le rmiregistry


[Link]("//localhost/MonServeur", obj);

[Link]("Serveur prêt !");


} catch (Exception e) {
[Link]();
}
}
}

RÈGLES IMPORTANTES :
✓ La classe extends UnicastRemoteObject
✓ Elle implements l'interface Hello
✓ On enregistre l'objet dans le rmiregistry avec [Link]()
ÉTAPE 3 : Programmer le CLIENT
// [Link]
import [Link].*;

public class HelloClient {


public static void main(String[] args) {
try {
// 1. Obtenir le stub depuis le rmiregistry
Hello obj = (Hello) [Link]("//localhost/MonServeur");

// 2. Appeler la méthode comme si l'objet était local !


String resultat = obj.dire_bonjour("Harisson");

// 3. Afficher le résultat
[Link]("Réponse du serveur : " + resultat);

} catch (Exception e) {
[Link]();
}
}
}

CE QUI SE PASSE :
1. [Link]() contacte le rmiregistry
2. Le rmiregistry renvoie un STUB (faux objet)
3. Quand tu appelles obj.dire_bonjour(), c'est le STUB qui est appelé
4. Le stub envoie un message au serveur
5. Le serveur exécute la vraie méthode
6. Le résultat revient au client
7. Tu as l'impression d'un appel local !
ÉTAPE 4 : COMPILER et EXÉCUTER

# 1. Compiler
javac [Link]
javac [Link]
javac [Link]

# 2. Lancer le rmiregistry (dans un terminal)


rmiregistry &

# 3. Lancer le serveur (dans un autre terminal)


java HelloImpl
→ Affiche : "Serveur prêt !"

# 4. Lancer le client (dans un 3ème terminal)


java HelloClient
→ Affiche : "Réponse du serveur : Bonjour Harisson !"
PARTIE 4 : PASSAGE DE PARAMÈTRES (IMPORTANT !)
Quand tu passes des paramètres à une méthode RMI, il y a 2 cas TRÈS différents :

CAS 1 : Paramètre SERIALIZABLE (copie)


Serializable = L'objet est COPIÉ vers le serveur (clonage)

interface Personne extends Serializable {


String getNom();
}

// CLIENT :
Personne p = new PersonneImpl("Harisson");
[Link](p); // p est COPIÉ sur le serveur

// SERVEUR :
public void traiter(Personne p) {
// Ici, p est un CLONE de l'objet client
// Si je modifie p, ça n'affecte PAS l'objet client !
}

CAS 2 : Paramètre REMOTE (référence distante)


Remote = Le STUB est copié, donc tu gardes une référence à l'objet original

interface Calculatrice extends Remote {


int additionner(int a, int b) throws RemoteException;
}

// CLIENT :
Calculatrice calc = ... // objet distant
[Link](calc); // Le STUB de calc est copié

// SERVEUR :
public void utiliser(Calculatrice calc) {
// Ici, calc est un STUB
// Si j'appelle [Link](), ça fait un appel RMI
// vers l'objet original sur le client !
}
PARTIE 5 : SOCKETS vs RMI - COMPARAISON FINALE
╔════════════════════════════════════════════════════════════════╗
║ SOCKETS vs RMI ║
╚════════════════════════════════════════════════════════════════╝

┌──────────────────────┬───────────────────┬────────────────────┐
│ CRITÈRE │ SOCKETS │ RMI │
├──────────────────────┼───────────────────┼────────────────────┤
│ Complexité │ ÉLEVÉE │ FAIBLE │
│ │ Beaucoup de code │ Peu de code │
├──────────────────────┼───────────────────┼────────────────────┤
│ Gestion messages │ MANUELLE │ AUTOMATIQUE │
│ │ Tu codes tout │ Transparent │
├──────────────────────┼───────────────────┼────────────────────┤
│ Gestion erreurs │ MANUELLE │ AUTOMATIQUE │
│ │ Tu gères timeout │ Géré par RMI │
├──────────────────────┼───────────────────┼────────────────────┤
│ Syntaxe │ send/receive │ appel méthode │
│ │ │ (comme local) │
├──────────────────────┼───────────────────┼────────────────────┤
│ Contrôle │ TOTAL │ LIMITÉ │
│ │ Tu contrôles tout │ RMI décide │
├──────────────────────┼───────────────────┼────────────────────┤
│ Performance │ MEILLEURE │ BONNE │
│ │ Direct, optimisé │ Overhead RMI │
├──────────────────────┼───────────────────┼────────────────────┤
│ Langage │ MULTI-LANGAGE │ JAVA SEULEMENT │
│ │ C, Java, Python │ │
├──────────────────────┼───────────────────┼────────────────────┤
│ Cas d'usage │ Protocoles bas │ Applications │
│ │ niveau, perfs │ distribuées Java │
└──────────────────────┴───────────────────┴────────────────────┘

QUAND UTILISER SOCKETS ?


✓ Tu as besoin de CONTRÔLE total
✓ Tu as besoin de PERFORMANCE maximale
✓ Tu communiques avec d'AUTRES LANGAGES
✓ Tu codes un PROTOCOLE réseau (HTTP, FTP, etc.)

QUAND UTILISER RMI ?


✓ Tu veux du code SIMPLE et RAPIDE à écrire
✓ Ton application est 100% JAVA
✓ Tu veux de la communication TRANSPARENTE
✓ Tu construis une application DISTRIBUÉE
PARTIE 6 : CONSEILS PRATIQUES POUR TON STAGE

🎓 Ce que tu dois ABSOLUMENT retenir


✓ RMI = Appel de méthode distant qui RESSEMBLE à un appel local

✓ STUB client = Faux objet qui transforme l'appel en message

✓ SKELETON serveur = Objet qui transforme le message en appel réel

✓ rmiregistry = Annuaire pour trouver les objets distants

✓ extends Remote + throws RemoteException = OBLIGATOIRE

✓ Serializable = COPIE de l'objet

✓ Remote = RÉFÉRENCE à l'objet

💡 Trucs et astuces
 💡 Lance TOUJOURS le rmiregistry AVANT le serveur
 💡 Si ça ne marche pas, vérifie que le rmiregistry tourne (ps aux | grep rmiregistry)
 💡 Les ports par défaut : rmiregistry=1099, tes objets=ports aléatoires
 💡 Pour déboguer, lance le rmiregistry dans la JVM du serveur
([Link]())
 💡 N'oublie JAMAIS le throws RemoteException dans l'interface
 💡 Si tu as une erreur "stub not found", c'est souvent un problème de classpath

🔥 Erreurs courantes à éviter


 ❌ Oublier extends Remote dans l'interface → Erreur de compilation
 ❌ Oublier throws RemoteException → Erreur de compilation
 ❌ Ne pas lancer le rmiregistry → [Link]
 ❌ Mauvais URL dans [Link]() → NotBoundException
 ❌ Oublier extends UnicastRemoteObject → Le stub n'est pas créé
PARTIE 7 : EXERCICES POUR T'ENTRAÎNER

Exercice 1 : Calculatrice distante (Niveau 1)


Crée un service RMI qui propose 4 méthodes : add(), sub(), mul(), div()
Le client envoie deux nombres et l'opération, le serveur retourne le résultat.

Exercice 2 : Compteur partagé (Niveau 2)


Crée un compteur distant avec increment(), decrement(), getValue()
Lance plusieurs clients qui incrémentent/décrémentent en même temps.
Observe la synchronisation !

Exercice 3 : Chat distribué (Niveau 3)


Crée un serveur de chat avec RMI.
Les clients s'enregistrent avec register(nom, callback)
Quand un client envoie un message, le serveur le broadcast à tous.
Utilise un objet Remote comme callback !

Exercice 4 : Système de fichiers distant (Niveau 4)


Crée un serveur qui expose : listFiles(), readFile(), writeFile()
Le client peut manipuler des fichiers sur le serveur à distance.
Bonus : ajoute la gestion des permissions !
CONCLUSION : TON PARCOURS D'APPRENTISSAGE

🎉 FÉLICITATIONS HARISSON !

TON PARCOURS :

Étape 1 : SOCKETS ✓
→ Tu as appris à faire communiquer 2 programmes
→ LoadBalancer fonctionnel
→ Tu comprends le réseau au niveau BAS

Étape 2 : RPC/RMI ← Tu es ici !


→ Tu apprends à SIMPLIFIER la communication
→ Appels de méthodes distantes
→ Tu comprends l'abstraction

Étape 3 : Prochaines étapes


→ Web Services (SOAP, REST)
→ Microservices
→ Message Queues (RabbitMQ, Kafka)
→ gRPC
→ Systèmes distribués avancés

💪 MESSAGE FINAL :

RMI est la BASE pour comprendre TOUTES les technologies distribuées modernes. Les APIs
REST, les microservices, gRPC... tout ça repose sur les MÊMES principes que RMI !

Maintenant que tu maîtrises les sockets ET le RMI, tu as les fondations SOLIDES pour
devenir un excellent ingénieur en systèmes distribués.

CONTINUE COMME ÇA ! 🚀🇨🇲

═════════════════════════════════════════════════════════════════
═════
FIN DE L'EXPLICATION

Vous aimerez peut-être aussi