Überblick Fernmethodenaufrufe Remote Method Invocation (RMI) Aufrufe von Methoden an Objekten auf anderen Rechnern Remote-Referenz: Transparente Objektreferenz zu entferntem Objekt Beispiel: Java RMI Java RMI Java Remote Method Invocation Marshalling und Unmarshalling Aufgabe 1 Client Server Stub Skeleton RMI-Referenzenschicht RMI-Transportschicht VS-Übung (SS11) Java RMI 1–1 Java RMI Transportschicht Datenübertragung zwischen Rechnern Implementierung Java RMI – Java Remote Method Invocation 1–2 Java RMI Referenzenschicht Verwaltung von Remote-Referenzen Implementierung der Aufrufsemantik (Beispiele) Aktueller Standard: Verwendung von TCP/IP-Sockets Generell: verschiedene Transportmechanismen denkbar VS-Übung (SS11) VS-Übung (SS11) Unicast, Punkt-zu-Punkt Aufruf an einem replizierten Objekt Strategien zum Wiederaufbau der Verbindung nach einer Unterbrechung Client Server Client Server Stub Skeleton Stub Skeleton RMI-Referenzenschicht RMI-Referenzenschicht RMI-Transportschicht RMI-Transportschicht Java RMI – Java Remote Method Invocation 1–3 VS-Übung (SS11) Java RMI – Java Remote Method Invocation 1–4 Java RMI Stub & Skeleton Stub 1. 2. 3. 4. 5. 6. Java RMI Remote-Objekt (entferntes Objekt) erhält einen Objekt-Ausgabe-Strom von der RMI-Referenzenschicht schreibt die Parameter in diesen Strom teilt der RMI-Referenzenschicht mit, die Methode aufzurufen holt einen Objekt-Eingabe-Strom von der RMI-Referenzenschicht liest das Rückgabe-Objekt aus diesem Strom liefert das Rückgabe-Objekt an den Aufrufer Kann aus einer anderen Java Virtual Machine heraus genutzt werden Erst von außerhalb erreichbar, nachdem es exportiert wurde Remote-Schnittstelle Beschreibt die per Fernaufruf erreichbaren Methoden des Objekts Abgeleitet von java.rmi.Remote (Marker-Schnittstelle) Einzige Möglichkeit mit Java RMI auf ein entferntes Objekt zuzugreifen Skeleton 1. 2. 3. 4. 5. Server erhält einen Objekt-Eingabe-Strom von der RMI-Referenzenschicht liest die Parameter aus diesem Strom ruft die Methode am implementierten Objekt auf holt einen Objekt-Ausgabe-Strom von der RMI-Referenzenschicht schreibt das Rückgabe-Objekt in diesen Strom Client Server Stub Skeleton Remote-Exception (java.rmi.RemoteException) Muss im throws-Clause jeder Remote-Methode angegeben sein Beim Auftreten einer Remote-Exception weiß der Aufrufer nicht, ob die Methode komplett, teilweise oder gar nicht ausgeführt wurde RMI-Referenzenschicht VS-Übung (SS11) Java RMI – Java Remote Method Invocation Java RMI 1–5 Registry Namensdienst VS-Übung (SS11) Stub Skeleton Java RMI – Java Remote Method Invocation Java RMI – Beispiel 1–6 Bank-Anwendung public class VSMoney implements Serializable { private float amount ; Registry-Schnittstelle public VSMoney ( float amount ) { this . amount = amount ; } public interface Registry extends Remote { public void bind ( String name , Remote obj ); public Remote lookup ( String name ); [...] } public float getAmount () { return amount ; } } Zuordnung eines Objekts zu einem eindeutigen Namen Rückgabe der Remote-Referenz zu einem Namen Konto VSAccount (Remote-Schnittstelle) Erzeugung und Verbindung zur Registry public class LocateRe gistry { public static Registry creat eRegistr y ( int port ); public static Registry getRegistry ( String host , int port ); [...] } createRegistry() getRegistry() VS-Übung (SS11) Server Geldbetrag VSMoney Bekanntmachen von Remote-Objekten Abbildung von Objektnamen auf Objektreferenzen bind() lookup() Client Erzeugung einer Registry auf dem lokalen Rechner Holen einer Remote-Referenz auf eine Registry Java RMI – Java Remote Method Invocation 1–7 public interface VSAccount extends Remote { public void deposit ( VSMoney money ) throws R em oteE x cept io n ; } Bank VSBank (Remote-Schnittstelle) public interface VSBank extends Remote { public void deposit ( VSMoney money , VSAccount account ) throws R em o te Ex cep ti on ; } VS-Übung (SS11) Java RMI – Java Remote Method Invocation 1–8 Java RMI – Beispiel Remote-Objekt Java RMI – Beispiel Konto-Implementierung VSAccountImpl VSBankImpl: Implementierung der Remote-Schnittstelle VSBank Exportieren des Remote-Objekts Implementierung der Remote-Schnittstelle VSAccount Exportieren analog zu VSBankImpl Synchronisation paralleler deposit()-Aufrufe Implizit: Unterklasse von java.rmi.server.UnicastRemoteObject public class VSBankImpl extends U n i c a s t R e m o t e O b je c t implements VSBank { // Konstruktor public VSBankImpl () throws R emot e Ex ception { super (); } [Auf welchem Rechner erscheint die Bildschirmausgabe?] // Implementie rung der Remote - Methode public void deposit ( VSMoney money , VSAccount account ) throws RemoteException { account . deposit ( money ); } public class VSAccountImpl implements VSAccount { private float amount ; public VSAccountImpl ( float amount ) { this . amount = amount ; } } VSBank bank = new VSBankImpl (); public synchronized void deposit ( VSMoney money ) { amount += money . getAmount (); System . out . println (" New amount : " + amount ); } Explizit: Aufruf von UnicastRemoteObject.export() public class VSBankImpl implements VSBank { [...] } VSBank b = new VSBankImpl (); VSBank bank = ( VSBank ) U n i c a s t R e m o t e O b j e c t . exportObject (b , 0); } VS-Übung (SS11) VS-Übung (SS11) Java RMI – Java Remote Method Invocation Java RMI – Beispiel Remote-Objekt 1–9 Server Server-Implementierung VSBankServer Java RMI – Java Remote Method Invocation Java RMI – Beispiel 1 – 10 Client Client-Implementierung VSBankClient Erzeugen des Remote-Objekts Exportieren des Remote-Objekts Remote-Objekt mittels Registry bekannt machen public class VSBankClient { public static void main ( String [] args ) throws Exception { // Geldbetrag - Objekt anlegen VSMoney money = new VSMoney (10.0 f ); public class VSBankServer { public static void main ( String [] args ) throws Exception { // Remote - Objekt erzeugen VSBank bankImpl = new VSBankImpl (); // Account anlegen und exportieren VSAccount accountImpl = new VSAccountImpl (100.0 f ); VSAccount account = ( VSAccount ) U n i c a s t R e m o t e O b j e c t . exportObject ( accountImpl , 0); // Remote - Objekt exportieren VSBank bank = ( VSBank ) U n i c as t R e m o t e O b j e c t . exportObject ( bankImpl , 0); // Remote - Referenz holen ( Annahme : Server auf faui05a ) Registry registry = Loca teRegist ry . getRegistry (" faui05a " , 12345); VSBank bank = ( VSBank ) registry . lookup (" bank "); // Remote - Objekt bekannt machen Registry registry = Loca teRegist ry . cre ateRegi stry (12345); registry . bind (" bank " , bank ); // Geld einzahlen bank . deposit ( money , account ); } System . exit (0); } } } VS-Übung (SS11) Java RMI – Java Remote Method Invocation 1 – 11 VS-Übung (SS11) Java RMI – Java Remote Method Invocation 1 – 12 Java RMI – Beispiel Interaktion Ausgangssituation vor Registry-Zugriff des Client Client Java Virtual Machine Java RMI – Beispiel Remote-Referenz auf bank von Registry holen Server Java Virtual Machine money Client Java Virtual Machine Server Java Virtual Machine money account account client VS-Übung (SS11) Interaktion bank Java RMI – Java Remote Method Invocation client 1 – 13 Java RMI – Beispiel Interaktion Methodenaufruf von bank.deposit() Client Java Virtual Machine VS-Übung (SS11) Remote-Referenz bank Java RMI – Java Remote Method Invocation 1 – 14 Java RMI – Beispiel Interaktion Nach dem Auspacken der Parameter Server Java Virtual Machine money Client Java Virtual Machine Server Java Virtual Machine money Kopie von money account account Rem o te-R efer enz bank.deposit() client Kopie von money bank client bank.deposit() bank Stub für account VS-Übung (SS11) Java RMI – Java Remote Method Invocation 1 – 15 VS-Übung (SS11) Java RMI – Java Remote Method Invocation 1 – 16 Java RMI – Beispiel Interaktion Überblick Methodenaufruf von account.deposit() Client Java Virtual Machine Server Java Virtual Machine money Java RMI Java Remote Method Invocation Marshalling und Unmarshalling Aufgabe 1 Kopie von money account account.deposit() Kopie von Kopie von money client VS-Übung (SS11) bank.deposit() bank Java RMI – Java Remote Method Invocation 1 – 17 VS-Übung (SS11) Java RMI – Marshalling und Unmarshalling Marshalling und Unmarshalling Unterschiedliche Datentypen Definition Primitive Datentypen Marshalling: Verpacken von Informationen in einer Nachricht Unmarshalling: Auspacken von Informationen aus einer Nachricht z. B. char, boolean, int,... Benutzerdefinierte Datentypen Problemstellungen Unterschiedliche Datentypen Heterogenität bei der lokalen Repräsentation von Datentypen Unterschiedliche Parameterübergabearten Client 1 – 18 z. B. structs Felder Server z. B. int[47] Referenzen z. B. char * Stub Objekte Skeleton z. B. Strings, Dateien,... ... Kommunikationssystem Host A VS-Übung (SS11) Host B Java RMI – Marshalling und Unmarshalling 1 – 19 ⇒ Kein allgemeines Vorgehen möglich VS-Übung (SS11) Java RMI – Marshalling und Unmarshalling 1 – 20 Heterogenität Heterogenität Byte Sex“-Problem ” Kanonische Repräsentation Big Endian (Network Byte Order) Nutzung einer allgemeingültigen Form als Zwischenrepräsentation z. B. IEEE-Standard ⇒ Eventuell unnötige Konvertierungen Most-significant byte first z. B. SPARC, Motorola Little Endian [z. B. wenn Sender und Empfänger identische Repräsentation nutzen] Least-significant byte first z. B. Intel x86 Sender makes it right“ ” Sender kennt Datenrepräsentation des Empfängers Sender konvertiert Daten ⇒ Multicast an heterogene Gruppe nicht möglich Repräsentation von Fließkommazahlen Allgemein Vorzeichen (s) Mantisse (m) Exponent (e) Zahlenwert: (−1)s ∗ m ∗ 2e Receiver makes it right“ ” Kennzeichnung des Datenformats Empfänger konvertiert Daten ⇒ Bereitstellung sämtlicher Konvertierungsroutinen notwendig Variationsmöglichkeiten Anzahl der Bits für m und e Speicherreihenfolge von m, e und s Byte-Order VS-Übung (SS11) Java RMI – Marshalling und Unmarshalling [Unproblematisch für Byte-Order-Konvertierung] 1 – 21 Unterschiedliche Parameterübergabearten VS-Übung (SS11) Java RMI – Marshalling und Unmarshalling 1 – 22 Serialisierung & Deserialisierung in Java Primitive Datentypen Eingabeparameter Hilfsklasse java.nio.ByteBuffer Teil der Anfragenachricht z. B. value in void setValue(int value); public abstract class ByteBuffer [...] { public static ByteBuffer allocate ( int capacity ); public static ByteBuffer wrap ( byte [] array ); public byte [] array (); public ByteBuffer put < Datentyp >( < Datentyp > value ); public < Datentyp > get < Datentyp >(); [...] } Ausgabeparameter Teil der Antwortnachricht z. B. String-Returnwert in String toString(); allocate() wrap() array() put*(),get*() Ein-/Ausgabeparameter Teil der Anfrage- und Antwortnachricht z. B. Stack in Object pop(Stack stack); neues (leeres) Byte-Array anlegen bestehendes Byte-Array verwenden Byte-Array zurückgeben Daten einfügen bzw. lesen Beispiel: {S,Des}erialisierung eines double-Werts Lösungsansatz double d = 0.47; ByteBuffer buffer1 = ByteBuffer . allocate ( Double . SIZE / 8); buffer1 . putDouble ( d ); byte [] byteArray = buffer1 . array (); ByteBuffer buffer2 = ByteBuffer . wrap ( byteArray ); double d2 = buffer2 . getDouble (); Semantiken: Call-by-Value, Call-by-Result, Call-by-Value-Result Behandlung von Referenzen Zeiger dereferenzieren: Objektkopie erzeugen Remote-Referenzen VS-Übung (SS11) Lösungsvarianten Java RMI – Marshalling und Unmarshalling 1 – 23 VS-Übung (SS11) Java RMI – Marshalling und Unmarshalling 1 – 24 Serialisierung & Deserialisierung in Java Serialisierung & Deserialisierung in Java Objekte Schnittstellen Objekt ⇔ Stream: java.io.Object{Out,In}putStream Automatisierte {S,Des}erialisierung: java.io.Serializable public class O bj e ct Ou t pu t S t r e a m [...] { public O b je ct O u t p u t S t r e a m ( OutputStream out ); public void writeObject ( Object obj ); // Objekt [...] // serialisieren } public class O bj e c t I n p u tS t r e a m [...] { public Ob j ec t In pu t S t r e a m ( InputStream in ); public Object readObject (); // Objekt deserialisieren [...] } Muss von jedem Objekt implementiert werden, das von einen Object{Out,In}putStream serialisiert bzw. deserialisiert werden soll Marker-Schnittstelle → keine zu implementierenden Methoden ⇒ {S,Des}erialisierung wird vom Object{Out,In}putStream übernommen Manuelle {S,Des}erialisierung: java.io.Externalizable Klassenspezifische {S,Des}erialisierung Stream ⇔ Byte-Array: java.io.ByteArray{Out,In}putStream public class B y t e A r r a y O u t p u t S t r e a m extends OutputStream { public byte [] toByteArray (); // Rueckgabe des Byte - Array [...] } public class B y t e A r r a y I n p u t S t r e a m extends InputStream { public B y t e A r r a y I n p u t S t r e a m ( byte buf []); [...] } VS-Übung (SS11) Java RMI – Marshalling und Unmarshalling 1 – 25 Serialisierung & Deserialisierung in Java public interface E xternali zable extends Serializable { void writeExternal ( ObjectOutput out ); void readExternal ( ObjectInput in ); } writeExternal() readExternal() Objekt serialisieren Objekt deserialisieren ⇒ {S,Des}erialisierung wird vom Objekt selbst übernommen VS-Übung (SS11) Java RMI – Marshalling und Unmarshalling 1 – 26 Überblick Geschützte Attribute Einige Attribute einer Klasse sollen nicht serialisiert werden Sicherheitsaspekte Effizienzüberlegungen Einige Objekte können nicht serialisiert & deserialisiert werden, da sich ihr Zustand nicht so ohne weiteres wiederherstellen lässt Java RMI Java Remote Method Invocation Marshalling und Unmarshalling Aufgabe 1 FileInputStream Socket, ServerSocket Thread ⇒ Schlüsselwort transient Mit transient gekennzeichnete Attribute werden bei der automatischen {S,Des}erialisierung vom Object{Out,In}putStream ignoriert Beispiel public class Tr an si e n t Ex a m p l e { private transient Thread t = new Thread (); } VS-Übung (SS11) Java RMI – Marshalling und Unmarshalling 1 – 27 VS-Übung (SS11) Java RMI – Aufgabe 1 1 – 28 Übungsaufgabe 1 Programmieren mit Java RMI Beispielanwendung: Schwarzes Brett Programmieren mit Java RMI public interface VSBoard { public void post ( VS BoardMes sage message ); public VSBoar dMessag e [] get ( int n ); public void listen ( V SB oa r dL is te n er listener ); } Implementierung der Kommunikationsschicht Client Server Stub public interface VS B oa rd Li s te ne r { public void newMessage ( VSBoard Message message ); } post() get() listen() Skeleton Hinzufügen von neuen Botschaften Abfragen der neuesten Botschaften Automatische Benachrichtigung über neue Botschaften Verteilung mittels Java RMI Server Bereitstellung der Anwendung als Remote-Objekt Registrierung des Diensts bei einer Registry Kommunikationssystem Host A Host B Client Zugriff auf den Dienst über Fernaufrufe Interaktion mit dem Nutzer per Kommandozeile VS-Übung (SS11) Java RMI – Aufgabe 1 1 – 29 VS-Übung (SS11) Java RMI – Aufgabe 1 Implementierung der Kommunikationsschicht Optimierte {S,Des}erialisierung Übertragung von Datenpaketen Ziel Minimierung der über das Netzwerk zu übertragenden Daten public class VSConnection { public void sendChunk ( byte [] chunk ); public byte [] receiveChunk (); } Ausgangspunkt Analyse der vom ObjectOutputStream erzeugten Daten Beispielklasse Übermittlung von Daten über eine TCP-Verbindung Senden und Empfangen von Byte-Arrays beliebiger Länge public class VSTestMessage implements Serializable { private int integer ; private String string ; private Object [] objects ; } Übertragung von Objekten public class V S O b j e c t C o n n e c t i o n { public void sendObject ( Serializable object ); public Serializable receiveObject (); } Reduzierung der benötigten Datenmenge Anwendung der Schnittstelle Externalizable Manuelle Implementierung der {S,Des}erialisierungmethoden Senden und Empfangen von beliebigen Objekten Marshalling und Unmarshalling von Nachrichten VS-Übung (SS11) Java RMI – Aufgabe 1 1 – 30 1 – 31 VS-Übung (SS11) Java RMI – Aufgabe 1 1 – 32