26.10.2012 Aufrufe

Programmieren in Java

Programmieren in Java

Programmieren in Java

MEHR ANZEIGEN
WENIGER ANZEIGEN

Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.

YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.

HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />

FG TECHNISCHE INFORMATIK V – JV – 800 – 00 – TH – 03<br />

-----------------------------------------------------------------------------------<br />

<strong>Programmieren</strong> <strong>in</strong> <strong>Java</strong><br />

Kapitel 8<br />

8. <strong>Java</strong> <strong>in</strong> verteilten Systemen<br />

8.1. Socket-basierte Kommunikation<br />

8.2. Remote Method Invocation (RMI)


FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />

FG TECHNISCHE INFORMATIK V – JV – 801 – 00 – TH – 01<br />

-----------------------------------------------------------------------------------<br />

• Verteilte Systeme<br />

Grundlegendes zu verteilten Systemen<br />

◇ Verteilte Systeme bestehen aus zwei oder mehr unabhängigen aber mite<strong>in</strong>ander verbundenen Rechnern (z.B. über<br />

e<strong>in</strong> Netzwerk), die zur geme<strong>in</strong>samen Lösung von Aufgaben e<strong>in</strong>gesetzt werden können.<br />

◇ Die geme<strong>in</strong>sam zu lösende Aufgabe wird auf mehrere Prozesse aufgeteilt, die auf unterschiedlichen Rechnern laufen.<br />

� Verteilte Anwendung<br />

◇ Die an e<strong>in</strong>er verteilten Anwendung beteiligten Prozesse müssen mite<strong>in</strong>ander Informationen austauschen. Die dafür<br />

notwendige Interprozess-Kommunikation über Rechnergrenzen h<strong>in</strong>weg erfordert die Def<strong>in</strong>ition und E<strong>in</strong>haltung<br />

bestimmter Schnittstellen und Protokolle.<br />

Derartige Protokolle können auf unterschiedlichen Ebenen (Schichten) e<strong>in</strong>gesetzt werden.<br />

• Client-Server-Modell<br />

◇ Am häufigsten arbeiten verteilte Anwendungen nach dem Client-Server-Modell :<br />

E<strong>in</strong> Server-Prozess stellt Dienstleistungen über e<strong>in</strong>e def<strong>in</strong>ierte Schnittstelle zur Verfügung. Diese Dienstleistungen<br />

können von Client-Prozessen genutzt werden.<br />

◇ Die Kommunikation zwischen Client und Server folgt dem – asymmetrischen – Request-Response-Pr<strong>in</strong>zip :<br />

E<strong>in</strong> Client richtet zu e<strong>in</strong>em beliebigen Zeitpunkt – also asynchron – e<strong>in</strong>e Anfrage (request) an den auf Anfragen wartenden<br />

Server. Der Server antwortet (response) i.a. <strong>in</strong>nerhalb e<strong>in</strong>er bestimmten Zeit – also synchron – auf diese Anfrage.<br />

◇ Häufig kann e<strong>in</strong> Server gleichzeitig zu mehreren Clients Kommunikationsbeziehungen unterhalten (Multithread-<br />

Server)<br />

◇ Verteilte Anwendungen, bei denen die beteiligten Prozesse sowohl als Server als auch als Client agieren, arbeiten nach<br />

dem Peer-to-Peer-Modell<br />

◇ Pr<strong>in</strong>zipiell werden zwei Verb<strong>in</strong>dungsarten e<strong>in</strong>er Rechnergrenzen überschreitenden Interprozess-Kommunikation<br />

unterschieden :<br />

▻ verb<strong>in</strong>dungsorientierte Kommunikation :<br />

Zwischen Client und Server wird für die Dauer der Kommunikation e<strong>in</strong>e ständige – virtuelle – Verb<strong>in</strong>dung herge-<br />

stellt. Diese Verb<strong>in</strong>dung muss aufgebaut werden, bevor die eigentliche Kommunikation stattf<strong>in</strong>den kann.<br />

� Die e<strong>in</strong>zelnen Sendeoperationen benötigen ke<strong>in</strong>e expliziten Angaben über die Empfängeradresse.<br />

▻ verb<strong>in</strong>dungslose Kommunikation :<br />

Zwischen Client und Server existiert ke<strong>in</strong>e ständige Kommunikationsverb<strong>in</strong>dung. Diese wird vielmehr mit jeder<br />

e<strong>in</strong>zelnen Sendeoperation neu hergestellt.<br />

� Jeder Sendeoperation muss die Adresse des Empfängers explizit mitgegeben werden.<br />

• Programmierschnittstellen<br />

◇ Die programmtechnische Implementierung von Client-Server-Kommunikationen kann auf unterschiedlichen Schichten<br />

erfolgen (OSI-Schichten-Modell der Rechnerkommunikation !)<br />

◇ Am weitesten verbreitet s<strong>in</strong>d heute :<br />

▻ Sockets, Programmierschnittstelle der Transportschicht (bzw Vermittlungsschicht)<br />

Sockets def<strong>in</strong>ieren den jeweiligen Kommunikations-Endpunkt e<strong>in</strong>er logischen Verb<strong>in</strong>dung zwischen Server und<br />

Client. Sie basieren auf dem für die jeweilige Verb<strong>in</strong>dung e<strong>in</strong>gesetzten Kommunikationsprotokoll-Typ und den<br />

von diesem verwendeten Adress-Angaben. � Es gibt unterschiedliche Socket-Typen<br />

Sockets ermöglichen e<strong>in</strong>e bidirektionale Kommunikation (Senden und Empfangen) mittels I/O-Operationen<br />

analog zu Datei- bzw Stream-Zugriffen.<br />

E<strong>in</strong>e Kommunikation über e<strong>in</strong>en Socket kann erst stattf<strong>in</strong>den, wenn er an e<strong>in</strong>e lokale Adresse gebunden ist<br />

▻ Prozedur-Fernaufrufe (Remote Procedure Calls), Programmierschnittstelle der Anwendungsschicht<br />

Sie ermöglichen den Aufruf von Unterprogrammen (Funktionen), die sich <strong>in</strong> e<strong>in</strong>em anderen Prozessraum be-<br />

f<strong>in</strong>den unter Anwendung der gleichen Semantik wie für den Aufruf lokaler Unterprogramme.<br />

Die Implementierung dieses Konzepts <strong>in</strong> <strong>Java</strong> wird Remote Method Invocation (RMI) genannt. RMI erlaubt den<br />

Aufruf von Methoden für Objekte, die sich <strong>in</strong> e<strong>in</strong>er anderen JVM (i.a. auf e<strong>in</strong>em anderen Rechner) bef<strong>in</strong>den.


FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />

FG TECHNISCHE INFORMATIK V – JV – 811 – 00 – TH – 01<br />

-----------------------------------------------------------------------------------<br />

Socket-basierte Kommunikation <strong>in</strong> <strong>Java</strong> (1)<br />

• Pr<strong>in</strong>zip der verb<strong>in</strong>dungsorientierten Socket-Kommunikation<br />

◇ Der Server-Prozess erzeugt e<strong>in</strong>en Socket, den er an e<strong>in</strong>e lokale Adresse (Server-Adresse) b<strong>in</strong>det.<br />

Art und Aufbau der Adresse hängen von der für die Kommunikation e<strong>in</strong>gesetzten Protokoll-Familie ab.<br />

An diesem Socket wartet der Server auf Verb<strong>in</strong>dungswünsche durch Clients ("Horch"-Socket).<br />

◇ E<strong>in</strong> Client-Prozess <strong>in</strong>itiiert e<strong>in</strong>e Verb<strong>in</strong>dung zum Server, <strong>in</strong> dem er e<strong>in</strong>en Socket erzeugt und über diesen e<strong>in</strong>en<br />

Verb<strong>in</strong>dungswunsch an die Server-Adresse sendet.<br />

◇ Falls der Server-Prozess den Verb<strong>in</strong>dungswunsch akzeptiert, erzeugt er e<strong>in</strong>en neuen Socket, über den dann die eigent-<br />

liche Kommunikation mit dem Client stattf<strong>in</strong>den kann ("Kommunikations"-Socket).<br />

◇ Die anschliessende eigentliche Client-Server-Kommunikation erfolgt über die Sockets mittels dateianaloger Schreib-<br />

und Lese-Operationen<br />

◇ Die Kommunikation wird beendet, wenn der Client-Socket oder/und der "Kommunikations"-Socket des Servers<br />

geschlossen werden.<br />

◇ E<strong>in</strong> sequentieller Server kann erst nach Abschluss e<strong>in</strong>er Client-Kommunikation auf weitere Verb<strong>in</strong>dungswünsche<br />

warten.<br />

Bei e<strong>in</strong>em Multi-Thread-Server f<strong>in</strong>det jede Client-Kommunikation <strong>in</strong> e<strong>in</strong>em seperaten Thread statt.<br />

E<strong>in</strong> derartiger Server kann auf weitere Verb<strong>in</strong>dungswünsche unmittelbar nach Erzeugung des Kommunikations-Threads<br />

warten<br />

◇ Pr<strong>in</strong>zipieller Ablauf :<br />

Client<br />

Erzeugung e<strong>in</strong>es Sockets<br />

Verb<strong>in</strong>dungswunsch<br />

an die Server-Adresse<br />

Schreib-Operation<br />

Lese-Operation<br />

Schliessen<br />

des Sockets<br />

Verb<strong>in</strong>dungsaufnahme<br />

Kommunikation<br />

Server<br />

Erzeugung<br />

e<strong>in</strong>es "Horch"-Sockets<br />

B<strong>in</strong>dung an die Server-Adresse<br />

Warten auf<br />

Verb<strong>in</strong>dungswünsche<br />

durch Clients<br />

Akzeptieren e<strong>in</strong>es<br />

Verb<strong>in</strong>dungswunsches<br />

Erzeugung e<strong>in</strong>es<br />

"Kommunikations"-Sockets<br />

Lese-Operation<br />

Schreib-Operation<br />

Schliessen des<br />

"Kommunikations"-Sockets<br />

Multi-Thread-<br />

Multi-Thread-<br />

Server<br />

Server<br />

sequentieller Server


FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />

FG TECHNISCHE INFORMATIK V – JV – 812 – 00 – TH – 03<br />

------------------------------------------------------------------------------------<br />

• INET-Sockets<br />

Socket-basierte Kommunikation <strong>in</strong> <strong>Java</strong> (2)<br />

◇ INET-Sockets s<strong>in</strong>d Sockets für die TCP/IP-Protokoll-Familie.<br />

Diese Protokoll-Familie hat derzeit für die Rechnerkommunikation die grösste Bedeutung.<br />

U.a. wird sie im Internet, aber auch <strong>in</strong> den meisten lokalen Netzen e<strong>in</strong>gesetzt.<br />

◇ Adressen der TCP/IP-Protokoll-Familie (INET-Adressen) bestehen aus zwei Komponenten :<br />

▻ IP-Adresse : Sie bestimmt den Rechner, auf dem e<strong>in</strong> Prozess läuft<br />

4 Bytes (IP4-Adresse) bzw 16 Bytes (IP6-Adresse) gross.<br />

▻ Port-Nummer : Sie identifiziert den Prozess (Applikation) auf e<strong>in</strong>em Rechner.<br />

2 Bytes gross : ganze Zahl zwischen 0 und 65535<br />

(0 bis 1023 reserviert für systemnahe Dienste, well-known ports)<br />

◇ Zur besseren Verständlichkeit für den benutzenden Menschen werden IP-Adressen häufig auf Rechner-Namen<br />

(host names) abgebildet.<br />

Die Umsetzung von Rechner-Namen <strong>in</strong> IP-Adressen erfolgt u.a. durch Doma<strong>in</strong> Name Server (DNS).<br />

◇ Die beiden wichtigsten Protokolle dieser Protokoll-Familie s<strong>in</strong>d :<br />

▻ TCP (Transmission Control Protocol)<br />

▻ UDP (User Datagram Protocol)<br />

◇ TCP ist e<strong>in</strong> Protokoll für die verb<strong>in</strong>dungsorientierte Kommunikation.<br />

Es arbeitet streambasiert und mit Fehlerkontrolle. Dadurch bietet es Schutz gegen Datenverlust und Übertragungsfehler.<br />

Ausserdem stellt es die Beibehaltung der Daten-Reihenfolge sicher (sequenc<strong>in</strong>g). � zuverlässiges Protokoll<br />

Sockets für dieses Protokoll werden als Stream-Sockets bezeichnet.<br />

