RMI - Programmierung

Werbung
Netzwerk Programmierung
FH Merseburg SS 2002
RMI - Programmierung
Erweiterung des Chat-System zu entferntem Methodenaufruf per RMI
Was ist RMI (Remote Method Invocation)
Theoretische Grundlagen
 Sockets sind für viele verteilte Anwendungen eine flexible, solide und ausreichende
Technik
 beschränken sich auf Übertragung von Daten (Bytestrom)
 lassen Semantik der Daten unberücksichtigt  es müssen auf Anwendungsebene
Protokolle zur Interpretation der Daten entwickelt werden (siehe Socketbeispiele)
 Rahmenwerk für die Semantik steht zur Verfügung: Objekte
 Lokal: Objekte kommunizieren mit anderen Objekten über die mit Semantik
belegten Methoden
 Symmetrische Beziehung: jedes Objekt kann ein anderes aufrufen
Grundprinzip lokaler Methodenaufruf
 Beispiel Schläger und Ball
 Schläger schlägt den Ball  Schläger ruft Methode hit() von Ball auf
public class Schlaeger {
public void play (Ball ball) {
ball.hit();
}
public static void main (String args[]) {
Ball ball = new Ball();
Schlaeger schlaeger = new Schlaeger();
schlaeger.play(ball);
}
}
public class Ball {
public void hit(){
System.out.println
geschlagen");
}
("Class
Ball:
Ball
wurde
}



in verteilten Umgebungen: analog  RMI
Klasse Ball befindet sich auf anderer Maschine
Problem:
 Referenzierung über Pointer nicht möglich (anderer Adressraum)
 Unterschiedliche Datenformate auf verschiedenen Maschinen
RMI ist folglich ein Mechanismus, um Methoden von Objekten aufzurufen, die nicht
auf der gleichen VM laufen.

Ist in mehreren Schichten aufgebaut
Server = Dienstanbieter
Client = Dienstnehmer
Beides sind normale Objekte, die in Java implementiert sind

Server  muß gekennzeichnet sein und für den R-Zugriff vorbereitet werden, bevor er
vom Client benutzt wird
 asymmetrische Beziehung
481352650
Seite 1 von 8
Netzwerk Programmierung


FH Merseburg SS 2002
Server muß Schnittstelle für R-Zugriff in IF-Beschreibung (von IF-Remote abgeleitet)
dokumentieren
aus dieser Beschreibung werden dann durch speziellen Compiler (rmic) zusätzliche
Klassen STUB und SKELETON erzeugt, die sich um die Kommunikationsabwicklung
kümmern

STUB ist Stellvertreterobjekt, das die gleiche Schnittstelle wie Serverobjekt anbietet und
einen Aufruf zu seinem Serverobjekt weiterleitet
 muß entweder auf dem Client-Rechner hinterlegt sein oder zur Laufzeit durch RMIClassloader geladen werden

SKELETON verbleibt auf Serverseite und
 nimmt Aufrufe des STUB entgegen
 bereitet diese auf
 gibt sie an das Serverobjekt weiter
 erwartet das Ergebnis und
 sendet Ergebnis zurück an STUB
Server
Client
Stub
Skeleton
RMI - Referenzschicht
RMI - Transportschicht
TCP/IP


Referenzschicht dient dazu, um den jeweiligen Kommunikationspartner zu finden
Teil dieser Schicht ist der Namensdienst, die Registry  rmiregistry

Transportschicht verwaltet Kommunikationsverbindungen (nicht OSI Transportschicht)
Konkrete Realisierung


Verteilte Objekte müssen sich anders verhalten als lokale O.
 Lokale Objekte erben von java.lang.Object
 Verteilte Objekte erben von java.rmi.RemoteObject
dadurch werden Methoden von java.lang überlagert und an Remote-Bedingungen
angepaßt
Serversicht





von java.rmi.RemoteObject ist java.rmi.UnicastRemoteObject abgeleitet, die eine Punktzu-Punkt-Verbindung anbietet
ein O, auf das über RMI zugegriffen werden soll, muß von dieser Klasse erben
die Schnittstelle, die das O für R-Zugriff anbieten möchte, muß über IF-definition
beschrieben werden  diese ist dann Grundlage für Erzeugung von Stubs und
Skeletons
nur hier definierte Methoden stehen auf R-Rechner zur Verfügung
das IF muß IF java.rmi.Remote erweitern
481352650
Seite 2 von 8
Netzwerk Programmierung
FH Merseburg SS 2002
java.rmi.RemoteObject
java.rmi.Remote
java.rmi.UnicastRemoteObject
MyServerInterface
extends
implements
MyServer
Grundprinzip entfernter Methodenaufruf

Server muß seine Dienste für R-Zugriff über IF zur Verfügung stellen
import java.rmi.*;
public interface RemoteBall extends Remote {
public void hit() throws java.rmi.RemoteException;
}

Serverobjekt muß
 diese Schnittstelle implementieren
 von RemoteObject bzw. UnicastRemoteObject erben
import java.rmi.*;
import java.rmi.server.*;
public class BallR extends UnicastRemoteObject implements RemoteBall
{
public BallR() throws RemoteException {
super();
//Initialisierung UnicastRemoteObject
}
public void hit(){
System.out.println
geschlagen");
}
("Class
BallR:
Der
Ball
wurde
public static void main(String args[]) {
try {
BallR ballr = new BallR();
// Wenn Ball erzeugt wurde, kann dieser bei der Registry
// angemeldet werden:
Naming.rebind("BallR", ballr);
}
catch (Exception e) {
e.printStackTrace();
}
}
}

danach müssen Stub und Skeleton erzeugt werden:
rmic BallR
// Parameter = class-Datei
 BallR_Stub.class  für Clientseite
 BallR_Skel.class  für Serverseite
481352650
Seite 3 von 8
Netzwerk Programmierung

beim Nachladen der Stub Datei über das Netz muss auf
SecurityManager eingerichtet werden:
FH Merseburg SS 2002
Clientseite ein
System.setSecurityManager(new RMISecurityManager());

Bevor Server gestartet werden kann, muß rmiregistry gestartet werden, die für den
Namensdienst und die Annahme von Anfragen verantwortlich ist
Clientsicht



C hat es einfacher, muß aber auch modifiziert werden um
 Zusätzliche Ausnahmen aufzufangen
 initale Verbindung zu einem R-Objekt herzustellen
aber keine Interfaces implementieren
um den Server finden zu können, wendet er sich an den Namensdienst auf dem
Rechner des Servers und fragt mittels des Namens nach dem gewünschten Dienst
import java.rmi.*;
public class SchlaegerR {
public BallR ballr;
public void play (RemoteBall ballr) {
try {
ballr.hit();
}catch (RemoteException e) {
System.out.println(e);
}
}
public static void main (String args[]) {
SchlaegerR batr = new SchlaegerR();
try {
System.setSecurityManager(new RMISecurityManager());
RemoteBall remoteBall = (RemoteBall) Naming.lookup(
"rmi://localhost/BallR");
schlaegerr.play(remoteBall);
}catch (Exception e) { System.out.println(e); }
}
}

Aufruf java SchlaegerR führt auf Serverrechner zu der Ausschrift:
Class BallR: Der Ball wurde geschlagen.
**** Ende des Beispiels Ball ****
Komplexeres Beispiel: Chat System


ChatServer
ChatClient

Im Socket-Beispiel wurden lediglich Strings ausgetauscht, die durch das vereinbarte
Protokoll als Chat-Beiträge interpretiert wurden

ChatServer stellt Dienste über IF zur Verfügung
481352650
Seite 4 von 8
Netzwerk Programmierung
FH Merseburg SS 2002

meldet seine Dienste beim lokalen Namensdienst an und wartet auf Anrufe


Client wendet sich an diesen Namensdienst auf der Servermaschine
Baut eine Referenz zum Serverobjekt auf und benutzt die Schnittstelle als wäre sie ein
lokales Objekt
public interface IChatServer extends java.rmi.Remote {
public void login(String name, IChatClient newClient)
throws java.rmi.RemoteException;
public void logout(String name)
throws java.rmi.RemoteException;
public void send(Message message)
throws java.rmi.RemoteException;
}

auch Objekte werden übergeben
 send() Methode  Message-Objekt (enthält Namen des Chatclients und Text)
public class Message implements java.io.Serializable {
public String name;
public String text;
public Message(String name, String text) {
this.name = name;
this.text = text;
}
}
 auch bei login()  ChatClient-Objekt wird übergeben


ChatClient beschreibt sich in diesem übergebenen Objekt selbst
Server benötigt aber nicht nur die Beschreibung des Clients sondern auch Referenz auf
ihn um ihm Nachrichten zukommen zu lassen  diese sollen über RMI-Methodenaufrufe
ausgetauscht werden
Konsequenz: ChatClient-Objekt muß ebenfalls als Remote gekennzeichnet werden
public interface IChatClient extends java.rmi.Remote {
public void receiveEnter(String name)
throws java.rmi.RemoteException;
public void receiveExit(String name)
throws java.rmi.RemoteException;
public void receiveMessage(Message message)
throws java.rmi.RemoteException;
}
Normale Objekte wie String oder Message werden, wenn sie als Parameter bei einem
Methodenaufruf übergeben werden, als Kopie übergeben, Objekte die das IF Remote
implementieren (wie IChatClient) werden als entfernte Referenz übergeben

Server kann daraufhin entfernte Methoden im ChatClient-Object aufrufen (recieveEnter()
für neue Chatmitglieder und recieveMessage() für neue Nachrichten) und ihm
Nachrichten zukommen lassen

Beispiel der Objektübergabe Message: Vorteil der OO vs Socket  bei Änderung der
Datenstruktur muß nicht gesamtes Auswertungsprotokoll wie bei Sockets geändert
werden
481352650
Seite 5 von 8
Netzwerk Programmierung
FH Merseburg SS 2002
Nachdem die Schnittstellen definiert sind, kann man sie implementieren:
import java.rmi.*;
import java.rmi.server.*;
public
class
IChatClient{
ChatClient
ChatFrame gui;
String name;
IChatServer server;
String serverUrl;
extends
UnicastRemoteObject
implements
// GUI wie bei Socketbeispiel
public ChatClient(String name, String url) throws RemoteException{
this.name = name;
serverUrl = url;
// GUI erzeugen und Events behandeln:
// Nach Texteingaben wird sendTextToChat() aufgerufen,
// bei Schließen des Fensters wird disconnect() aufgerufen.
gui = new ChatFrame("Chat mit RMI");
gui.input.addKeyListener (new EnterListener(this,gui));
gui.addWindowListener(new ExitListener(this));
connect();
}
private void connect() {
try {
server = (IChatServer) java.rmi.Naming.lookup
("rmi://"+serverUrl+ "/ChatServer");
server.login(name, this);
} catch (Exception e) { e.printStackTrace();}
}
protected void sendTextToChat(String text) {
try {
server.send(new Message(name,text));
} catch (RemoteException e) {e.printStackTrace();}
}
protected void disconnect() {
try {
server.logout(name);
} catch (Exception e) {e.printStackTrace();}
}
// im GUI wird neuer Chatteilnehmer ausgegegben
public void receiveEnter(String name) {
gui.output.append(name+" entered \n");
}
// im GUI wird Verlassen eines Teilnehmers angezeigt
public void receiveExit(String name) {
gui.output.append(name+" left \n");
}
// im GUI wird neue Message ausgegegben
public void receiveMessage(Message message) {
gui.output.append(message.name+": "+message.text+"\n");
}
public static void main(String[] args) {
if (args.length==2) {
try {
System.setSecurityManager(new RMISecurityManager());
new ChatClient(args[0],args[1]);
} catch (RemoteException e) {
481352650
Seite 6 von 8
Netzwerk Programmierung
e.printStackTrace();
}
}
else {
System.out.println("Aufruf:
<server>");
}
FH Merseburg SS 2002
java
ChatClient
<name>
}
}
Serverimplementierung


Server hält Kontakt zu mehreren Clients
alle eingehenden Nachrichten muss er an diese verteilen


Clientverwaltung über Hash-Tabelle wobei die Namen als Schlüssel fungieren
Aus dieser Tabelle wird eine Enumeration (Aufzählung) erzeugt, die der Reihe nach
abgearbeitet wird und jeweils einen Client ausgibt, dem die Nachricht geschickt wird

Server hält dabei die entfernten Referenzen, so daß der Aufruf über RMI abgewickelt
wird
import java.rmi.*;
import java.rmi.server.*;
import java.util.*;
public class ChatServer extends UnicastRemoteObject implements
IChatServer {
Hashtable chatters = new Hashtable();
public ChatServer() throws RemoteException {
}
public synchronized void login(String name, IChatClient newClient) throws RemoteException {
Enumeration enum = chatters.elements();
chatters.put(name, newClient);
// login allen Clients bekannt geben
while (enum.hasMoreElements()) {
((IChatClient) enum.nextElement()).receiveEnter(name);
}
System.out.println("Neuer Client "+name+" eingelogged");
}
public synchronized void logout(String name) throws RemoteException {
chatters.remove(name);
Enumeration enum = chatters.elements();
// logout allen Clients bekannt geben
while (enum.hasMoreElements()) {
((IChatClient)enum.nextElement()).receiveExit(name);
}
}
public synchronized void send(Message message) throws RemoteException {
Enumeration enum = chatters.elements();
while (enum.hasMoreElements()) {
((IChatClient)enum.nextElement()).receiveMessage(message);
}
}
public static void main(String[] args) {
481352650
Seite 7 von 8
Netzwerk Programmierung
FH Merseburg SS 2002
try {
ChatServer server = new ChatServer();
Naming.rebind("ChatServer", server);
} catch (Exception ex) {ex.printStackTrace();}
}}
***
481352650
Seite 8 von 8
Herunterladen