Programmieren in Java
Programmieren in Java
Programmieren in Java
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 />
}