◇ UDP ist e<strong>in</strong> Protokoll für die verb<strong>in</strong>dungslose Kommunikation.<br />

Es arbeitet paketbasiert (Übertragung unabhängiger Datenpakete == Datagramme) sowie ohne Fehlerkontrolle und<br />

Sequenc<strong>in</strong>g. Dadurch s<strong>in</strong>d weder Verlustlosigkeit und Fehlerfreiheit noch die Beibehaltung der Datenreihenfolge<br />

sichergestellt. � unzuverlässiges Protokoll. Dafür ist die Übertragungsleistung dieses Protokolls höher.<br />

Sockets für dieses Protokoll werden Datagram-Sockets genannt.<br />

• Unterstützung von INET-Sockets <strong>in</strong> <strong>Java</strong><br />

◇ Die Implementierung von verteilten Anwendungen mittels INET-Sockets werden <strong>in</strong> <strong>Java</strong> sehr effizient durch geeignete<br />

Klassen der Standard-Bibliothek unterstützt. Die entsprechenden Klassen bef<strong>in</strong>den sich im Package java.net.<br />

◇ Zur Implementierung von Stream-Sockets existieren die Klassen<br />

▻ ServerSocket : Klasse für "Horch"-Sockets <strong>in</strong> Server-Prozessen<br />

▻ Socket : Klasse für "Kommunikations"-Sockets <strong>in</strong> Client- und Server-Prozessen<br />

◇ Die Implementierung e<strong>in</strong>er verb<strong>in</strong>dungslosen Kommunikation über Datagram-Sockets ermöglichen die Klassen :<br />

▻ DatagramSocket : Klasse für Datagramm-Sockets<br />

▻ DatagramPacket : Klasse zur Beschreibung der zu übertragenen Datenpakete<br />

◇ Socket-Adressen werden repräsentiert durch<br />

▻ SocketAddress : abstrakte Basisklasse für Socket-Adressen, ke<strong>in</strong>e konkrete Protokollb<strong>in</strong>dung<br />

▻ InetSocketAddress : konkrete Klasse für Adressen der TCP/IP-Protokoll-Familie (INET-Adresse)<br />

◇ Zur Repräsentation von IP-Adressen existieren die Klassen :<br />

▻ InetAddress : Darstellung sowohl von IP4-Adressen (4-Bytes) als auch IP6-Adressen (16 Bytes)<br />

▻ Inet4Address : Darstellung von IP4-Adressen (abgeleitet von InetAddress)<br />

▻ Inet6Address : Darstellung von IP6-Adressen (abgeleitet von InetAddress)<br />

◇ Zur Repräsentation von Internet-Resourcen referierenden URLs (Uniform Resource Locator) dient die Klasse<br />

▻ URL<br />

◇ Über die o.a. Klassen h<strong>in</strong>aus umfasst das Package java.net noch e<strong>in</strong>e Reihe weiterer Klassen.


FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />

FG TECHNISCHE INFORMATIK V – JV – 813 – 00 – TH – 03<br />

------------------------------------------------------------------------------------<br />

• Die Klasse InetAddress<br />

◇ Enthalten im Package java.net.<br />

Socket-basierte Kommunikation <strong>in</strong> <strong>Java</strong> (3)<br />

◇ Objekte dieser Klasse repräsentieren IP-Adressen<br />

Über Variable dieses Typs werden tatsächlich Inet4Address-Objekte (für IP4-Adressen (4-Bytes)) bzw<br />

Inet6Address-Objekte (für IP6-Adressen (16 Bytes)) referiert.<br />

Die Klasse InetAddress stellt e<strong>in</strong> geme<strong>in</strong>sames Verwendungs<strong>in</strong>terface für beide Arten von IP-Adressen zur<br />

Verfügung<br />

◇ Die Klasse besitzt ke<strong>in</strong>e öffentlichen Konstruktoren.<br />

Zur Objekterzeugung existieren statische Memberfunktionen. Diesen kann entweder die IP-Adresse (als Byte-Array<br />

oder als Str<strong>in</strong>g <strong>in</strong> dotted decimal notation) oder (gegebenenfalls und) der Rechnername übergeben werden.<br />

Bei alle<strong>in</strong>iger Übergabe des Rechnernamens wird zur Ermittlung der IP-Adresse die im System <strong>in</strong>stallierte Methode zur<br />

Namensauflösung (address resolution) verwendet.<br />

Ist e<strong>in</strong>e übergebene IP-Adresse dem Format nach ungültig oder schlägt die Namensauflösung fehl wird von den<br />

Erzeugungsmethoden e<strong>in</strong>e UnknownHostException (abgeleitet von IOException) geworfen.<br />

◇ Neben der IP-Adresse enthalten InetAddress-Objekte gegebenenfalls auch den zugehörigen Rechnernamen.<br />

Dies ist dann der Fall, wenn der Name bei der Objekterzeugung verwendet wurde oder e<strong>in</strong>e <strong>in</strong>verse Namensauflösung<br />

(reverse host name resolution) vorgenommen wurde.<br />

◇ Die Klasse InetAddress verwaltet e<strong>in</strong>en Cache, <strong>in</strong> dem erfolgreiche und nicht erfolgreiche Namensauflösungen<br />

abgelegt werden.<br />

◇ Es existieren u.a. Instanz-Memberfunktionen, die die gespeicherte IP-Adresse bzw den Rechnernamen zurück-<br />

liefern.<br />

◇ Statische Memberfunktion der Klasse InetAddress zur Objekterzeugung (Auswahl)<br />

public static Erzeugung e<strong>in</strong>es InetAddress-Objekts (genauer :<br />

InetAddress getByAddress(byte[] addr) e<strong>in</strong>es Inet4Address- bzw Inet6Address-<br />

throws UnknownHostException Objekts) mit der durch addr gegebenen IP-Adresse.<br />

Der Parameter addr muss die Address-Bytes <strong>in</strong><br />

Network Byte Order (big endian) enthalten<br />

public static Erzeugung e<strong>in</strong>es InetAddress-Objekts (genauer :<br />

InetAddress getByName(Str<strong>in</strong>g host) e<strong>in</strong>es Inet4Address- bzw Inet6Address-<br />

throws UnknownHostException Objekts) mit der durch Namensauflösung des Rechner-<br />

namens host ermittelten IP-Adresse.<br />

Der Parameter host kann auch direkt die IP-Adresse<br />

<strong>in</strong> Str<strong>in</strong>gdarstellung (dotted decimal notation) enthalten<br />

In diesem Fall entfällt e<strong>in</strong>e Namensauflösung<br />

◇ Instanz-Memberfunktion der Klasse InetAddress (Auswahl)<br />

public byte[] getAddress() Rückgabe der IP-Adresse als Byte-Array (<strong>in</strong> Network Byte Order)<br />

public Str<strong>in</strong>g getHostAddress() Rückgabe der IP-Adresse als Str<strong>in</strong>g <strong>in</strong> dotted decimal notation<br />

public Str<strong>in</strong>g getHostName() Rückgabe des Rechnernamens falls dieser im Objekt gespeichert ist<br />

oder durch <strong>in</strong>verse Namensauflösung ermittelt werden kann.<br />

Ist e<strong>in</strong> Security-Manager <strong>in</strong>stalliert, so wird bei erforderlicher <strong>in</strong>verser<br />

Namensauflösung dieser befragt, ob die Operation zulässig ist<br />

Ist die <strong>in</strong>verse Namensauflösung unzulässig oder kann der Rechner-<br />

name nicht ermittelt werden, wird die IP-Adresse als Str<strong>in</strong>g <strong>in</strong> dotted<br />

decimal notation zurückgegeben.


HOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />

FG TECHNISCHE INFORMATIK V – JV – 814 – 00 – TH – 04<br />

------------------------------------------------------------------------------------<br />

• Die abstrakte Klasse SocketAddress<br />

◇ Enthalten im Package java.net.<br />

Socket-basierte Kommunikation <strong>in</strong> <strong>Java</strong> (4)<br />

◇ Diese Klasse repräsentiert generische – an ke<strong>in</strong> konkretes Protokoll gebundene – Socket-Adressen.<br />

◇ Variable dieses Typs müssen immer Objekte e<strong>in</strong>er konkreten von SocketAddress abgeleiteten Klasse referieren.<br />

Objekte e<strong>in</strong>er derartigen Klasse repräsentieren an jeweils e<strong>in</strong> konkretes Protokoll gebundene Socket-Adressen.<br />

Z. Zt. existiert <strong>in</strong> der <strong>Java</strong>-Standard-Bibliothek lediglich die abgeleitete Klasse InetSocketAddress (für<br />

Adressen der TCP/IP-Protokoll-Familie)<br />

◇ Die Klasse wird u.a. als Typangabe (Parameter- und Rückgabetyp) <strong>in</strong> Methoden der Klassen Socket und<br />

ServerSocket verwendet.<br />

• Die Klasse InetSocketAddress<br />

◇ Enthalten im Package java.net.<br />

◇ Objekte dieser Klasse repräsentieren Adressen der TCP/IP-Protokoll-Familie (INET-Adressen)<br />

� Sie enthalten e<strong>in</strong>e IP-Adresse und e<strong>in</strong>e Port-Nummer.<br />

◇ Bei der Objekterzeugung s<strong>in</strong>d dem Konstruktor die IP-Adresse (als InetAddress-Objekt) und die Port-Nummer<br />

zu übergeben.<br />

E<strong>in</strong>em alternativen Konstruktor kann statt der IP-Adresse auch der Rechnername übergeben werden. In diesem Fall<br />

wird e<strong>in</strong>e Namensauflösung versucht. Bei Fehlschlag derselben wird der Name im Objekt gespeichert. Das Objekt<br />

repräsentiert dann e<strong>in</strong>e nichtaufgelöste Adresse (unresolved address). Diese kann beispielsweise bei Verb<strong>in</strong>dungs-<br />

aufnahme über e<strong>in</strong>en Proxy verwendet werden.<br />

◇ Die Klasse InetSocketAddress besitzt Memberfunktionen, mit denen die Komponenten e<strong>in</strong>er von e<strong>in</strong>em<br />

Objekt repräsentierten Adresse ermittelt werden können.<br />

◇ Konstruktoren der Klasse InetSocketAddress<br />

public InetSocketAddress(InetAddress addr, Erzeugung e<strong>in</strong>er INET-Adresse aus der IP-Adresse<br />

<strong>in</strong>t port) addr und der Port-Nr port<br />

public InetSocketAddress(<strong>in</strong>t port) Erzeugung e<strong>in</strong>er INET-Adresse aus der IP-Adresse<br />

0.0.0.0 (wildcard) und der Port-Nr port<br />

public Erzeugung e<strong>in</strong>er INET-Adresse aus der durch<br />

InetSocketAddress(Str<strong>in</strong>g host, <strong>in</strong>t port) Namensauflösung von host ermittelten IP-Adresse<br />

und der Port-Nr port<br />

◇ Memberfunktionen der Klasse InetSocketAddress (Auswahl)<br />

public f<strong>in</strong>al InetAddress getAddress() Rückgabe der IP-Adresse (als InetAddress-Objekt)<br />

public f<strong>in</strong>al <strong>in</strong>t getPort() Rückgabe der Port-Nummer<br />

public f<strong>in</strong>al Str<strong>in</strong>g getHostName() Rückgabe des Rechnernamens<br />

public f<strong>in</strong>al boolean isUnresolved() Überprüfung, ob der Rechnername aufgelöst werden<br />

konnte<br />

Rückgabe von true, wenn Auflösung nicht möglich war<br />

Rückgabe von false, wenn Auflösung möglich war


FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />

FG TECHNISCHE INFORMATIK V – JV – 815 – 00 – TH – 01<br />

-----------------------------------------------------------------------------------<br />

• Die Klasse Socket<br />

◇ Enthalten im Package java.net.<br />

Socket-basierte Kommunikation <strong>in</strong> <strong>Java</strong> (5)<br />

◇ Objekte dieser Klasse implementieren TCP-"Kommunikations-Sockets".<br />

◇ Client-seitige Sockets bauen üblicherweise bei ihrer Erzeugung e<strong>in</strong>e Verb<strong>in</strong>dung zu e<strong>in</strong>em Server auf.<br />

Hierfür muss ihrem Konstruktor die IP-Adresse und die Port-Nummer der Server-Applikation übergeben werden.<br />

Dadurch werden sie auch automatisch an e<strong>in</strong>e geeignete lokale Adresse gebunden.<br />

Falls e<strong>in</strong> Security-Manager <strong>in</strong>stalliert ist, überprüft dieser die Zulässigkeit der gewünschten Verb<strong>in</strong>dung.<br />

Bei Unzulässigkeit wird e<strong>in</strong>e SecurityException geworfen.<br />

Alternativ kann auch e<strong>in</strong> unverbundener Socket erzeugt werden (parameterloser Konstruktor).<br />

E<strong>in</strong> derartiger Socket ist dann auch an ke<strong>in</strong>e lokale Adresse gebunden.<br />

E<strong>in</strong> explizites B<strong>in</strong>den an e<strong>in</strong>e lokale Adresse ist mit der Memberfunktion b<strong>in</strong>d(...) möglich.<br />

Der spätere Aufbau e<strong>in</strong>er Server-Verb<strong>in</strong>dung sowie gegebenenfalls die implizite B<strong>in</strong>dung an e<strong>in</strong>e lokale Adresse<br />

kann mittels der Methode connect(...) erfolgen.<br />

◇ Server-seitige Sockets werden beim Akzeptieren e<strong>in</strong>es Client-Verb<strong>in</strong>dungswunsches durch den "Horch-Socket" erzeugt.<br />

◇ Zur Kommunikation stellen Socket-Objekte jeweils e<strong>in</strong> InputStream- und e<strong>in</strong> OutputStream-Objekt<br />

zur Verfügung � dateiartige Lese- und Schreib-Operationen.<br />

◇ Nach Beendigung der Kommunikation sollten die Stream-Objekte (zuerst) und das Socket-Objekt geschlossen<br />

werden.<br />

◇ Viele Memberfunktionen (und Konstruktoren) der Klasse Socket können Exceptions verschiedenen Typs werfen<br />

(s. API-Dokumentation)<br />

◇ Konstruktoren der Klasse Socket (Auswahl)<br />

public Socket() Erzeugung e<strong>in</strong>es unverbundenen Sockets<br />

Der Socket ist auch an ke<strong>in</strong>e lokale Adresse gebunden<br />

public Socket(Str<strong>in</strong>g host, <strong>in</strong>t port) Erzeugung e<strong>in</strong>es Sockets, der mit der durch host (Rechner-<br />

throws UnknownHostException, name oder IP-Adr. als Str<strong>in</strong>g) und port def<strong>in</strong>ierten Server-<br />

IOException Adresse verbunden ist.<br />

Der Socket wird an e<strong>in</strong>e geeignete lokale Adresse gebunden<br />

public Socket(InetAddress adr, Erzeugung e<strong>in</strong>es Sockets, der mit der durch adr und<br />

<strong>in</strong>t port) und port def<strong>in</strong>ierten Server-Adresse verbunden ist<br />

throws IOException Der Socket wird an e<strong>in</strong>e geeignete lokale Adresse gebunden<br />

◇ Memberfunktionen der Klasse Socket (Auswahl)<br />

public void b<strong>in</strong>d(SocketAddress adr) B<strong>in</strong>den des Sockets an die lokale Socket-Adresse adr<br />

throws IOException (bei der Adresse muss es sich um e<strong>in</strong>e INET-Adr. handeln)<br />

public void connect(SocketAddress adr) Aufbau e<strong>in</strong>er Verb<strong>in</strong>dung zum Server mit der Adresse adr<br />

throws IOException (bei der Adresse muss es sich um e<strong>in</strong>e INET-Adr. handeln)<br />

public InputStream getInputStream() Rückgabe e<strong>in</strong>es InputStream-Objekts, mit dem aus<br />

throws IOException dem Socket gelesen (empfangen) werden kann<br />

public OutputStream getOutputStream() Rückgabe e<strong>in</strong>es OutputStream-Objekts, mit dem <strong>in</strong><br />

throws IOException den Socket geschrieben (gesendet) werden kann<br />

public void close() throws IOException Schliessen des Sockets<br />

Memberfunktionen zum Ermitteln der lokalen sowie der verbundenen (entfernten) Adresse, sowohl als INET-<br />

Adresse (SocketAddress-Objekt) als auch getrennt für IP-Adresse und Port-Nr), s. API-Dokumentation


FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />

FG TECHNISCHE INFORMATIK V – JV – 816 – 00 – TH – 01<br />

-----------------------------------------------------------------------------------<br />

• Die Klasse ServerSocket<br />

◇ Enthalten im Package java.net.<br />

Socket-basierte Kommunikation <strong>in</strong> <strong>Java</strong> (6)<br />

◇ Objekte dieser Klasse implementieren TCP-"Horch-Sockets" (Server-Sockets).<br />

◇ Üblicherweise wird e<strong>in</strong> Server-Socket gleich bei se<strong>in</strong>er Erzeugung an die lokale Adresse gebunden, an der er auf<br />

Verb<strong>in</strong>dungswünsche warten soll.<br />

Da die IP-Adresse i.a. bekannt ist, muss dem Konstruktor normalerweise nur die Port-Nr übergeben werden.<br />

Alternativ kann dem Konstruktor zusätzlich noch die maximale Grösse der Warteschlange für anstehende Verb<strong>in</strong>-<br />

dungswünsche übergeben werden (backlog). Ohne diese Angabe wird hierfür der Defaultwert 50 verwendet.<br />

Bei voller Warteschlange werden weitere Verb<strong>in</strong>dungswünsche zurückgewiesen.<br />

Es existiert auch e<strong>in</strong> Konstruktor, dem zusätzlich e<strong>in</strong>e IP-Adresse (als InetAddress-Objekt) übergeben werden<br />

kann. Dies ermöglicht für Server-Prozesse, die sich auf e<strong>in</strong>em über mehrere IP-Adressen verfügenden Rechner bef<strong>in</strong>den,<br />

die Festlegung e<strong>in</strong>er bestimmten Horch-Adresse .<br />

◇ Alternativ kann auch e<strong>in</strong> Socket erzeugt werden, der an ke<strong>in</strong>e lokale Adresse gebunden ist (parameterloser Konstruktor).<br />

In diesem Fall ist e<strong>in</strong> späteres B<strong>in</strong>den an e<strong>in</strong>e lokale Adresse mit der Memberfunktion b<strong>in</strong>d(...) möglich.<br />

◇ Falls e<strong>in</strong> Security-Manager <strong>in</strong>stalliert ist, überprüft dieser sowohl <strong>in</strong> den Konstruktoren als auch <strong>in</strong> der Methode<br />

b<strong>in</strong>d(..), ob an der lokalen Adresse e<strong>in</strong> anschliessendes Warten ("Horchen") auf Verb<strong>in</strong>dungswünsche zulässig ist.<br />

Bei Unzulässigkeit wird e<strong>in</strong>e SecurityException geworfen.<br />

◇ Durch Aufruf der Methode accept() wird e<strong>in</strong> ServerSocket <strong>in</strong> den blockierenden Wartezustand versetzt, <strong>in</strong> dem<br />

er auf Verb<strong>in</strong>dungswünsche durch Clients wartet ("Horch-Zustand").<br />

Für e<strong>in</strong>en akzeptierten Verb<strong>in</strong>dungswunsch erzeugt accept() e<strong>in</strong>en "Kommunikations-Socket". Dieser Socket<br />

ist an e<strong>in</strong> neues Port gebunden. Dies ermöglicht e<strong>in</strong>em Multi-Thread-Server (Server, bei dem die Kommunikation mit<br />

e<strong>in</strong>em Client jeweils <strong>in</strong> e<strong>in</strong>em eigenen Thread stattf<strong>in</strong>det) sofort nach dem Akzeptieren e<strong>in</strong>es Verb<strong>in</strong>dungswunsches<br />

an dem "Horch"-Port auf weitere Verb<strong>in</strong>dungswünsche zu warten.<br />

Falls e<strong>in</strong> Security-Manager <strong>in</strong>stalliert ist, überprüft dieser ob die Erzeugung des vorgesehenen "Kommunikations-<br />

Sockets" zulässig ist. Bei Unzulässigkeit wird e<strong>in</strong>e SecurityException geworfen.<br />

◇ Auch e<strong>in</strong> ServerSocket-Objekt sollte geschlossen werden, wenn es nicht mehr benötigt wird<br />

◇ Viele Memberfunktionen (und Konstruktoren) der Klasse ServerSocket können Exceptions verschiedenen Typs<br />

werfen (s. API-Dokumentation)<br />

◇ Konstruktoren der Klasse ServerSocket (Auswahl)<br />

public ServerSocket() Erzeugung e<strong>in</strong>es an ke<strong>in</strong>e lokale Adresse gebundenen Sockets<br />

throws IOException<br />

public ServerSocket(<strong>in</strong>t port) Erzeugung e<strong>in</strong>es Server-Sockets, der an die IP-Adresse 0.0.0.0<br />

throws IOException (wildcard) und die Port-Nr. port gebunden ist.<br />

Herstellung der Bereitschaft, auf Verb<strong>in</strong>dungswünsche zu warten<br />

Für port==0 kann auf allen Ports gewartet werden.<br />

Die maximale Grösse der Warteschlange wird auf 50 gesetzt<br />

◇ Memberfunktionen der Klasse ServerSocket (Auswahl)<br />

public void b<strong>in</strong>d(SocketAddress adr) B<strong>in</strong>den des Sockets an die lokale Socket-Adresse adr<br />

throws IOException (bei der Adresse muss es sich um e<strong>in</strong>e INET-Adr. handeln)<br />

public Socket accept() Warten auf Verb<strong>in</strong>dungswünsche von Clients. Bei Akzep-<br />

throws IOException tieren Erzeugung e<strong>in</strong>es "Kommunikations-Sockets"<br />

public void close() throws IOException Schliessen des Sockets<br />

Memberfunktionen zum Ermitteln der lokalen Adresse, sowohl als INET-Adresse (SocketAddress-Objekt) als<br />

auch getrennt für IP-Adresse und Port-Nr), s. API-Dokumentation


FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />

FG TECHNISCHE INFORMATIK V – JV – 817 – 00 – TH – 01<br />

-----------------------------------------------------------------------------------<br />

• Pr<strong>in</strong>zipielles Realisierungsgerüst des Servers<br />

Kommunikation über INET-Stream-Sockets <strong>in</strong> <strong>Java</strong><br />

1. Erzeugung e<strong>in</strong>es ServerSocket-Objekts ServerSocket srvsk = new ServerSocket(port);<br />

B<strong>in</strong>den des Sockets an e<strong>in</strong> Port<br />

2. Warten auf Verb<strong>in</strong>dungswünsche durch Socket comsk = null;<br />

Clients mittels accept(), damit while ((comsk=srvsk.accept())!=null)<br />

Erzeugung e<strong>in</strong>es Socket-Objektes {<br />

(i.a. <strong>in</strong> e<strong>in</strong>er Schleife)<br />

3. Kommunikation mit dem Client über das<br />

Socket-Objekt<br />

▻ Ermittlung der vom Socket-Objekt InputStream is = comsk.getInputStream();<br />

bereitgestellten Stream-Objekte OutputStream os = comsk.getOutputStream();<br />

▻ Erzeugung der für die Kommunikation // zum Beispiel :<br />

tatsächlich e<strong>in</strong>zusetzenden Stream-Objekte DataInputStream dis =new DataInputStream(is);<br />

(Objekte von Stream-Filter-Klassen) DataOutputStream dos=new DataOutputStream(os);<br />

▻ Kommunikation mittels // zum Beispiel :<br />

Lese- und Schreiboperationen str = dis.readUTF();<br />

über die Stream-Objekte dos.writeUTF(str);<br />

▻ nach Beendigung der Kommunikation dis.close();<br />

Schliessen der Stream-Objekte; dos.close();<br />

4. Schliessen des Socket-Objektes comsk.close();<br />

}<br />

• Pr<strong>in</strong>zipielles Realisierungsgerüst des Clients<br />

1. Erzeugung e<strong>in</strong>es Socket-Objektes Socket sock = new Socket(name, port);<br />

Festlegung des Servers (Name oder IP-Adresse)<br />

und des Ports � Verb<strong>in</strong>dungswunsch an Server<br />

2. Kommunikation mit dem Server über das<br />

Socket-Objekt<br />

▻ Ermittlung der vom Socket-Objekt OutputStream os = sock.getOutputStream();<br />

bereitgestellten Stream-Objekte InputStream is = sock.getInputStream();<br />

▻ Erzeugung der für die Kommunikation // zum Beispiel :<br />

tatsächlich e<strong>in</strong>zusetzenden Stream-Objekte DataOutputStream dos=new DataOutputStream(os);<br />

(Objekte von Stream-Filter-Klassen) DataInputStream dis =new DataInputStream(is);<br />

▻ Kommunikation mittels // zum Beispiel :<br />

Schreib- und Leseoperationen dos.writeUTF(str);<br />

über die Stream-Objekte str = dis.readUTF();<br />

▻ nach Beendigung der Kommunikation dis.close();<br />

Schliessen der Stream-Objekte; dos.close();<br />

3. Schliessen des Socket-Objektes sock.close();


FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />

FG TECHNISCHE INFORMATIK V – JV – 818 – 01 – TH – 02<br />

------------------------------------------------------------------------------------<br />

Demonstrationsbeispiel zur Kommunikation über INET-Stream-Sockets <strong>in</strong> <strong>Java</strong> (1)<br />

• Zu lösende Aufgabe : Filterung von Text<br />

◇ Der zu filternde Text wird <strong>in</strong> e<strong>in</strong>em Client-Programm zeilenweise von der Standard-E<strong>in</strong>gabe e<strong>in</strong>gelesen<br />

und über e<strong>in</strong>e INET-Stream-Socket-Verb<strong>in</strong>dung zu e<strong>in</strong>em Server-Programm gesendet.<br />

Der Name des Server-Rechners und die Port-Nr des Server-Programms können durch Kommandozeilen-Parameter<br />

festgelegt werden. Falls das nicht erfolgt : Verwendung von Defaults.<br />

◇ Das Server-Programm filtert die erhaltenen Zeilen-Str<strong>in</strong>gs mittels e<strong>in</strong>es Filter-Objektes und sendet anschliessend<br />

die gefilterten Str<strong>in</strong>gs über die INET-Stream-Socket-Verb<strong>in</strong>dung zum Client zurück.<br />

Die Port-Nr des Server-Programms kann durch e<strong>in</strong>en Kommandozeilen-Parameter festgelegt werden.<br />

Falls das nicht erfolgt, wird e<strong>in</strong>e Default-Port-Nr verwendet.<br />

◇ Das Client-Programm gibt die erhaltenen gefilterten Zeilen-Str<strong>in</strong>gs <strong>in</strong> die Standard-Ausgabe aus.<br />

◇ Die Art der Filterung wird durch die Klasse des vom Server-Programm e<strong>in</strong>gesetzten Filter-Objekts festgelegt.<br />

Diese muss das Interface TextFilter implementieren.<br />

Hier : Klasse UpcaseFilter (Umwandlung aller Buchstaben <strong>in</strong> Gross-Buchstaben)<br />

• Quelldatei mit Def<strong>in</strong>ition e<strong>in</strong>es Interfaces für Text-Filter (TextFilter.java)<br />

// TextFilter.java<br />

// Def<strong>in</strong>ition e<strong>in</strong>es Interfaces fuer Klassen zur TextFilterung<br />

public <strong>in</strong>terface TextFilter<br />

{<br />

public Str<strong>in</strong>g filterStr<strong>in</strong>g(Str<strong>in</strong>g str);<br />

}<br />

• Beispiel e<strong>in</strong>er Text-Filter-Klasse : Quelldatei UpcaseFilter.java<br />

// UpcaseFilter.java<br />

// Klasse zur Filterung von Str<strong>in</strong>gs : Umwandlung aller Buchstaben <strong>in</strong> Gross-Buchstaben<br />

// Implementierung des Interfaces TextFilter<br />

public class UpcaseFilter implements TextFilter<br />

{<br />

public Str<strong>in</strong>g filterStr<strong>in</strong>g(Str<strong>in</strong>g str)<br />

{<br />

return str.toUpperCase();<br />

}<br />

}


FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />

FG TECHNISCHE INFORMATIK V – JV – 818 – 02 – TH – 02<br />

------------------------------------------------------------------------------------<br />

Demonstrationsbeispiel zur Kommunikation über INET-Stream-Sockets <strong>in</strong> <strong>Java</strong> (2)<br />

• Quelldatei mit Klasse für Serverprogramm (FilterServer.java)<br />

// FilterServer.java<br />

// Start-und Steuer-Klasse e<strong>in</strong>es Servers zum Filtern von Str<strong>in</strong>gs<br />

import java.net.*;<br />

import java.io.*;<br />

public class FilterServer<br />

{<br />

static f<strong>in</strong>al <strong>in</strong>t DEF_PORT = 60290;<br />

}<br />

public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args) throws IOException<br />

{<br />

<strong>in</strong>t port = DEF_PORT;<br />

if (args.length>0)<br />

port=Integer.parseInt(args[0]);<br />

Pr<strong>in</strong>tStream stdout = System.out;<br />

ServerSocket servsock = new ServerSocket(port);<br />

stdout.pr<strong>in</strong>tln("FilterServer");<br />

stdout.pr<strong>in</strong>tln("Lokale Adresse : " + servsock.getInetAddress());<br />

stdout.pr<strong>in</strong>tln("Lokales Port : " + servsock.getLocalPort() + '\n');<br />

Socket comsock = null;<br />

TextFilter fil = new UpcaseFilter();<br />

while ((comsock=servsock.accept())!=null)<br />

{ stdout.pr<strong>in</strong>t("Verb<strong>in</strong>dung zu : ");<br />

stdout.pr<strong>in</strong>t(comsock.getInetAddress());<br />

stdout.pr<strong>in</strong>tln(" (Port : " + comsock.getPort() +")");<br />

DataInputStream <strong>in</strong> = new DataInputStream(comsock.getInputStream());<br />

DataOutputStream out = new DataOutputStream(comsock.getOutputStream());<br />

Str<strong>in</strong>g l<strong>in</strong>e = null;<br />

boolean goon = true;<br />

while (goon)<br />

{ try<br />

{ l<strong>in</strong>e = <strong>in</strong>.readUTF();<br />

l<strong>in</strong>e = fil.filterStr<strong>in</strong>g(l<strong>in</strong>e);<br />

out.writeUTF(l<strong>in</strong>e);<br />

}<br />

catch (EOFException ex)<br />

{ stdout.pr<strong>in</strong>tln("Verb<strong>in</strong>dung geschlossen");<br />

goon = false;<br />

}<br />

catch (IOException ex)<br />

{ stdout.pr<strong>in</strong>tln(ex.getMessage());<br />

goon = false;<br />

}<br />

}<br />

<strong>in</strong>.close();<br />

out.close();<br />

comsock.close();<br />

}<br />

servsock.close();<br />

}


FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />

FG TECHNISCHE INFORMATIK V – JV – 818 – 03 – TH – 02<br />

------------------------------------------------------------------------------------<br />

Demonstrationsbeispiel zur Kommunikation über INET-Stream-Sockets <strong>in</strong> <strong>Java</strong> (3)<br />

• Quelldatei mit Klasse für Clientprogramm (FilterClient.java)<br />

// FilterClient.java<br />

// Filterung von Str<strong>in</strong>gs, die ueber die Standarde<strong>in</strong>gabe e<strong>in</strong>gegeben werden<br />

// Demonstrationsbeispiel zur Socket-Kommunikation<br />

import java.io.*;<br />

import java.net.*;<br />

public class FilterClient<br />

{<br />

static f<strong>in</strong>al Str<strong>in</strong>g DEF_HOST = "localhost";<br />

static f<strong>in</strong>al <strong>in</strong>t DEF_PORT = 60290;<br />

}<br />

public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args) throws IOException<br />

{<br />

Str<strong>in</strong>g host = DEF_HOST;<br />

<strong>in</strong>t port = DEF_PORT;<br />

switch(args.length)<br />

{ case 2 : port = Integer.parseInt(args[1]);<br />

case 1 : host = args[0];<br />

break;<br />

}<br />

Pr<strong>in</strong>tStream stdout = System.out;<br />

BufferedReader std<strong>in</strong> = new BufferedReader(new InputStreamReader(System.<strong>in</strong>));<br />

Socket sock = new Socket(host, port);<br />

DataInputStream <strong>in</strong> = new DataInputStream(sock.getInputStream());<br />

DataOutputStream out = new DataOutputStream(sock.getOutputStream());<br />

Str<strong>in</strong>g l<strong>in</strong>e;<br />

stdout.pr<strong>in</strong>t("E<strong>in</strong>gabe ? ");<br />

while ((l<strong>in</strong>e=std<strong>in</strong>.readL<strong>in</strong>e())!=null)<br />

{ out.writeUTF(l<strong>in</strong>e);<br />

l<strong>in</strong>e=<strong>in</strong>.readUTF();<br />

stdout.pr<strong>in</strong>tln("Ausgabe : " + l<strong>in</strong>e);<br />

stdout.pr<strong>in</strong>t("E<strong>in</strong>gabe ? ");<br />

}<br />

<strong>in</strong>.close();<br />

out.close();<br />

sock.close();<br />

}


FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />

FG TECHNISCHE INFORMATIK V – JV – 821 – 00 – TH – 01<br />

-----------------------------------------------------------------------------------<br />

• Konzept von RMI<br />

Remote Method Invocation (RMI) von <strong>Java</strong> - Allgeme<strong>in</strong>es<br />

◇ E<strong>in</strong> objektorientiertes System besteht aus e<strong>in</strong>er Ansammlung von Objekten, die mite<strong>in</strong>ander <strong>in</strong> Kommunikations-<br />

beziehungen stehen.<br />

Jede Kommunikationsbeziehung zwischen Objekten kann als Client-Server-Beziehung aufgefasst werden :<br />

E<strong>in</strong> Server-Objekt stellt Dienstleistungen zur Verfügung, die von Client-Objekten durch den Aufruf von Methoden<br />

des Server-Objekts (= Senden von Botschaften an das Server-Objekt) genutzt werden können<br />

◇ Remote Method Invocation (RMI) realisiert e<strong>in</strong>e Übertragung des Konzepts des Prozedur-Fernaufrufs (Remote<br />

Procedure Call, RPC) auf e<strong>in</strong>e objektorientierte Umgebung.<br />

◇ RMI erlaubt den Aufruf von Methoden für Objekte, die sich <strong>in</strong> anderen virtuellen Masch<strong>in</strong>en bef<strong>in</strong>den, e<strong>in</strong>schliesslich<br />

solcher virtueller Masch<strong>in</strong>en, die auf anderen Rechnern laufen.<br />

� Kommunikation zwischen Objekten über Rechnergrenzen h<strong>in</strong>weg � verteilte Objekte<br />

◇ RMI ist die <strong>Java</strong>-spezifische Implementierung e<strong>in</strong>es Systems für verteilte Objekte<br />

"Natürliche" Integration des verteilten Objekt-Modells <strong>in</strong> die Sprache <strong>Java</strong> unter Ausnutzung ihrer Konzepte und<br />

Beibehaltung ihrer Objekt-Semantik<br />

� E<strong>in</strong> entfernter Methodenaufruf sieht wie e<strong>in</strong> normaler lokaler Methodenaufruf aus<br />

(transparenter entfernter Methodenaufruf)<br />

◇ Bestandteil des <strong>Java</strong>-API (ab JDK 1.1, modifiziert und erweitert <strong>in</strong> JDK 1.2)<br />

• Weitere wesentliche Eigenschaften von RMI<br />

◇ Anwendungen stehen zwei Mechanismen zur Erlangung von Referenzen auf entfernte Objekte zur Verfügung :<br />

▻ Nachfragen bei e<strong>in</strong>em RMI-eigenen Namensdienst (rmiregistry)<br />

▻ Übergabe als Parameter und/oder Rückgabewerte von entfernten Funktionsaufrufen<br />

◇ Die eigentliche Kommunikation zwischen verteilten Objekten wird vom RMI-Laufzeitsystem unter E<strong>in</strong>satz von<br />

Sockets durchgeführt. E<strong>in</strong>zelheiten bleiben der eigentlichen Anwendung (und ihrem Programmierer) aber verborgen.<br />

◇ RMI ermöglicht die Übergabe von Objekten als Parameter und Rückgabewerte<br />

Das RMI-Laufzeitsystem stellt die notwendigen Mechanismen zur Übertragung von Objekt-Daten und -Code zur<br />

Verfügung (� Kopieren von Objekten)<br />

Diese beruhen auf<br />

▻ dem <strong>Java</strong>-Konzept der Objekt-Serialisierung (object serialization)<br />

▻ sowie der <strong>Java</strong>-Eigenschaft des dynamischen Ladens von Code (dynamic code download<strong>in</strong>g)<br />

� Erzeugung von Objekten, deren Klassen-Implementierung (<strong>Java</strong>-Byte-Code) lokal nicht verfügbar ist<br />

◇ Das dynamische Laden von Code ermöglicht die dynamische Änderung des Verhaltens von Server und/oder Client<br />

◇ Unterstützung von Callbacks vom Server zum Client<br />

Übergabe von Referenzen auf – im Client vorhandene – entfernte Objekte als Parameter im entfernten Methodenaufruf.<br />

◇ Verteilte Garbage Collection<br />

E<strong>in</strong>beziehung von entfernten Objekten <strong>in</strong> den Garbage Collection Mechanismus von <strong>Java</strong><br />

RMI stellt sicher, daß dann und nur dann entfernte Objekte (remote objects) vernichtet werden, wenn weder e<strong>in</strong>e lokale<br />

noch e<strong>in</strong>e entfernte Referenz auf das jeweilige Objekt existiert.<br />

◇ E<strong>in</strong>bettung <strong>in</strong> die Sicherheitsmechanismen der <strong>Java</strong>-Plattform<br />

Verwendung von Security-Manager, Class Loader und Policy Files zur Überprüfung der Zulässigkeit des Ladens<br />

von entferntem Code und des Ausführens von Code (Resourcenzugriff)<br />

◇ Flexibilität und Erweiterbarkeit, z.B.<br />

▻ Implementierung unterschiedlicher Referenz-Semantiken für entfernte (Server-) Objekte<br />

(z.Zt im Standard-API implementiert : UnicastRemoteObject und Activatable )<br />

▻ E<strong>in</strong>satz unterschiedlicher Socket-Typen <strong>in</strong> der Transportschicht von RMI (Ersatz des standardmäßig verwendeten<br />

Socket-Typs (TCP-Protokoll) durch SSL-Sockets oder selbstdef<strong>in</strong>ierte Socket-Typen)


FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />

FG TECHNISCHE INFORMATIK V – JV – 822 – 01 – TH – 02<br />

-----------------------------------------------------------------------------------<br />

• RMI –Architektur<br />

Remote Method Invocation (RMI) von <strong>Java</strong> – Funktionsweise (1)<br />

◇ Das RMI-System besteht aus drei Schichten :<br />

▻ Stub-/Skeleton-Schicht<br />

▻ RMI-Referenz-Schicht<br />

▻ RMI-Transport-Schicht<br />

Client-Objekt<br />

Stub<br />

RMI-Referenz-Schicht<br />

RMI-Tranport-Schicht<br />

Server-Objekt<br />

Skeleton<br />

RMI-Referenz-Schicht<br />

RMI-Tranport-Schicht<br />

RMI-<br />

Laufzeit-<br />

System<br />

◇ Die Stub-/Skeleton-Schicht bildet die Schnittstelle zwischen den Bestandteilen der verteilten Applikation<br />

(Client-Objekt und Server-Objekt) und dem restlichen RMI-System (RMI-Laufzeitsystem).<br />

Der Stub ist e<strong>in</strong> Stellvertreter-Objekt (Proxy) des Server-Objekts auf der Clientseite, der die gleiche Methoden-<br />

Aufruf-Schnittstelle wie das Server-Objekt anbietet.<br />

Er nimmt die RMI-Aufrufe des Clients entgegen, wandelt die Methoden-Aufruf-Parameter mittels Objekt-Serialisierung<br />

<strong>in</strong> serielle Byte-Streams um (marshall<strong>in</strong>g) und leitet diese zusammen mit den für den Aufruf der Serverfunktion<br />

benötigten Informationen (Identifikation des Ziel-Objekts und der aufzurufenden Methode) an die RMI-Referenzschicht<br />

weiter<br />

Umgekehrt erhält er von der RMI-Referenzschicht die Rückgabewerte e<strong>in</strong>es RMI-Aufrufs als Byte-Streams, deseriali-<br />

siert diese (ummarshall<strong>in</strong>g) und reicht sie an das aufrufende Client-Objekt weiter.<br />

Das Skeleton nimmt auf der Serverseite die RMI-Aufrufe von der RMI-Referenzschicht entgegen, deserialisiert die<br />

als Byte-Streams erhaltenen Parameter und ruft mit diesen die eigentlich auszuführende im Server-Objekt implementierte<br />

Methode auf. Nach Bendigung dieser Funktion nimmt es deren Rückgabewerte entgegen und leitet sie nach<br />

Serialisierung an die RMI-Referenzschicht weiter.<br />

In früheren <strong>Java</strong>-Versionen wurde hierfür e<strong>in</strong> eigenes Skeleton-Objekt e<strong>in</strong>gesetzt.<br />

In neueren Versionen wird die Funktionalität des Skeletons durch e<strong>in</strong>en allgeme<strong>in</strong>en Verteiler des RMI-Laufzeit-<br />

systems ersetzt. Es muss daher ke<strong>in</strong> eigenes Skeleton-Objekt mehr erzeugt werden.<br />

Der Stub muss dagegen an das jeweilige Server-Objekt angepaßt se<strong>in</strong>.<br />

Se<strong>in</strong>e Klasse wird aus der Server-Objekt-Klasse mittels e<strong>in</strong>es RMI-Compilers (rmic) generiert.<br />

(Der RMI-Compiler war früher auch zuständig für die Erzeugung der Skeleton-Klasse)<br />

Ab dem JDK 5.0 kann das Stub-Objekt dynamisch zur Laufzeit erzeugt werden. � Aufruf von rmic nicht<br />

erforderlich wenn auch der Client-Code mit dem JDK 5.0 erzeugt wurde.<br />

◇ Die RMI-Referenz-Schicht ist für die Lokalisierung des jeweiligen Kommunikationspartners (Server bzw Client)<br />

zuständig. Sie be<strong>in</strong>haltet den RMI-Namensdienst (Registry) und verwaltet die Referenzen auf entfernte Objekte.<br />

Unter Berücksichtigung der jeweiligen Referenz-Semantik gibt sie die vom Stub erhaltenen RMI-Aufrufe e<strong>in</strong>schließ-<br />

lich deren Parameter (Byte-Streams) an die RMI-Transportschicht weiter.<br />

Auf der Serverseite nimmt sie die RMI-Aufrufe und deren Parameter von der RMI-Transportschicht entgegen, aktiviert<br />

gegebenenfalls das Server-Objekt und leitet die Aufrufe an das Skeleton weiter.<br />

Analog ist sie an der Übermittlung der Rückgabewerte beteiligt.<br />

◇ In der RMI-Transport-Schicht werden die Kommunikationsverb<strong>in</strong>dungen verwaltet und die eigentliche Kommu-<br />

nikation zwischen verschiedenen Adressräumen (JVMs) abgewickelt.<br />

Üblicherweise werden hierfür Sockets e<strong>in</strong>gesetzt.


FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />

FG TECHNISCHE INFORMATIK V – JV – 822 – 02 – TH – 01<br />

-----------------------------------------------------------------------------------<br />

Remote Method Invocation (RMI) von <strong>Java</strong> – Funktionsweise (2)<br />

• Übertragung von Parametern und Rückgabewerten<br />

◇ Die Parameter und Rückgabewerte von RMI-Aufrufen werden mittels Objekt-Serialisierung als Byte-Streams<br />

übertragen.<br />

�Übertragbare Objekte müssen serialisierbar se<strong>in</strong>, d.h. das Interface java.io.Serializable implementieren.<br />

◇ e<strong>in</strong>fache Datentypen : Übertragung der Werte (Call by Value)<br />

◇ lokale Objekte (non-remote objects) : Übertragung e<strong>in</strong>er Kopie des Objekts (Call by Copy)<br />

Für Rückgabewerte wird beim Aufrufer e<strong>in</strong> neues Objekt erzeugt<br />

◇ entfernte Objekte (remote objects) : Übertragung e<strong>in</strong>er Referenz auf das Objekt (Call by Reference)<br />

Die Referenz ist das zum Objekt gehörende Stub-Objekt. (das se<strong>in</strong>erseits per Kopie übertragen wird)<br />

◇ In dem im Byte-Stream für e<strong>in</strong> übertragenes Objekt enthaltenen Klassen-Deskriptor ist auch die URL über die der<br />

Klassen-Code (<strong>Java</strong> Byte Code) zugänglich ist, vermerkt.<br />

Dies ermöglicht es dem empfangenden System, den Klassen-Code dynamisch zu laden, falls er nicht lokal verfügbar<br />

ist. (Dynamic Code Download<strong>in</strong>g).<br />

E<strong>in</strong>e derartige Situation kann auftreten, wenn das übertragene Objekt e<strong>in</strong>e Instanz e<strong>in</strong>es Untertyps des deklarierten<br />

Parametertyps ist. E<strong>in</strong> Untertyp <strong>in</strong> diesem S<strong>in</strong>n ist entweder e<strong>in</strong>e Klasse, die e<strong>in</strong> Interface, das als Parametertyp dekla-<br />

riert ist, implementiert oder e<strong>in</strong>e von der Parameterklasse abgeleitete Klasse.<br />

• RMI-Registry<br />

◇ Die RMI-Registry ist e<strong>in</strong> e<strong>in</strong>facher Namensdienst, der es Clients ermöglicht, entfernte Objekte über ihren Namen zu<br />

lokalisieren.<br />

◇ E<strong>in</strong>e RMI-Registry muß lokal auf dem System, das Objekte für RMI-Aufrufe (entfernte Objekte) bereitstellt (RMI-<br />

Server) existieren.<br />

◇ Üblicherweise wird die RMI-Registry <strong>in</strong> e<strong>in</strong>er eigenen JVM als H<strong>in</strong>tergrundprozeß gestartet.<br />

Defaultmäßig "horcht" sie auf Port 1099.<br />

Sie kann aber auch mit e<strong>in</strong>er anderen Port-Nummer gestartet werden.<br />

Kommando : [start] rmiregistry [port] (W<strong>in</strong>dows)<br />

rmiregistry [port] & (L<strong>in</strong>ux)<br />

◇ E<strong>in</strong> entferntes Objekt, das über die Registry zugänglich se<strong>in</strong> soll, muß vom Server-Prozeß der Registry bekannt<br />

gemacht (registriert, "gebunden") werden.<br />

◇ E<strong>in</strong> Client, der e<strong>in</strong>en RMI-Aufruf ausführen möchte, benötigt e<strong>in</strong>e Referenz auf das entsprechende (entfernte) Server-<br />

Objekt. Diese erhält er durch e<strong>in</strong>e Nachfrage ("lookup") bei der RMI-Registry des Server-Rechners.<br />

Falls für das – über e<strong>in</strong>en Namen referierte – Objekt e<strong>in</strong> E<strong>in</strong>trag vorhanden ist, liefert die Registry se<strong>in</strong> als Referenz<br />

dienendes Stub-Objekt zurück.<br />

◇ Typischerweise wird die RMI-Registry nur zur Lokalisierung des ersten vom Client referierten entfernten Objekts<br />

verwendet.<br />

Weitere gegebenenfalls benötigte entfernte Objekte können dann über dieses Objekt ermittelt werden (als Parameter<br />

bzw Rückgabewerte von RMI-Aufrufen)<br />

◇ Die Kommunikation mit der RMI-Registry erfolgt üblicherweise über das von der <strong>Java</strong>-Klasse java.rmi.Nam<strong>in</strong>g<br />

bereitgestellte Interface (statische Methoden)<br />

◇ Tatsächlich stellt die RMI-Registry bereits selbst e<strong>in</strong> besonderes entferntes Objekt dar, zu dem auch mittels RMI, das<br />

durch die Nam<strong>in</strong>g-Funktionen gekapselt wird, zugegriffen wird.<br />

Client-Objekt<br />

2 : Nachfrage<br />

3 : RMI-Aufruf<br />

RMI-Registry<br />

1:Registrierung<br />

Server-Objekt


FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />

FG TECHNISCHE INFORMATIK V – JV – 822 – 03 – TH – 02<br />

-----------------------------------------------------------------------------------<br />

Remote Method Invocation (RMI) von <strong>Java</strong> – Funktionsweise (3)<br />

• Dynamisches Laden von Code (Dynamic Code Download<strong>in</strong>g)<br />

◇ E<strong>in</strong>e hervorstechende Eigenschaft von <strong>Java</strong> ist die Fähigkeit, dynamisch Code von jeder URL <strong>in</strong> e<strong>in</strong>e laufende<br />

<strong>Java</strong> Virtual Mach<strong>in</strong>e (JVM) zu laden. I.a. wird die URL auf e<strong>in</strong> anderes physikalisches System verweisen.<br />

� E<strong>in</strong>e JVM kann Code ausführen, der nie auf ihrem eigenen System <strong>in</strong>stalliert worden ist.<br />

◇ Diese Fähigkeit wird auch vom RMI-System genutzt :<br />

▻ Zum Laden des Codes für den Stub des Server-Objekts durch den Client (ab dem JDK 5.0 nicht mehr erforderlich).<br />

� Die Stub-Klasse muß nicht lokal zur Verfügung stehen<br />

(ab dem JDK 5.0 wird sie lokal beim Client aus dem RMI-Interface erzeugt)<br />

▻ Zum Laden des Codes für als Parameter <strong>in</strong> oder Rückgabewerte von RMI-Aufrufen übergebene Objekte<br />

(sowohl lokale Objekte als auch entfernte Objekte)<br />

◇ Das dynamische Laden von Code erfordert das Setzen der Property java.rmi.server.codebase <strong>in</strong> der JVM<br />

des das Objekt bzw die Klasse zur Verfügung stellenden Prozesses :<br />

- bei Stubs von Server-Objekten : <strong>in</strong> der JVM des RMI-Server-Prozesses, der e<strong>in</strong> entferntes Objekt registriert<br />

(ab dem JDK 5.0 nicht mehr notwendig)<br />

- bei als Parameter übergebenen Objekten : <strong>in</strong> der JVM des RMI-Client-Prozesses<br />

- bei Objekten, die von RMI-Aufrufen zurückgegeben werden : <strong>in</strong> der JVM des Server-Prozesses<br />

Als Wert der codebase-Property ist die URL, von der der Klassen-Code geladen werden kann, anzugeben.<br />

Diese URL kann sich auf e<strong>in</strong> drittes System beziehen.<br />

◇ Wenn der Server-Prozeß e<strong>in</strong> entferntes Objekt unter e<strong>in</strong>em Namen bei der RMI-Registry registriert, wird der <strong>in</strong> der<br />

Server-JVM gesetzte codebase-Wert (URL !) zusammen mit der Objekt-Referenz (Stub-Objekt) gespeichert.<br />

Voraussetzung : Der Code der Stub-Klasse darf nicht über die CLASSPATH-Environment-Variable der JVM der<br />

RMI-Registry erreichbar se<strong>in</strong>. (gilt nicht ab dem JDK 5.0, da muss die .class-Datei des RMI-Interfaces über die<br />

CLASSPATH-Environment-Variable der JVM der RMI-Registry erreichbar se<strong>in</strong>)<br />

◇ Der Client-Prozeß erhält auf se<strong>in</strong>e Nachfrage bei der RMI-Registry das Stub-Objekt als Referenz auf das Server-<br />

Objekt. Falls er den Stub-Klassen-Code nicht über se<strong>in</strong>e CLASSPATH-Environment-Variable lokal f<strong>in</strong>det, versucht<br />

er bis e<strong>in</strong>schliesslich dem JDK 1.4 den Code von der mit dem Stub-Objekt verbundenen URL (codebase-Wert) zu<br />

laden. (ab dem JDK 5.0 wird der Code lokal aus dem RMI-Interface erzeugt)<br />

Voraussetzung : Der RMI-Client-Prozeß hat e<strong>in</strong>en Security-Manager <strong>in</strong>stalliert, der das Laden des Stubs erlaubt<br />

(z.B. RMISecurityManager). In <strong>Java</strong> 2 (ab JDK 1.2) erfordert dies zusätzlich e<strong>in</strong> entsprechend konfiguriertes<br />

Security Policy File (Default : Datei .java.policy im Heimat-Verzeichnis des Users)<br />

Anmerkung : Der Security-Manager wird bereits für den Zugriff zur Registry benötigt.<br />

◇ Analog erfolgt das Laden von Klassen-Codes für Objekte, die dem Server-Objekt vom Client-Objekt als Parameter<br />

<strong>in</strong> RMI-Aufrufen übergeben werden (e<strong>in</strong>schliesslich das Laden aller weiteren von diesen benötigten Objekte).<br />

Das gilt auch für das JDK 5.0 !<br />

Voraussetzungen : Der codebase-Wert im Client-Prozeß ist auf die richtige URL gesetzt und das Server-Objekt<br />

kann den Code nicht lokal über se<strong>in</strong>e CLASSPATH-Environment-Variable f<strong>in</strong>den. Außerdem muß im Server e<strong>in</strong><br />

Security-Manager <strong>in</strong>stalliert se<strong>in</strong>.<br />

4. u. 5<br />

nicht bei<br />

JDK 5.0<br />

Client-Objekt<br />

5. Rückgabe des Klassen-<br />

Codes des Stub-Objekts<br />

4. Erfragen des<br />

Klassen-Codes<br />

für Stub-Objekt<br />

2. Namens-<br />

Nachfrage<br />

myHost<br />

codebase-URL<br />

(http)<br />

RMI-Registry<br />

3. Rückgabe e<strong>in</strong>es<br />

Stub-Objekts<br />

6. RMI-Aufruf<br />

1. Registrierung<br />

des entfernten<br />

Server-Objekts<br />

Server-Prozeß,<br />

der entferntes Objekt<br />

erzeugt<br />

Server-Objekt<br />

java.rmi.server.codebase<br />

=http://myHost/mydir/


FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />

FG TECHNISCHE INFORMATIK V – JV – 823 – 01 – TH – 02<br />

------------------------------------------------------------------------------------<br />

• RMI-Packages<br />

<strong>Java</strong>-RMI - Interfaces und Klassen (1)<br />

Das RMI-API von <strong>Java</strong> wird durch die folgenden Packages zur Verfügung gestellt :<br />

▻ java.rmi<br />

grundlegendes Package<br />

▻ java.rmi.activation<br />

Unterstützung für die RMI Object Activation<br />

▻ java.rmi.dgc<br />

Klassen und Interfaces für die RMI Distributed Garbage Collection<br />

▻ java.rmi.registry<br />

Klassen und Interfaces für die RMI-Registry<br />

▻ java.rmi.server<br />

Klassen und Interfaces zur Unterstützung der Server-Seite von RMI<br />

• Überblick über die wichtigsten Interfaces und Klassen des RMI-API<br />

Für Anwenderprogramme s<strong>in</strong>d vor allem die folgenden Interfaces und Klassen von Bedeutung :<br />

<strong>in</strong>terface<br />

Remote<br />

(java.rmi)<br />

class<br />

UnicastRemoteObject<br />

(java.rmi.server)<br />

class<br />

Nam<strong>in</strong>g<br />

(java.rmi)<br />

abstract class<br />

RemoteObject<br />

(java.rmi.server)<br />

abstract class<br />

RemoteServer<br />

(java.rmi.server)<br />

class<br />

Activatable<br />

(java.rmi.activation)<br />

class<br />

RMISecurityManager<br />

(java.rmi)<br />

class<br />

RemoteException<br />

(java.rmi)


FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />

FG TECHNISCHE INFORMATIK V – JV – 823 – 02 – TH – 03<br />

------------------------------------------------------------------------------------<br />

<strong>Java</strong>-RMI - Interfaces und Klassen (2)<br />

• Die wichtigsten Interfaces und Klassen des <strong>Java</strong>-RMI-API - Kurzbeschreibung<br />

◇ <strong>in</strong>terface Remote (Package : java.rmi)<br />

"Basis"-Interface für alle Interfaces, deren Methoden mittels RMI aufrufbar se<strong>in</strong> sollen.<br />

Alle Klassen, deren Objekte mittels RMI ansprechbar se<strong>in</strong> sollen, müssen direkt oder <strong>in</strong>direkt – über abgeleitete<br />

Interfaces – dieses Interface implementieren.<br />

Mittels RMI können nur die Methoden, die <strong>in</strong> e<strong>in</strong>em von Remote abgeleiteten Interface (� remote <strong>in</strong>terface) spezi-<br />

fiziert s<strong>in</strong>d, aufgerufen werden.<br />

◇ class RemoteObject (Package : java.rmi.Server)<br />

Abstrakte Klasse, die e<strong>in</strong>ige Methoden der Klasse java.lang.Object für entfernt nutzbare Objekte (remote<br />

objects) überschreibt und damit die entsprechenden Fähigkeiten für derartige Objekte implementiert.<br />

(spezielle Implementierungen der Methoden hashCode(), equals() und toStr<strong>in</strong>g())<br />

◇ class RemoteServer (Package : java.rmi.Server)<br />

Abstrakte Superklasse der Klassen für entfernt nutzbare Server-Objekte.<br />

Sie stellt e<strong>in</strong> geme<strong>in</strong>sames Framework zur Unterstützung unterschiedlichster Semantiken für entfernte Referenzen<br />

zur Verfügung, die durch die von ihr abgeleiteten Klassen implementiert werden<br />

Die zur Erzeugung und Exportierung von Objekten an das RMI-Laufzeitsystem benötigten Methoden (Konstruktoren<br />

und gegebenenfalls weitere Methoden) werden durch die von dieser Klasse abgeleiteten Klassen bereitgestellt.<br />

U.a. stellt diese Klasse auch e<strong>in</strong>e statische Methode zum Ermitteln des aufrufenden Client-Rechners zur Verfügung.<br />

◇ class UnicastRemoteObject (Package : java.rmi.Server)<br />

Von der Klasse RemoteServer abgeleitete Klasse für e<strong>in</strong>fache – nicht replizierbare – entfernte Objekte, deren<br />

Referenzen nur gültig s<strong>in</strong>d, solange die Objekte aktiv s<strong>in</strong>d.<br />

Sie stellt die Unterstützung für Punkt-zu-Punkt-Verb<strong>in</strong>dungen zu aktiven Objekten (bezüglich Aufrufe, Parameter,<br />

Rückgabewerte) unter Verwendung von TCP-Sockets bereit<br />

Durch Übergabe e<strong>in</strong>es <strong>in</strong>t-Parameters an den Konstruktor kann die Port-Nummer festgelegt werden.<br />

Wird ke<strong>in</strong> Parameter übergeben, wird vom System e<strong>in</strong> anonymes Port gewählt.<br />

Eigene Klassen, die diese Referenz-Semantik bereitstellen sollen, müssen – unter Implementierung e<strong>in</strong>es geeigneten<br />

remote <strong>in</strong>terfaces - von dieser Klasse abgeleitet werden.<br />

◇ class Activatable (Package : java.rmi.Activation)<br />

Von der Klasse RemoteServer abgeleitete Klasse für entfernte Objekte, deren Referenzen auch gültig s<strong>in</strong>d,<br />

wenn die Objekte <strong>in</strong>aktiv und persistent ausgelagert s<strong>in</strong>d Diese Objekte können bei Bedarf wieder aktiviert werden.<br />

Eigene Klassen, die diese Referenz-Semantik bereitstellen sollen, müssen – unter Implementierung e<strong>in</strong>es geeigneten<br />

remote <strong>in</strong>terfaces - von dieser Klasse abgeleitet werden.<br />

◇ class RemoteException (Package : java.rmi)<br />

Superklasse der kommunikationsorientierten Exceptions, die bei RMI auftreten können.<br />

Alle Methoden e<strong>in</strong>es remote <strong>in</strong>terfaces müssen diese Exception weiterreichen können, d.h. <strong>in</strong> ihrem Funktionskopf<br />

muß e<strong>in</strong>e entsprechende Exception-Spezifikation (throws-Klausel) enthalten se<strong>in</strong>.<br />

◇ class Nam<strong>in</strong>g (Package : java.rmi)<br />

Nicht ableitbare Klasse (f<strong>in</strong>al), die statische Methoden zum Zugriff zur RMI-Registry bereitstellt<br />

◇ class RMISecurityManager (Package : java.rmi)<br />

Beispiel e<strong>in</strong>es von RMI-Anwendungen für das dynamische Laden von Code benötigten Security-Managers.<br />

Der RMI Class Loader kann ohne <strong>in</strong>stallierten Security-Manager ke<strong>in</strong>en Code von URLs, die auf e<strong>in</strong>en entfernten<br />

Rechner verweisen, laden.


FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />

FG TECHNISCHE INFORMATIK V – JV – 824 – 01 – TH – 02<br />

-----------------------------------------------------------------------------------<br />

• Auszuführende Schritte<br />

Erzeugung e<strong>in</strong>er RMI-Anwendung (1)<br />

▶ Def<strong>in</strong>ition e<strong>in</strong>es Interfaces für die RMI-Aufrufe (remote <strong>in</strong>terface)<br />

▶ Erstellung e<strong>in</strong>es Servers (Implementierung des Interfaces und der Server-Start-Funktionalität)<br />

▶ Entwicklung e<strong>in</strong>es Clients, der unter Nutzung dieses Interfaces RMI-Aufrufe ausführt<br />

▶ Erzeugung der Stub-Klasse (ab dem JDK 5.0 nicht mehr erforderlich)<br />

▶ Starten der RMI-Registry auf dem Server-Rechner<br />

▶ Start des Servers und des Clients<br />

• Def<strong>in</strong>ition e<strong>in</strong>es Interfaces für die RMI-Aufrufe (remote <strong>in</strong>terface)<br />

◇ Alle Methoden des Server-Objekts, die über RMI aufrufbar se<strong>in</strong> sollen, s<strong>in</strong>d <strong>in</strong> e<strong>in</strong>em Interface zu deklarieren<br />

(RMI-Methoden)<br />

◇ Eigenschaften dieses RMI-Interfaces :<br />

► Das Interface muß public deklariert werden<br />

► Das Interface muß von dem Interface java.rmi.Remote abgeleitet se<strong>in</strong> (� remote <strong>in</strong>terface).<br />

► Jede Methode des Interfaces muß die Exception java.rmi.RemoteException als werfbar deklarieren<br />

(Exception-Deklaration : throws java.rmi.RemoteException)<br />

◇ Die Klasse der RMI-Server-Objekte muß dieses Interface implementieren (RMI-Server-Klasse).<br />

Nur die Methoden der Server-Objekte, die <strong>in</strong> diesem Interface enthalten s<strong>in</strong>d, s<strong>in</strong>d auch entfernt aufrufbar.<br />

Alle weiteren eventuell vorhandenen Methoden s<strong>in</strong>d nur lokal ansprechbar.<br />

◇ Der Client muß das Stub-Objekt, das er als lokale Referenz auf das entfernte Server-Objekt erhält, immer als e<strong>in</strong>e<br />

Instanz dieses Interfaces referieren .<br />

Der hierfür notwendige Type-Cast ist zulässig, da auch die Stub-Klasse dieses Interface implementiert.<br />

◇ Übersetzung der <strong>Java</strong>-Quell-Datei (z.B. MyServer.java)<br />

� Erzeugung e<strong>in</strong>er <strong>Java</strong>-Bytecode-Datei (MyServer.class)<br />

• Klassendiagramm für e<strong>in</strong>en e<strong>in</strong>fachen RMI-Server


FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />

FG TECHNISCHE INFORMATIK V – JV – 824 – 02 – TH – 01<br />

-----------------------------------------------------------------------------------<br />

• Erstellung e<strong>in</strong>es Servers<br />

◇ Zur Realisierung e<strong>in</strong>es RMI-Servers werden benötigt :<br />

Erzeugung e<strong>in</strong>er RMI-Anwendung (2)<br />

► E<strong>in</strong>e das RMI-Interface implementierende Klasse (RMI-Server-Klasse)<br />

► Die Server-Start-Funktionalität.<br />

Häufig wird die Server-Start-Funktionalität durch die ma<strong>in</strong>()-Methode der RMI-Server-Klasse realisiert.<br />

Diese ma<strong>in</strong>()-Methode kann aber auch <strong>in</strong> e<strong>in</strong>er anderen – speziell hierfür vorgesehenen - Klasse enthalten se<strong>in</strong>.<br />

◇ Die RMI-Server-Klasse muß<br />

► wenigstens e<strong>in</strong> RMI-Interface (remote <strong>in</strong>terface) implementieren<br />

► von e<strong>in</strong>er Unterklasse der Klasse java.rmi.server.RemoteServer abgeleitet se<strong>in</strong><br />

► e<strong>in</strong>en Konstruktor def<strong>in</strong>ieren, der die Exception java.rmi.RemoteException werfen kann<br />

► alle im implementierenden RMI-Interface enthaltenen Methoden def<strong>in</strong>ieren<br />

◇ Die Server-Start-Funktionalität be<strong>in</strong>haltet :<br />

▻ Erzeugung und Installation e<strong>in</strong>es Security Managers<br />

▻ Erzeugung e<strong>in</strong>es oder mehrerer RMI-Server-Objekte (Instanzen der RMI-Server-Klasse)<br />

▻ Registrierung wenigstens e<strong>in</strong>es dieser Objekte bei der RMI-Registry<br />

◇ Erzeugung und Installation e<strong>in</strong>es Security-Managers<br />

In jeder JVM, <strong>in</strong> der Code von anderen Quellen als den durch die CLASSPATH-Environmentvariable festgelegten<br />

geladen werden soll, muß e<strong>in</strong> Security-Manager <strong>in</strong>stalliert se<strong>in</strong>.<br />

Falls noch ke<strong>in</strong> Security-Manager <strong>in</strong>stalliert ist, muß der Server e<strong>in</strong>en <strong>in</strong>stallieren – entweder e<strong>in</strong>e Instanz der Klasse<br />

RMISecurityManager oder e<strong>in</strong>er selbstdef<strong>in</strong>ierten Security-Manager Klasse<br />

if (System.getSecurityManager()==null)<br />

{<br />

System.setSecurityManager(new RMISecurityManager());<br />

}<br />

◇ Registrierung e<strong>in</strong>es RMI-Server-Objektes bei der lokalen RMI-Registry<br />

Mittels der statischen Methode reb<strong>in</strong>d() der Klasse Nam<strong>in</strong>g :<br />

public static void reb<strong>in</strong>d(Str<strong>in</strong>g name, Remote obj) throws RemoteException,<br />

MalformedURLException<br />

Parameter : name - URL-formatierter Str<strong>in</strong>g, der das zu registrierende Objekt bezeichnet<br />

- Allgeme<strong>in</strong>e Form : "//host:port-nr/ObjectName".<br />

- Wenn die RMI-Registry auf dem Default-Port 1099 läuft, können die Angabe des Hosts<br />

(host) und der Port-Nr. (port-nr) weggelassen werden, es reicht die Angabe von<br />

"ObjectName".<br />

- "ObjectName" ist e<strong>in</strong> beliebiger Name unter dem das Objekt registriert werden soll.<br />

obj Name des Objekts unter dem es angelegt worden ist und im Programm referiert wird.<br />

Beispiel : Nam<strong>in</strong>g.reb<strong>in</strong>d("MyServer", serv);<br />

Die von der Methode werfbaren Exceptions müsssen gefangen werden.<br />

◇ Jeder Aufruf e<strong>in</strong>er RMI-Methode erfolgt <strong>in</strong> e<strong>in</strong>em eigenen Thread.<br />

� E<strong>in</strong> mittels RMI realisierter Server ist grundsätzlich e<strong>in</strong> Multithread-Server.<br />

◇ Innerhalb e<strong>in</strong>er RMI-Methode kann der Rechner des aufrufenden Clients mittels der von RemoteServer geerbten<br />

statischen Methode getClientHost() ermittelt werden :<br />

public static Str<strong>in</strong>g getClientHost() throws ServerNotActiveException<br />

Funktionswert : Str<strong>in</strong>g-Repräsentation des Client-Rechners


FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />

FG TECHNISCHE INFORMATIK V – JV – 824 – 03 – TH – 03<br />

------------------------------------------------------------------------------------<br />

• Entwicklung e<strong>in</strong>es Clients<br />

◇ Wesentliche Funktionalität des Clients :<br />

Erzeugung e<strong>in</strong>er RMI-Anwendung (3)<br />

► Erzeugung und Installation e<strong>in</strong>es Security-Managers<br />

► Erfragen e<strong>in</strong>er Referenz auf das entfernte RMI-Server-Objekt bei der RMI-Registry<br />

► Aufruf der RMI-Methoden über die erhaltene Referenz<br />

◇ Die Erzeugung und Installation e<strong>in</strong>es Security Managers erfolgt analog wie beim Server :<br />

if (System.getSecurityManager()==null)<br />

{<br />

System.setSecurityManager(new RMISecurityManager());<br />

}<br />

◇ Erfragen e<strong>in</strong>er Referenz auf das entfernte RMI-Server-Objekt bei der RMI-Registry<br />

Mittels der statischen Methode lookup() der Klasse Nam<strong>in</strong>g :<br />

public static Remote lookup(Str<strong>in</strong>g name) throws NotBoundException,<br />

MalformedURLException,<br />

RemoteException<br />

Parameter : name - URL-formatierter Str<strong>in</strong>g, der das zu suchende Objekt bezeichnet<br />

- Allgeme<strong>in</strong>e Form : "//host:port-nr/ObjectName".<br />

- Als Host (host) ist der Rechner (Name oder IP-Adresse) anzugeben, auf dem sich das<br />

gesuchte Objekt und die RMI-Registry bef<strong>in</strong>det.<br />

- Wenn die RMI-Registry auf dem Default-Port 1099 läuft, kann die Angabe der Port-Nr.<br />

(port-nr) weggelassen werden<br />

- "ObjectName" ist der Name des Objekts, unter dem es <strong>in</strong> der Registry registriert<br />

worden ist.<br />

Die Methode Nam<strong>in</strong>g.lookup() erzeugt unter Verwendung von Host und Port-Nr. e<strong>in</strong> Registry-Stub-Objekt,<br />

über das die Methode lookup() für die Registry mit "ObjectName" als Parameter aufgerufen wird.<br />

Diese gibt – sofern e<strong>in</strong> E<strong>in</strong>trag <strong>in</strong> der Registry vorhanden ist – e<strong>in</strong> Stub-Objekt für das gesuchte RMI-Server-Objekt<br />

zurück.<br />

Nam<strong>in</strong>g.lookup() gibt dieses Stub-Objekt als Referenz auf das RMI-Server-Objekt an den aufrufenden Client<br />

zurück (als Instanz des Interfaces Remote).<br />

Der Stub-Code wird – sofern er nicht lokal über die CLASSPATH-Environmentvariable gefunden wird – bis zum<br />

JDK 1.4 von der <strong>in</strong> der Registry für die Stub-Klasse abgelegten (und im Stub-Objekt angegebenen) Codebase geladen.<br />

Ab dem JDK 5.0 wird er lokal beim Client aus dem RMI-Interface erzeugt.<br />

Der Client wandelt den Typ des Stub-Objekts <strong>in</strong> den Typ des vom RMI-Server-Objekt implementierten RMI-Inter-<br />

faces um.<br />

◇ Der Client referiert das erhaltene Stub-Objekt als Instanz des vom RMI-Server-Objekt implementierten RMI-Inter-<br />

faces. Über diese Instanz erfolgt e<strong>in</strong> Aufruf der RMI-Methoden.


FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />

FG TECHNISCHE INFORMATIK V – JV – 824 – 04 – TH – 03<br />

------------------------------------------------------------------------------------<br />

Erzeugung e<strong>in</strong>er RMI-Anwendung (4)<br />

• Erzeugung der Stub- (und früher auch Skeleton-)Klassen<br />

◇ Ab dem (und für das) JDK 5.0 wird das Stub-Objekt dynamisch zur Laufzeit erzeugt<br />

� ke<strong>in</strong>e explizite Erzeugung der Stub-Klasse erforderlich (ke<strong>in</strong> Aufruf von rmic).<br />

◇ Für Vor-JDK-5.0-Anwendungen muss die Stub-Klasse (und gegebenenfalls auch die Skeleton-Klasse) explizit mittels<br />

des RMI-Compilers (Stub-Generators) rmic aus der das RMI-Interface implementierenden RMI-Server-Klasse und<br />

dem RMI-Interface erzeugt werden.<br />

◇ Dem RMI-Compiler ist der voll-qualifizierte Package-Name der als <strong>Java</strong>-Byte-Code vorliegenden RMI-Server-<br />

Klasse als Parameter zu übergeben.<br />

◇ Die den <strong>Java</strong>-Byte-Code der RMI-Server-Klasse enthaltende Datei (.class-file) sowie die Datei mit dem <strong>Java</strong>-Byte-<br />

Code (oder mit dem Quell-Code) des RMI-Interfaces müssen über die CLASSPATH-Environment-Variable erreich-<br />

bar se<strong>in</strong>.<br />

◇ Zusätzlich kann beim Aufruf von rmic mit der "-d" Option angegeben werden, <strong>in</strong> welchem Ausgangs-Direc-<br />

tory die erzeugten <strong>Java</strong>-Byte-Code-Dateien (.class-files) für Stub (und gegebenenfalls Skeleton) abgelegt werden<br />

sollen (Ausgehend von diesem Directory erfolgt die Ablage <strong>in</strong> e<strong>in</strong>er dem vollqualifizierten Package-Namen entspre-<br />

chenden Directory-Struktur). Ohne diese Angabe dient das aktuelle Directory als Ausgangs-Directory.<br />

◇ Die von rmic erzeugten Klassen-Dateien für Stub (und gegebenefalls Skeleton) tragen den um _Stub bzw _Skel<br />

ergänzten Hauptnamen der RMI-Server-Klassen-Datei<br />

◇ Beispiel : (ohne Verwendung e<strong>in</strong>es Package-Namens)<br />

rmic –d G:\My<strong>Java</strong>\classes\ MyServerImpl<br />

Hierdurch werden die Dateien MyServerImpl_Stub.class und MyServerImpl_Skel.class im<br />

Directory G:\My<strong>Java</strong>\classes erzeugt.<br />

• Starten der RMI-Registry<br />

◇ Üblicherweise wird die RMI-Registry als eigener Prozeß (<strong>in</strong> e<strong>in</strong>er eigenen JVM laufend) auf dem Server-Rechner von<br />

der Kommandozeile aus mit dem Kommando rmiregistry gestartet. Falls die Registry nicht auf dem Default-<br />

Port 1099 arbeiten soll, muß die Port-Nr. beim Aufruf als Parameter angegeben werden.<br />

Beispiel : rmiregistry (� Registry läuft auf Port-Nr. 1099)<br />

rmiregistry 1248 (� Registry läuft auf Port-Nr. 1248)<br />

◇ Alternativ kann die Registry auch lokal für den Server-Prozeß von diesem erzeugt und gestartet werden<br />

(Statische Methode createRegistry() der Klasse LocateRegistry)<br />

◇ Achtung : Bis zum JDK 1.4 gilt : Die .class-Datei der Stub-Klasse(n) darf für die JVM der RMI-Registry nicht<br />

über die CLASSPATH-Environment-Variable erreichbar se<strong>in</strong>. Beim Start des Servers muss die Codebase, <strong>in</strong> der<br />

sich die Stub-Klasse bef<strong>in</strong>det, angegeben werden.<br />

Alternative ab dem JDK 5.0 : Der RMI-Registry kann statt der Stubklasse auch die .class-Datei des RMI-Interfaces<br />

zur Verfügung gestellt werden – entweder über die Codebase oder durch Bereitstellung e<strong>in</strong>er direkten Zugriffs-<br />

möglichket ( .class-Datei des RMI-Interfaces bef<strong>in</strong>det sich im Startverzeichnis der Registry oder die CLASSPATH-<br />

Variable enthält das Directory der .class-Datei )<br />

• Start des Servers und des Clients<br />

◇ Auf dem Server- und dem Client-Rechner s<strong>in</strong>d jeweils e<strong>in</strong>e JVM mit der jeweiligen Start-Klasse zu starten.<br />

◇ Als Optionen können die Codebase (URL) und die zu verwendende Policy-Datei (Dateipfad) angegeben werden<br />

(Default für die Policy-Datei : .java.policy im Heimat-Verzeichnis des Users)<br />

◇ Beispiel (für Server, ke<strong>in</strong> Package-Name) :<br />

java –Djava.rmi.server.codebase=http://cd2/~thomas/classes/<br />

-Djava.security.policy=my.policy MyServerImpl


FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />

FG TECHNISCHE INFORMATIK V – JV – 825 – 01 – TH – 01<br />

-----------------------------------------------------------------------------------<br />

• Zu lösende Aufgabe : Filterung von Text<br />

E<strong>in</strong>faches Demonstrationsbeispiel zu RMI <strong>in</strong> <strong>Java</strong> (1)<br />

◇ Lösung der Aufgabe des Demonstrationsbeispiels zur INET-Socket-Kommunikation mittels RMI<br />

◇ Def<strong>in</strong>ition e<strong>in</strong>es Remote-Interfaces, das die Methode filterStr<strong>in</strong>g() deklariert (RMI-Methode).<br />

◇ Das Remote-Interface wird durch e<strong>in</strong>e RMI-Klasse implementiert.<br />

In e<strong>in</strong>em Server-Programm wird e<strong>in</strong> Objekt dieser Klasse <strong>in</strong>stanziiert (� Remote-Objekt)<br />

◇ Die RMI-Klasse implementiert <strong>in</strong> ihrer ma<strong>in</strong>()-Methode auch die Server Start-Funktionalität.<br />

◇ Der zu filternde Text wird <strong>in</strong> e<strong>in</strong>em Client-Programm zeilenweise von der Standard-E<strong>in</strong>gabe e<strong>in</strong>gelesen<br />

Zur Filterung ruft der Client die RMI-Methode filterStr<strong>in</strong>g() des Remote-Objekts im Server auf.<br />

Der Name des Server-Rechners kann beim Client-Start durch Kommandozeilen-Parameter festgelegt werden.<br />

Falls das nicht erfolgt : Verwendung von Defaults.<br />

◇ Die RMI-Methode des Remote-Objekts des Servers filtert die erhaltenen Zeilen-Str<strong>in</strong>gs mittels e<strong>in</strong>es Filter-Objektes<br />

und gibt die gefilterten Str<strong>in</strong>gs als Funktionswert der RMI-Methode an den Client zurück.<br />

Das Filter-Objekt wird dem Remote-Objekt bei der Erzeugung im Konstruktor zu übergeben.<br />

◇ Das Client-Programm gibt die erhaltenen gefilterten Zeilen-Str<strong>in</strong>gs <strong>in</strong> die Standard-Ausgabe aus.<br />

◇ Die Art der Filterung wird durch die Klasse des vom Server-Programm e<strong>in</strong>gesetzten Filter-Objekts festgelegt.<br />

Diese muss das Interface TextFilter implementieren. (s. Beispiel zur INET-Socket-Kommunikation)<br />

Hier : Klasse UpcaseFilter (Umwandlung aller Buchstaben <strong>in</strong> Gross-Buchstaben)<br />

◇ Die RMI-Registry wird auf dem Default-Port 1099 gestartet.<br />

Das Remote-Objekt wird unter dem Namen "TextFilter" <strong>in</strong> der RMI-Registry registriert<br />

• Quelldatei mit der Def<strong>in</strong>ition des Remote-Interfaces (RMITextFilter.java)<br />

// RMITextFilter.java<br />

// Def<strong>in</strong>ition e<strong>in</strong>es Remote-Interfaces fuer Klassen zur TextFilterung<br />

import java.rmi.*;<br />

public <strong>in</strong>terface RMITextFilter extends Remote<br />

{<br />

public Str<strong>in</strong>g filterStr<strong>in</strong>g(Str<strong>in</strong>g str) throws RemoteException;<br />

}<br />

• Quelldatei mit Def<strong>in</strong>ition e<strong>in</strong>es Interfaces für Text-Filter (TextFilter.java)<br />

(gleiches Interfaces wie im Beispiel zur INET-Socket-Kommunikation)<br />

// TextFilter.java<br />

// Def<strong>in</strong>ition e<strong>in</strong>es Interfaces fuer Klassen zur TextFilterung<br />

public <strong>in</strong>terface TextFilter<br />

{<br />

public Str<strong>in</strong>g filterStr<strong>in</strong>g(Str<strong>in</strong>g str);<br />

}


FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />

FG TECHNISCHE INFORMATIK V – JV – 825 – 02 – TH – 01<br />

-----------------------------------------------------------------------------------<br />

E<strong>in</strong>faches Demonstrationsbeispiel zu RMI <strong>in</strong> <strong>Java</strong> (2)<br />

• Quelldatei mit der Def<strong>in</strong>ition der RMI-Server-Klasse (RMIFilterServer.java)<br />

// RMIFilterServer.java<br />

// Start-Klasse e<strong>in</strong>es Servers zum Filtern von Str<strong>in</strong>gs<br />

// Implementierung des Remote-Interfaces RMITextFilter<br />

// E<strong>in</strong>faches Demo-Beispiel zu RMI<br />

import java.rmi.*;<br />

import java.rmi.server.*;<br />

public class RMIFilterServer extends UnicastRemoteObject<br />

implements RMITextFilter<br />

{<br />

TextFilter fil;<br />

}<br />

public RMIFilterServer(TextFilter tf) throws RemoteException<br />

{ super();<br />

fil = tf;<br />

}<br />

public Str<strong>in</strong>g filterStr<strong>in</strong>g(Str<strong>in</strong>g str) throws RemoteException<br />

{<br />

try<br />

{ System.out.pr<strong>in</strong>tln("Remote-Aufruf von : " + RemoteServer.getClientHost());<br />

}<br />

catch (ServerNotActiveException ex)<br />

{ System.err.pr<strong>in</strong>tln("ke<strong>in</strong> Remote-Aufruf");<br />

}<br />

return fil.filterStr<strong>in</strong>g(str);<br />

}<br />

public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />

{<br />

if (System.getSecurityManager() == null)<br />

System.setSecurityManager(new RMISecurityManager());<br />

try<br />

{ RMITextFilter fil = new RMIFilterServer(new UpcaseFilter());<br />

Nam<strong>in</strong>g.reb<strong>in</strong>d("TextFilter", fil);<br />

System.out.pr<strong>in</strong>tln("TextFilter bound <strong>in</strong> Registry");<br />

}<br />

catch (Exception ex)<br />

{ System.out.pr<strong>in</strong>tln("RMIFilterServer error : " + ex.getMessage());<br />

ex.pr<strong>in</strong>tStackTrace();<br />

}<br />

}<br />

• Beispiel e<strong>in</strong>er Text-Filter-Klasse : Quelldatei UpcaseFilter.java<br />

(gleiche Klasse wie im Beispiel zur INET-Socket-Kommunikation)<br />

// UpcaseFilter.java<br />

// Klasse zur Filterung von Str<strong>in</strong>gs : Umwandlung aller Buchstaben <strong>in</strong> Gross-Buchstaben<br />

// Implementierung des Interfaces TextFilter<br />

public class UpcaseFilter implements TextFilter<br />

{<br />

public Str<strong>in</strong>g filterStr<strong>in</strong>g(Str<strong>in</strong>g str)<br />

{<br />

return str.toUpperCase();<br />

}<br />

}


FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK<br />

FG TECHNISCHE INFORMATIK V – JV – 825 – 03 – TH – 02<br />

-----------------------------------------------------------------------------------<br />

E<strong>in</strong>faches Demonstrationsbeispiel zu RMI <strong>in</strong> <strong>Java</strong> (3)<br />

• Quelldatei mit der Def<strong>in</strong>ition der RMI-Client-Klasse (RMIFilterClient.java)<br />

// RMIFilterClient.java<br />

// Filterung von Str<strong>in</strong>gs, die ueber die Standarde<strong>in</strong>gabe e<strong>in</strong>gegeben werden<br />

// E<strong>in</strong>faches Demo-Beispiel zu RMI<br />

import java.rmi.*;<br />

import java.io.*;<br />

public class RMIFilterClient<br />

{<br />

static f<strong>in</strong>al Str<strong>in</strong>g DEF_HOST = "localhost";<br />

}<br />

public static void ma<strong>in</strong>(Str<strong>in</strong>g[] args)<br />

{<br />

Str<strong>in</strong>g host = DEF_HOST;<br />

if (args.length>0)<br />

host = args[0];<br />

Str<strong>in</strong>g server = "//"+host+"/"+"TextFilter";<br />

if (System.getSecurityManager() == null)<br />

System.setSecurityManager(new RMISecurityManager());<br />

try<br />

{<br />

RMITextFilter fil = (RMITextFilter) Nam<strong>in</strong>g.lookup(server);<br />

Pr<strong>in</strong>tStream stdout = System.out;<br />

BufferedReader std<strong>in</strong> = new BufferedReader(new InputStreamReader(System.<strong>in</strong>));<br />

Str<strong>in</strong>g l<strong>in</strong>e;<br />

stdout.pr<strong>in</strong>t("E<strong>in</strong>gabe ? ");<br />

while ((l<strong>in</strong>e = std<strong>in</strong>.readL<strong>in</strong>e()) != null)<br />

{<br />

l<strong>in</strong>e = fil.filterStr<strong>in</strong>g(l<strong>in</strong>e); // RMI-Aufruf !!!<br />

stdout.pr<strong>in</strong>tln("Ausgabe : " + l<strong>in</strong>e);<br />

stdout.pr<strong>in</strong>t("E<strong>in</strong>gabe ? ");<br />

}<br />

}<br />

catch(Exception ex)<br />

{<br />

System.err.pr<strong>in</strong>tln("RMIFilterClient Exception : " + ex.getMessage());<br />

ex.pr<strong>in</strong>tStackTrace();<br />

}

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!