Verteilte Kommunikation oberhalb der Socket-API

Slides:



Advertisements
Ähnliche Präsentationen
C ommon O bject R equest B roker A rchitecture
Advertisements

DVG Dateien Dateien. DVG Dateien 2 Die Klasse File Die Klasse File stellt die Verbindung zwischen dem Filesystem des Rechners und dem.
DI Christian Donner cd (at) donners.com
Objektorientierte Programmierung
Datenbankzugriff im WWW (Kommerzielle Systeme)
Lightweight Directory Access Protocol
Internetzugriff mit Strings und Streams
Java 2 Enterprise Edition (J2EE)
10 Streams JavaHS Merseburg WS 05/06 E/A - Ströme (Streams) in Java.
Ausnahmen HS Merseburg (FH) WS 06/07.
Stefanie Selzer - Pascal Busch - Michael Kropiwoda
Java: Objektorientierte Programmierung
Java: Dynamische Datentypen
Indirekte Adressierung
Java: Grundlagen der Sprache
Java: Grundlagen der Objektorientierung
MD 4/02 Hello World from CORBA ein erster Überblick.
Ein Beispiel in Java.
Konstruktoren.
Polymorphie (Vielgestaltigkeit)
Praktikum Entwicklung und Einsatz von Geosoftware I - Sitzung 5 Polymorphismus Sommersemester 2003 Lars Bernard.
Praktikum Entwicklung und Einsatz von Geosoftware I - Sitzung 3 Klassen, Objekte, Arrays und Kontrollstrukturen Sommersemester 2003 Lars Bernard.
Programmieren mit JAVA
Programmieren mit JAVA
Vererbung Spezialisierung von Klassen in JAVA möglich durch
PKJ 2005/1 Stefan Dissmann Ausblick Es fehlen noch: Möglichkeiten zum Strukturieren größerer Programme Umgang mit variabler Zahl von Elementen Umgang mit.
PKJ 2005/1 Stefan Dissmann Rückblick auf 2005 Was zuletzt in 2005 vorgestellt wurde: Klassen mit Attributen, Methoden und Konstruktoren Referenzen auf.
PKJ 2005/1 Stefan Dissmann Zusammenfassung Bisher im Kurs erarbeitete Konzepte(1): Umgang mit einfachen Datentypen Umgang mit Feldern Umgang mit Referenzen.
JAVA RMI.
Projektplan: Fachgebiet Software Engineering Übersicht © Albert Zündorf, Kassel University.
Remote Methode Invocation (RMI)
DVG Kommentare1 Kommentare. DVG Kommentare 2 Kommentare Es gibt zwei Arten von Kommentaren: einzeilige Kommentare // der Kommentar geht.
DVG Einführung in Java1 Einführung in JAVA.
07-GraphischeObjekte Graphische Objekte in EMMA301Paint.
DVG Klassen und Objekte
EDV Parallelprogrammierung1 Parallelprogrammierung mit JAVA.
DVG Kommentare 1 Kommentare. 2 Kommentare Es gibt zwei Arten von Kommentaren: einzeilige Kommentare // der Kommentar geht bis zum Ende der Zeile.
JDBC EDV JDBC.
Common Object Request Broker anhand eines Beispiels Aufgabestellung ( Ein Konto wird von einem Server verwaltet. Der Stand des Kontos wird.
JDBC: JAVA Database Connectivity
Verteilte Kommunikation oberhalb der Socket-API
Workshop: Active Directory
Was umfaßt die CORBA Core Spezifikation? Welche zusätzlichen Komponenten muß ein ORB Produkt beinhalten? Core: CORBA Objekt Modell CORBA Architektur OMG.
Die .NET Common Language Runtime
Learning By Doing TCP/IP Netzwerke mit TCP/IP Das Internet verwendet weitgehend das rund 30-jährige TCP/IP-Protokoll (TCP: Transmission Control Protocol,
Aurich – Jonas Jacobi OSGi Tutorial Aurich – Jonas Jacobi Das OSGi Service Framework Dynamisches Modulsystem für Java Dynamische.
Javakurs FSS 2012 Lehrstuhl Stuckenschmidt
Javakurs FSS 2012 Lehrstuhl Stuckenschmidt
Kap. 4 Der Corba-Standard zur verteilten Objektverwaltung
OOP-Begriffe Abstraktion Modellieren Klasse Objekt Attribute Methoden
Welchen Problemen ist man bei heterogener, verteilter Programmierung ausgesetzt? Hardware: nicht einheitliche, inkompatible Systeme, verschiedene Leistungsfähigkeit.
Beschreiben Sie das Szenario wenn ein ORB einen Server aktiviert und eine Objektimplementation aufruft. Activate Server impl_is_ready Activate Object (GetID.
Die Architektur von Jini Präsentation von Thomas Heinis & Michea Wankerl Seminar Information & Kommunikation WS 2000/01.
7.1.5 Java RMI – Remote Method Invocation
Unterprogramme in JAVA
Objectives Verstehen was unterDelegate verstanden wird
EPROG Tutorium #6 Philipp Effenberger
Untersuchungen zur Erstellung eines
Voyager Eigenschaften/Vorzüge Universalität: –ROI-Modelle: CORBA, RMI, DCOM –verschiedene Namens-, Verzeichnisdienste Nachrichtentypen: synchron, oneway,
Informatik I : Software höhere Programmiersprachen Java Klassen: hat Methoden (Funktionen) und Daten (Variablen) es kann mehrere Klassen geben nur eine.
Alois Schütte Advanced System Programming 2 Interprozeßkommunikation  2.1 JVM Ablaufumgebung  2.2 Java Native Interface (JNI)  Verwendung von.
Internet-Grundtechnologien. Client / Server Client („Kunde“): fordert Information / Datei an im Internet: fordert Internetseite an, z.B.
MD 4/02 CORBA Static/Dynamic Invocation Interface (SII/DII), Interface Repository.
Web Services Spezielle Methoden der SWT Liste V – WS 2008/2009 Christian Boryczewski.
Rusch Philipp, Spiegel Philipp, Sieber Michael, Ucar Sahin, Wetzel Markus.
Java Programme nur ein bisschen objektorientiert.
C++ FÜR cOMPUTERSPIELENTWICKLER
Tutorstunde 10.
Implementieren von Klassen
 Präsentation transkript:

Verteilte Kommunikation oberhalb der Socket-API Datencodierung, Remote Procedure Calls, Verteilte Objektkommunikation, Namensdienste und Ortstranparenz Clemens Düpmeier, 08.04.2017

Zunächst mal 2 Probleme Kommunikation basiert auf Nachrichtenaustausch (über Sockets) Ein grundsätzliches Problem mit Sockets ist Wir müssen Encoding / Decoding der Nachrichten definieren, dass jeder Kommunikationspartner versteht Nachrichten sollen dabei beliebig komplex sein können (i.e. auch komplexe binäre Strukturen) 2. Problem: Wir brauchen einfache, aber universell funktionierende Mechanismen an Stelle von selbst-definierten Protokollen (Abstraktion oberhalb der Protokollebene) Höherwertige Kommunikationsmechanismen stellen Lösungen für diese beiden Probleme bereit Clemens Düpmeier, 08.04.2017

Übertragung komplexer binärer Daten Clemens Düpmeier, 08.04.2017

Externe Datenrepräsentation Höherwertige Kommunikationsmechanismen nutzen ein gemeinsames Datenformat, genannt externe Datendarstellung zur transparenten Übertragung von beliebigen (binären) Daten. Notwendig wegen der Heterogenität der Umgebungen Unterschiedliche Hardwarearchitektur Verschiedene Betriebssysteme Verschiedene Programmiersprachen Unter Marshalling versteht man den Prozess der Transformation strukturierter Datenelemente und elementarer Werte in eine (mit einer Nachricht übertragbaren) externe Datendarstellung Unter Un-Marshalling versteht man den Prozess der Erstellung elementarer Werte aus ihrer externen Datendarstellung und den Wiederaufbau der ursprünglichen Datenstrukturen. Clemens Düpmeier, 08.04.2017

Formen von externen Darstellungen Sender und Empfänger sind sich über die Reihenfolge und die Typen der Datenelemente in einer Nachricht einig ISO: ASN.1 (Abstract Syntax Notation) Sun ONC (Open Network Computing)-RPC: XDR (eXternal Data Representation) Corba: IDL und CDR (Common Data Representation): CDR bildet IDL-Datentypen in Bytefolgen ab. Vollständige Informationen über Reihenfolge und die Typen der Datenelemente sind in einer Nachricht enthalten Java: Objektserialisierung, d.h. Abflachung eines (oder mehrerer) Objektes zu einem seriellen Format inkl. Informationen über die Klassen. Deserialisierung ist die Wiederherstellung eines Objektes ohne Vorwissen über die Typen der Objekte. Clemens Düpmeier, 08.04.2017

Corba CDR Format Typ Darstellung Sequence String Array Struct Enumerated Darstellung Länge gefolgt von Elementen in der angegebenen Reihenfolge Länge gefolgt von Zeichen in der angegebenen Reihenfolge Array-Elemente in der angegebenen Reihenfolge Die Reihenfolge der Deklarationen der Komponenten Unsigned Long Reihenfolge und Typen der Elemente bei Sender und Empfänger bekannt! 0–3 4–7 8–11 12–15 16–19 20-23 24–27 5 "Smit" "h___" 6 "Lond" "on__" 1934 Index in Bytefolge 4 Byte Länge der Zeichenkette “Smith” “London” unsigned int Struct Person{ string name; string place; unsigned int year; }; Smith London 1934

Java Objektserialisierung: vereinfacht public class Person implements Serializable{ private String name; private String place; private int year; public Person(String aName, String aPlace, int aYear) { name = aName; place = aPlace; year = aYear; } // gefolgt von Methoden für den Zugriff auf die Instanzvariablen } Person p = new Person(„Smith“,“London“,1934); Klassenname, Versionsnummer Person 8-Byte Versionsnummer h0 java.lang.String java.lang.String Nummer, Typ und Name der Instanzvariablen 3 int year name: place: 1934 5 Smith 6 London h1 Werte der Instanzvariablen Das echte serialisierte Format enthält zusätzliche Typkennzeichner; h0 und h1 sind Handles, also Verweise auf serialisierte Objekte

Fazit Zuerst die schlechte Nachricht: das sieht alles ziemlich kompliziert zu implementieren aus, und das ist es auch! Die gute Nachricht: Solche externen Datendarstellungen sind schon konzipiert und implementiert und ihre Nutzung ist (insbesondere bei objektorientierten Sprachen) einfach Clemens Düpmeier, 08.04.2017

Elementare Kommunikationsmuster Clemens Düpmeier, 08.04.2017

Blockierende, synchrone Interaktion über Anfrage-Anwort (Request-Reply) Protokoll Client schickt Anfrage-Nachricht an Server Server empfängt Nachricht und führt zugehörige Aktion durch Server sendet Antwort-Nachricht an Client zurück Ausführung auf dem Client blockiert nach Schicken der Anfrage-Nachricht so lange, bis Antwort-Nachricht erhalten wurde Beide, Client und Server, müssen zur Zeit der Interaktion verfügbar sein Wenn nicht, muss durch wiederholtes Senden von Nachrichten Fehlersituation bereinigt werden Typischer Weise über Verbindungs-orientierte Sockets implementiert Punkt-zu-Punkt Verbindung Kommunikationspartner müssen direkt verbunden sein (Keine Message-Router dazwischen) Viele mögliche Fehlersituationen Clemens Düpmeier, 08.04.2017

Mögliche Fehlersituationen bei Request-Reply Client Server 1) Verlust der Auftragsnachricht 2) Verlust der Ergebnisnachricht 3) Ausfall des Servers 4) Ausfall des Clients 1) 2) 3) 4) Clemens Düpmeier, 08.04.2017

at least once Semantik at most once Semantik Client Server Client Request Request Liste der Requests Reply Request Liste der Requests über- prüfen; Verwerfen des 2. Requests Acknowledge- ment Request löschen Reply Request Bearbeitung des Requests; Request eintragen Timeout Timeout Reply Request Bearbeitung des Requests Timeout Timeout Ergebnis kann verschieden sein! Reply Request Bearbeitung des Requests Timeout Timeout Clemens Düpmeier, 08.04.2017

Fehlersemantiken und Eigenschaften Clemens Düpmeier, 08.04.2017

Weiteres zur Fehlerbehandlung Um zu verhindern, dass ein Service vorübergehend nicht verfügbar ist, kann Replizierung des Service (Serverteils) und automatische Lastverteilung und Relokation bei Fehlern eingesetzt werden Für eine "Exactly Once"-Strategie und kompliziertere Konsistenzerhaltung von Daten benötigt man Transaktionskonzept (siehe später) Clemens Düpmeier, 08.04.2017

Remote Procedure Calls (RPC) Vorläufer der Verteilten Objektkommunikationsmechanismen Clemens Düpmeier, 08.04.2017

Idee für einen entfernten Prozeduraufruf Clemens Düpmeier, 08.04.2017

Remote Procedure Calls (Sun-RPC) Realisieren entfernten Funktionsaufruf übernehmen Funktion des Anwenderprotokolls bei Socket-orientierter Kommunikation At least once Semantik (d.h. entfernter Prozeduraufruf wird mindestens 1-mal ausgeführt) synchrone Kommunikation beliebig komplexe Argument(e) und Returnwerte werden als komplexe Datenstrukturen aufgefasst und mit XDR kodiert übertragen bzw. dekodiert. Realisierungen von Funktionsaufrufen, die über Rechnergrenzen hinweg aufgerufen werden können, bezeichnet man als Remote Procedure Calls (RPC). Sie sind eng an der Semantik eines lokalen Funktionsaufrufs orientiert. Der Client soll im wesentlichen bei einem RPC Aufruf die aufzurufende RPC Funktion und ihre Parameter angeben können und wartet anschließend auf die Rückgabe des Returnwertes des RCP Aufrufs. Die Interna des RPC Aufrufs (d.h. das Anwendungsprotokoll, mit dem die Kommunikation zwischen Serverseite und Clientseite erfolgt) sind dabei vollständig intern in der RPC Schnittstelle gekapselt. Der Benutzer der RPC Aufrufe hat damit nichts mehr zu tun. Ihm bieten RPC‘s vielmehr eine „At least once“ Semantik, d.h. sie können sicher sein, das ihr Funktionsaufruf mindestens einmal auf der Serverseite ausgeführt wurde (aber Achtung hier: RPC garantiert nicht, das er genau einmal aufgerufen wurde!) Der Client wartet dabei bis der Server mit dem RPC fertig ist und gegebenenfalls einen Returnwert zurückliefert (synchrone Kommunikation). Die Übertragung der binären Daten (Parameter der Funktion und Returnwert) erfolgt bei einem RPC mit Hilfe eines über verschiedene Rechnerarchitekturen hinweg portablen Codierungsformat (bei klassischen RPC‘s im XDR (external data representation format)). Beim Aufruf des RPC müssen hierzu die entsprechenden Codierungs- und Decodierungsfunktionen mit angegebenen werden. Clemens Düpmeier, 08.04.2017

Synchrone Kommunikation in RPC‘s Client vor Aufruf Client wartet Client nach Aufruf Client RPC Aufruf RPC Return Lokale Funktion aufrufen Server Das obige Diagramm zeigt den synchronen Ablauf eines RPC Aufrufes. Nach Aufruf des RPC Aufrufes auf der Clientseite wartet der aufrufende Code auf der Clientseite bis der Server auf seiner Seite den Aufruf decodiert, dann die zugehörige lokale Funktion ausgeführt, anschließend den Returnwert codiert und dann zurück zum Client übertragen hat. Lokale Prozedur Zeit Clemens Düpmeier, 08.04.2017

Registrierung von RPC Programmen Portmap / rpcbind Client Programm Lookup 111 Registrierung RPC Server Im Gegensatz zu socket-basierten Programmen ist bei RPC Programmen dem Client die Portnummer, an dem der RPC Server seinen Dienst anbietet, nicht mehr unmittelbar bekannt. Stattdessen ist auf jedem Rechner, der RPC basierte Dienste anbietet, ein Auskunftsdienst (der portmapper oder rpcbind Prozess) in Betrieb, der es RPC Clients erlaubt, auf Grund einer Programmnummer und Versionsangabe RPC basierte Server auf diesem Rechner zu finden. Dieser Auskunftsdienst bietet seinen Service an dem speziellen Port 111 sowohl auf Basis von UDP als auch TCP an und ist ebenfalls RPC basiert. Beim Starten des Betriebssystems eines Rechners, der RPC Dienste anbietet, wird zunächst der portmap oder rpcbind Daemon gestartet. RPC Dienste, die anschließend starten, registrieren ihre Dienste durch Angabe einer RPC Programmnummer und Versionsangabe unter dem portmap oder rpcbind Daemon, wobei die intern für den Dienst verwendete Portnummer mit registriert wird. Die Clientseite führt bei einem RPC Aufruf zunächst einen Lookup des Servers beim zugehörigen Registrierungsdaemon der Zielmaschine durch, bekommt dabei intern die Portnummer des RPC Servers mitgeteil, sodass sie sich anschließend mit dem Server zur Durchführung des eigentlichen RPC Aufrufs verbinden kann. RPC Call Client System Server System Clemens Düpmeier, 08.04.2017

Beispiel für RPC Server (Low Level) #include <stdio.h> #include <rpc/rpc.h> #include <rpcsvc/rusers.h> /* lokale Funktion, die Anzahl Benutzer feststellt */ void *rusers(); main() { if (rpc_reg(RUSERSPROG,RUSERSVERS,RUSERSPROCNUM,rusers, xdr_void, xdr_u_int, /* Welche Argument hat RPC Prozedur, * was wird zurückgegeben */ "visible") == -1) /* Tranportwege = hier alle */ fprintf(stderr, "Couldn't register myself as RPC program\n"); exit(1); } svc_run(); /* Endlosschleife, * nur return, wenn durch Signal abgebrochen */ fprintf(stderr, "Programm wurde beendet\n"); Registrierung einer lokalen Prozedur im Laufzeitsystem des Servers unter Angabe von Programmnummer, Version Prozedurnummer Lokaler Funktion Parameterdecodierung Returnwertdecodierung Starten der Laufzeitinfrastruktur des Servers Laufzeitinfrastruktur registriert Programme und Prozeduren im Namensdienst Server des RUSERSPROG RPC Programms. Dieses Programm stellt eine RPC Prozedur bereit, die die Anzahl der Benutzer auf dem Rechner zurueckgibt. durch Aufruf der lokalen Funktion rusers() zurückgibt. Wir muessen dem RPC Laufzeitsystem mitteilen, welche Prozeduren wir bereitstellen. Hierzu geben wir Programmname, Version, Prozedurnummer und dann den Zeiger auf die implementierende Funktion sowie Filter zur Konvertierung nach bzw. vom XDR Format für die Argumentdaten bzw. Returnwertdaten und die Transportart in einem Aufruf von rpc_reg an. rpc_reg kann mehrfach aufgerufen werden, wenn mehr als eine Prozedur im Laufzeitsystem registriert werden soll. OK, wir können nun das Laufzeitsystem starten. Es wählt sich einen freien Serverport und registriert sich dann mit den im Laufzeitsystem registrierten Funktionen beim rpcbind (bzw. portmap). Dann wartet es auf Anfragen und ruft die registrierten Funktionen auf. Es benutzt die angegebenen Datenfilter der Funktionen, um den Datenstrom für die reinkommende Argumentstruktur bzw. für den rausgehenden Returnwert von XDR zu decodieren bzw. nach XDR zu codieren. Clemens Düpmeier, 08.04.2017

Beispiel für RPC Client (Low Level) /* einige includes */ main(argc, argv) int argc; char **argv; { unsigned int nusers; enum clnt_stat cs; if (argc != 2) { fprintf(stderr,"usage: rusers hostname\n"); exit(1); } if (cs= rpc_call(argv[1], RUSERSPROG, /* Programmnummer */ RUSERSVERS, RUSERSPROC_NUM,/* Version, Prozedur */ xdr_void, (char *)0, /* Argumente */ xdr_u_int, (char *)&nusers, /* Returnwert */ "visible") != RPC_SUCCESS) { clnt_perrno(cs); /* Gebe RPC Fehlercode auf Console aus */ fprintf(stdout, "%d users on %s\n", nusers, argv[1]); Aufruf der Prozedur unter Angabe von Hostname, Programmnr., Version Prozedurnummer Codierer + Parameter Decodierer, Variable für Returnwert Ausgabe des Wertes auf Standardausgabe Clemens Düpmeier, 08.04.2017

Low Level RPC sieht wirklich hässlich aus Problem: sieht noch nicht wirklich wie lokaler Prozeduraufruf aus Lösung hierfür ist Stub- und Skeleton Generierung Führe RPC Sprache ein, mit der RPC Aufrufe bzgl. Parameter (welche XDR Typen gehören dazu, etc.) spezifiziert werden RPC-Compiler generiert daraus lokale Funktionen XDR-Kodierungs- und Dekodierungsfunktionen Stubs für die Clientseite (sehen wie lokale Funktionen aus) Anwendungsprogrammierer benutzt nur die Stubs Skeleton für die Serverseite (Skeleton ruft normale Anwenderprozedur auf) Anwendungsprogrammierer programmiert nur Anwendungsprozeduren Stubs und Skeleton kommunizieren dann miteinander über die bereits vorgestellte Low Level RPC Schnittstelle Ähnliches Prinzip sehen wir gleich auch bei RMI und CORBA Clemens Düpmeier, 08.04.2017

Bedeutung von Stubs Aufruf von Stub Stub- oder Proxy /* einige includes */ main(argc, argv) int argc; char **argv; { unsigned int nusers; if (argc != 2) { fprintf(stderr,"usage: rusers hostname\n"); exit(1); } nusers=rusers(argv[1]); // Aufruf Stub fprintf(stdout, "%d users on %s\n", nusers, argv[1]); Bedeutung von Stubs Aufruf von Stub int rusers(char *hostnname) { if (cs= rpc_call(hostname, RUSERSPROG, /* Programmnummer */ RUSERSVERS, RUSERSPROC_NUM,/* Version, Prozedur */ xdr_void, (char *)0, /* Argumente */ xdr_u_int, (char *)&nusers, /* Returnwert */ "visible") != RPC_SUCCESS) return -1; else return cs; } Stub- oder Proxy Clemens Düpmeier, 08.04.2017

Wo wird RPC eingesetzt? RPC Einsatz findet sich an vielen Stellen bei Linux und Windows Betriebssystemen Beispiele Unix / Linux NFS - Network File Sytem YP - YP / NIS Verzeichnisdienst Mount Daemon für das Mounten von Netzwerklaufwerken ... Windows - alles an Diensten, was abhängig vom RPC Dienst ist COM+ Ereignissystem (COM+ Kommunikation allgemein) Dateireplikation Distributed Transaction Dienst Druckerdienst RPC Schnittstellen stellen oftmals unbekannte Sicherheitslücken im Netz dar Clemens Düpmeier, 08.04.2017

Verteilte Objektkommunikation Remote Method Invocation ist die objektorientierte Form der RPC Technologie, die speziell für die Sprache Java entwickelt wurde. Bei dieser Technologie kann man in Java Serverobjekte mit dedizierten Interfaces (Remote Interfaces) implementieren, die ein Client dann über Rechnergrenzen hinweg benutzen kann. Clemens Düpmeier, 08.04.2017

Entfernte und lokale Methodenaufrufe entfernter Aufruf lokaler Jeder Prozess hat Objekte, einige, die entfernte Aufrufe erhalten können - entfernte Objekte genannt -, einige, die nur lokale Aufrufe erhalten können Objekte müssen die entfernte Objektreferenz eines Objektes in einem anderen Prozess kennen, um dessen Methoden aufrufen zu können. Wo bekommen sie diese Referenz her ? Die entfernte Schnittstelle spezifiziert, welche Methoden entfernt aufgerufen werden können Clemens Düpmeier, 08.04.2017

Eigenschaften Verteilter Objekte Interagierende Objekte sind auf mehr als einen Prozess verteilt Wichtige Begriffe (Auswahl, vereinfacht): Entfernte Objektreferenz: die „Adresse“/eindeutige Identität eines Objekts im ganzen verteilten System Entfernte Schnittstellen: die Schnittstelle eines entfernten Objekts (interface definition language, IDL) Ereignisse/Aktionen: Ereignisse/Aktionen von Objekten können Prozessgrenzen überschreiten Exceptions/Ausnahmen: verteilte Ausführung des Systems erweitert das Spektrum möglicher Fehler Garbage Collection: Freigabe nicht mehr benutzten Speichers wird im verteilten System schwieriger Clemens Düpmeier, 08.04.2017

Entfernte Objektreferenzen Über Raum und Zeit garantiert eindeutig! Bestehen aus Internetadresse: gibt den Rechner an Port-Nummer und Zeit: Identifizieren eindeutig den Prozess Objektnummer: Identifiziert das Objekt Schnittstelle: beschreibt die entfernte Schnittstelle des Objekts Werden erzeugt von einem speziellen Modul - dem entfernten Referenzmodul - wenn eine lokale Referenz als Argument an einen anderen Prozess übergeben wird und in dem korrespondierenden Proxy gespeichert. Achtung: Diese Art der Referenz erlaubt kein Verschieben des Objektes in einen anderen Prozess zur Laufzeit! Internetadresse Port-Nummer Zeit Objektnummer Schnittstelle des entfernten Objektes 32 bits

Entfernte Schnittstellen Die entfernte Schnittstelle gibt an, wie auf entfernte Objekte zugegriffen wird (Signatur der Methodenmenge). Ihre Beschreibung enthält Den Namen der Schnittstelle Möglicherweise Datentypdefinitionen Die Signatur aller entfernt verfügbaren Methoden, bestehend aus Dem Methodennamen Ihrer Ein- und Ausgabeparameter Ihrem Rückgabewert Jede Verteilte Objektkommunikationstechnologie besitzt eine eigene Sprache, um solche Schnittstellen zu beschreiben. Clemens Düpmeier, 08.04.2017

Enternte Schnittstelle: Beispiel CORBA IDL struct Person { string name; string place; long year; } ; interface PersonList { readonly attribute string listname; void addPerson(in Person p) ; void getPerson(in string name, out Person p); long number(); }; Parameter sind in, out oder inout Signatur: Definition der Methoden CORBA hat Strukturen, Java hat Klassen entfernte Schnittstelle entfernte Schnittstelle lokaler Aufruf m1 m2 m3 m4 m5 m6 Daten Implementierung der Methoden entfernter

<<interface>> Proxy Design Pattern +request() <<interface>> Subject +request() RealSubject +request() Proxy Bei Verwendung des Proxy Design Patterns bietet man einem Objekt, das ein anderes mit einer bestimmten Funktionalität (d.h. mit bestimmten Methoden, die man aufrufen kann = einem bestimmten Interface, oben Subject genannt) verwenden möchte, statt der realen Implementierung (RealSubject) ein Proxy-Objekt (Proxy) zur Verwendung an, das die gleiche Schnittstelle (interface, d.h. von Namen und Parametern und Returnwert her, die gleichen Methoden) implementiert, wie ein Objekt der realen Implementierung. Das Proxy Objekt selbst benutzt dann eine wie auch immer geartete Kommunikation mit dem realen Objekt, um mit dessen Hilfe die entsprechende Funktionalität umzusetzen, die der Client bei ihm abruft. Der Vorteil dieses Proxy Konzeptes liegt nun darin, das das Proxy Objekt bei gleichbleibender Schnittstelle für das Clientobjekt intern eine Reihe weiterer Aktionen durchführen kann (z.B. eine Protokollierung der Aufrufe, also logging, Statistikdienste, etc.). Im Fall von RMI erledigt der Proxy mit Hilfe der RMI Implementierungsklassen einen für den Client unsichtbaren und völlig transparenten Aufruf des realen Objektes über Rechnergrenzen hinweg. realSubject Clemens Düpmeier, 08.04.2017

Bedeutung von Schnittstellen Client Server Implementierung im Server Gewünschte Schnittstelle im Client Proxy Object (Stub) Skeleton Das Proxy Objekt (im Fall von RMI / Corba auch Stub Objekt genannt) kommuniziert mit der Serverseite über eine Schicht von Protokollen (im Bild gelb) mit einem Skeleton Objekt (bei älteren Implementierungen 1.1.x Java Versionen) bzw. einer Softwareschicht, die die Java Reflection API benutzt, um die vom Proxy-Objekt angeforderten Methodenaufrufe durch Aufrufe der entsprechenden serverseitigen Implementierung umzusetzen (orange dargestellt). Bei der Implementierung werden nach dem Kompilieren der Server- und Clientklassen mit dem Java Compiler durch ein spezielles RMI Tool (rmic = rmi compiler) Skeleton und Stub-Klassen erzeugt, die die Aufrufe des Serverobjektes kapseln und auf die darunterliegenden Protokollschicht abbilden. Neuere Implementierungen (rmic Compiler Option –v1.2 für Java 1.2 kompatible Stubs) nutzen die Möglichkeiten der Reflection API, um dynamisch Methodenaufrufe der Serverobjekte aus den einzelnen Informationen, die über die Protokollklassen übertragen werden, zusammenzubasteln und dann die so zusammengefügte Methode dynamisch aufzurufen (dies leistet gerade die Reflection API). Hierbei entfällt dann die Erzeugung der Skeletonklassen. Kommunikationsschnittstelle Netzwerk Clemens Düpmeier, 08.04.2017

Teile einer Implementierung Kommunikationsschnittstelle: zuständig für das Request-/Reply (Anfrage-Antwort) Protokoll Entferntes Referenzmodul: Übersetzt zwischen entfernten und lokalen Objektreferenzen; besitzt meist eine entfernte Objekt-Tabelle, in der diese Zuordnung eingetragen wird. Beim ersten Aufruf wird die entfernte Objektreferenz von diesem Modul erzeugt. Proxies und Skeletons Proxies (auch Stubs) genannt stellen Client Schnittstelle zur Verfügung Skeletons rufen serverseitige Objektimplementierung auf Clemens Düpmeier, 08.04.2017

Rolle von Proxy und Skeleton Proxy: schafft Transparenz für Client. Proxy implementiert entfernte Schnittstelle. Marshals Request und unmarshals Reply. Leitet Request weiter. Ausführung des Request/Reply Protokolls Dispatcher: wählt Methode im Skeleton aus. Objekt A Entferntes Referenzmodul Kommunikations- schnittstelle Client Proxy B Server Objekt B Dispatcher B Skeleton B Request Reply Skeleton: implementiert Methoden der entfernten Schnittstelle. Unmarshals Request und Marshals Reply. Ruft Methode in entferntem Objekt auf. Übersetzung zwischen lokalen und entfernten Objektreferenzen

Parameterübergabe: Referenz- und Kopiersemantik Entfernte Methodenaufrufe sollten Parameterübergabe-Semantik der verwendeten Programmiersprache respektieren: In Java Übergabe von Werten per Kopie, Übergabe von Objekten per Referenz In C++ freie Wahl der Übergabeart Probleme: Entfernte Referenzen auf Werte prinzipiell nicht möglich Entfernte Referenzen auf Objekte nur möglich, wenn entsprechende Stubs und Skeletons existieren Empfänger benötigt Implementierungsklasse für erhaltenes Objekt (Kopiersemantik) bzw. Stub (Referenzsemantik) Clemens Düpmeier, 08.04.2017

Beispiel für Parameterübergabe Betrachte folgende Objektklasse: import B; public interface A extends Remote { public void setB(B b) throws Throwable; public B getB() throws Throwable;}} public class AServant extends UnicastRemoteObject implements A { private B b; public void setB(B b) { this.b = b; } public B getB() { return this.b; }} AServant B ASkeleton

Parameterübergabe: Kopiersemantik (1) 1. Clientobjekt hält Referenz auf Instanz von A, ruft darauf Methode getB() auf. 2. Stub übermittelt Methodenaufruf an Skeleton 3. Skeleton delegiert Methodenaufruf an Servant 4. Servant übergibt Referenz auf Instanz von B an Skeleton Adressraum 1 Klienten- objekt AStub Adressraum 2 AServant B ASkeleton "getB" Clemens Düpmeier, 08.04.2017

Parameterübergabe: Kopiersemantik (2) 8. Stub übergibt Verweis auf neue Instanz an Aufrufer 7. Stub lädt Klasse B, dekodiert Zustand und erzeugt damit neue Instanz von B 6. Kodierter Zustand wird an Stub übertragen 5. Skeleton kodiert Zustand von Instanz gemäß Wire Protocol Adressraum 1 AStub Klienten- objekt Adressraum 2 AServant B ASkeleton codierter Zustand von B B B.jar Clemens Düpmeier, 08.04.2017

Parameterübergabe: Referenzsemantik (1) 1. Clientobjekt hält Referenz auf Instanz von A, ruft darauf Methode getB() auf. 2. Stub übermittelt Methodenaufruf an Skeleton 3. Skeleton delegiert Methodenaufruf an Servant 4. Servant übergibt Referenz auf Instanz von B an Skeleton Adressraum 1 Klienten- objekt AStub Adressraum 2 AServant ASkeleton B "getB" Clemens Düpmeier, 08.04.2017

Parameterübergabe: Referenzsemantik (2) 8. A-Stub übergibt Verweis auf B-Stub an Aufrufer 7. A-Stub erzeugt neuen B-Stub, der Netzwerkadresse von B-Skeleton enthält 6. A-Skeleton sendet Netzwerkadresse von B-Skeleton an A-Stub 5. A-Skeleton erzeugt neues Skeleton für B, falls nicht bereits vorhanden Adressraum 2 AServant B ASkeleton Adressraum 1 AStub Klienten- objekt (hostname, port) BStub BSkeleton B.jar Clemens Düpmeier, 08.04.2017

Weitere Aspekte der Objektübergabe Festlegung der Übergabesemantik i.A. durch Typ des formalen Parameters: Referenzen und keine Referenzen sind zunächst alles Werte! Die Übergabesemantik regelt die Art der Interpretation. Referenzübergabe, wenn formaler Parameter bestimmtes Interface (in Java RMI z.B. java.rmi.Remote) implementiert Wertübergabe sonst Bei Wertübergabe Komplikationen möglich: Wenn übergebenes Objekt direkt oder indirekt andere Objekte referenziert, müssen diese ebenfalls übergeben werden (mit welcher Übergabesemantik?) Sharing von Objekten muss auf der Clientseite rekonstruiert werden Wenn übergebenes Objekt echter Untertyp des formalen Parameters ist, ist u.U. Upcast erforderlich Was ist mit Garbage Collection von Serverobjekt, wenn Client Referenz darauf hat (siehe nächste Folie)? Clemens Düpmeier, 08.04.2017

Weitere Implementierungsaspekte Namensdienst, der Clients Objektreferenzen zunächst unabhängig von ihrer Lage vermitteln kann Parallele Abarbeitung: Um zu verhindern, dass ein entfernter Aufruf einen anderen Aufruf verzögert, weisen Server der Ausführung jeden entfernten Aufrufs einen eigenen Thread zu! Aktivierung: Automatische Erzeugung einer Instanz und Initialisierung der Instanzvariablen. Persistenter Objektspeicher: Verwaltet persistente Objekte, also Objekte, die zwischen Aktivierungen weiterbestehen. Verteiltes garbage collection: Stellt sicher, dass in einem verteilten System garbage collection durchgeführt wird. Problem: Referenzen, die nur in Nachrichten vorhanden sind. Clemens Düpmeier, 08.04.2017

Fallbeispiel(e) Am Beispiel von Java Clemens Düpmeier, 08.04.2017

Beispiel RMI Clemens Düpmeier, 08.04.2017

RMI – Remote Method Invocation Definiert Verteilte Objektkommunikation von Java-Objekten unabhängig von ihrem Ort Eine reine Java-Lösung Callback Funktionalität und dynamisches Laden von Code Alle entfernten Objekte müssen eine entfernte Schnittstelle definiert als Java Interface abgeleitet von java.rmi.Remote besitzen Es sind Werkzeuge für die Generierung von Stubs und Skeletons vorhanden. JDK stellt eine Implementierung eines Naming-Service zur Verfügung: die RMIregistry. Ein RMI-Dämon erlaubt eine flexible (on-demand)-Instanziierung (Aktivierung) von Objekten. Clemens Düpmeier, 08.04.2017

Remote Reference Layer Remote Reference Layer RMI Architektur Server Client Server Programm Gemeinsames Client Programm Interface Skeleton/Reflection Stubs Remote Reference Layer RMI Komponenten Remote Reference Layer Transport Layer Transport Layer Diese Folie verdeutlicht die unter der Stub-Skeleton/Reflection Schicht liegenden Protokollschichten bei RMI. Sie ist in zwei separate Schichten zerlegt: Im Remote Reference Layer, über den Stubs und Server-objekte in Beziehung zueinander gesetzt sind und Stubs Methoden auf der Serverseite aufrufen Transport Layer, der die Verbindung zwischen den virtuellen Maschinen auf Server- und Clientseite herstellt, pflegt und den Transport der Informationen (Methoden, Parameter und Returnwertinformationen übernimmt). Netzwerk Clemens Düpmeier, 08.04.2017

Remote Reference Layer (RRL) Stub benutzt RRL-API, um Methodenaufrufe auf die Serverseite zu übertragen RRL auf Serverseite benutzt Reflection oder Skeleton Objekte, um auf Serverobjekt zuzugreifen RRL unterstützt unicast Punkt-zu-Punkt Objektverbindungen und aktivierbare Objekte Andere Formen (Multicast) sind denkbar Der Stub benutzt den RRL Layer, um Methodenaufrufe auf die Serverseite zu übertragen. Der RRL Layer auf der Serverseite benutzt die Reflection API oder Skeleton Objekte, um auf das zugehörige Serverobjekt zuzugreifen. RRL unterstützt dabei unicast Punkt zu Punkt Verbindungen und aktivierbare Objekte durch seine Implementierung innerhalb der UniCastRemoteObject oder Activable Serverimplementierungsklassen. Andere Formen, wie Multicast Semantik, ist durch andere Implementierungsklassen denkbar. Clemens Düpmeier, 08.04.2017

Transportlayer Stellt eigentliche Verbindung zwischen JVM's her spricht JRMP (Java Remote Method Protocol) als stream-basiertes Protokoll oberhalb von TCP/IP RMI ab JDK 1.3 spricht zusätzlich das RMI-IIOP Transportprotokoll basierend auf IIOP (Internet Inter-ORB Protocol) ermöglicht Kommunikation zwischen CORBA und RMI Objekten enthält Fähigkeiten, RMI Verkehr über andere Verbindungen zu tunneln (z.B. über HTTP) Der Transportlayer stellt die Verbindung zwischen den JVM‘s auf der Client- und Serverseite her. Es benutzt dabei standardmäßig das JRMP (Java Remote Method Protocol) als ein stream-basiertes (also TCP basiertes) Protokoll oberhalb von TCP/IP. Ab JDK 1.3 kann man auch das RMI-IIOP (ein zwischen RMI und CORBA kompatibles) Übertragungsprotokoll verwenden. Hierzu muss man eine entsprechende Option dem rmic Compiler bei der Erzeugung von Skeleton (in diesem Fall tie Objekte) und Stubs mitteilen (rmic –iiop). Letzteres ermöglicht dann eine Kommunikation zwischen CORBA und RMI Objekten. Mit der zusätzlichen Option -poa des rmic Compilers bekommt man Portable Objekt Adapter (siehe CORBA) kompatible RMI Serverobjekte (d.h. von PortableServer.Servant abgeleitete Klassen) und kann deren zusätzliche Funktionalität für Serverimplementierungen nutzen. Das JRMP Protokoll enthält automatische Fähigkeiten, den RMI Verkehr über HTTP zu tunneln. Falls ein Client keine direkte Verbindung zu einem Serversocket aufbauen kann, versucht er zunächst den Serversocket über Tunneln des RMI Verkehrs über das HTTP Protokoll zu erreichen. Dies funktioniert nur, wenn Firewalls HTTP Protokollverkehr zu beliebigen Ports (nicht nur Port 80) erlauben. Funktioniert dies auch nicht, versucht der Client ein HTTP-RMI CGI Programm unter Port 80 auf dem Zielrechner mit Adresse /cgi-bin/rmi-cgi zu erreichen. Dieses Programm sollte dann den Verkehr an den RMI Server weiterleiten. Ein Beispielimplementierung eines solchen Programms liegt dem JDK unter Beispiele bei. Clemens Düpmeier, 08.04.2017

Beispiel: Interfacebeschreibung eines RMI Objektes (entfernten Objektes) public interface Compute extends Remote { <T> T executeTask(Task<T> t) throws RemoteException; } Interface von Remote ableiten Jeder Methode throws java.rmi.RemoteException hinzufügen Objekte, die so ein "Remote" Interface implementieren, sind entfernte Objekte Jedes Interface, dass entfernte Objekte definiert, muss von dem Interface Remote abgeleitet sein. Alle Methoden des Interface, die von entfernt aufgerufen werden können sollen, müssen die Ausnahme RemoteException (throws RemoteException) werfen. Parameter oder Returnwerte, die wiederum Remote Objekte darstellen, müssen in Form einer Remote Interface Angabe und nicht durch die Angabe einer Implementierungsklasse beschrieben werden. Clemens Düpmeier, 08.04.2017

Verwendet "normales" Objekt mit Interface Task import java.io.Serializable; public interface Task<T> { T execute(); } Nicht-Remote Objektparameter von entfernten Methoden müssen serialisierbar sein Implementierungen müssen also sagen: implements Serializable Ein Task ist für uns ein beliebiges Objekt, dass eine execute() Methode zur Ausführung einer Berechnung besitzt und irgendein Ergebnis zurückgibt Objekte, die Task implementieren, sind lokale Objekte Objekte, die nicht vom Typ Remote sind und als Parameter an Remote-Prozeduren übergeben werden, müssen serialisierbar sein (damit sie von einer Virtuellen Maschine in eine anderen übertragen werden können). Unsere Remote-Methode executeTask() der ComputeEngine verlangt nach einem Task Objekt, dass bestimmt, was berechnet werden soll. Dieses Task Objekt muss das obige Interface erfüllen, damit die ComputeEngine die Berechnung durch Ausführung der Interface-Methode execute() ausführen kann. Der Ergebniswert der Berechnung wird in Form eines beliebigen Objekttyps als Returnwert zurückgegeben. Der Returnwert von execute() ist daher ein Objekt eines beliebigen Typs T. Clemens Düpmeier, 08.04.2017

RMI Parameterübergabe Entfernte Objekte werden als Proxy (Stub) an den Client übergeben (Referenzsemantik) Bei Benutzung sind sowohl Methoden wie auch Daten des Objektes entfernt Andere (lokale Objekte) werden Call by Value (Kopiersemantik) übergeben Beim Kommunikationspartner wird dabei eine Kopie des Objektes angelegt Die Objekte müssen hierfür serialisierbar sein, um übertragen werden zu können Der Code muss beim Kommunikationspartner verfügbar sein oder dynamisch geladen werden Bei der Parameterübergabe an Methoden von Remote Objekten muss man zwei Fälle unterscheiden. Ist der übergebende Parameter wieder ein Remote Objekt, dann wird statt einer Kopie des Objektes der Stub des Remote Objektes (also ein Proxy) übertragen. Nach der Übertragung sind also sowohl dessen Daten als auch dessen Methoden auf den Empfängerrechner bezogen entfernt. Andere Objekte (sogenannte lokale Objekte) werden Call by Value (also als Kopie) übertragen. D.h. der Empfänger arbeitet nach der Übertragung mit einer privaten, lokalen Kopie des Objektes und Änderungen dieses Objektes beeinfluss nicht das Orginal des Objektes beim Absender. An solche lokalen Objekte als Argumente oder Returnwerte von Remote Objektmethoden ist eine einzige Bedingung geknüpft: sie müssen serialisierbar sein, d.h. sie müssen das Serializable Interface implementieren (da Serializable nur ein sogenanntes Marker Interface ist, bei dem man keine Methoden oder so was implementieren muss reicht hier die Angabe implements Serializable). Nicht alle Klasse für Objekte werden als serialisierbar deklariert, da z.B. Objekte, die an lokale Ressourcen gebunden sind (z.B. ein Drucker, Font oder ähnliches) nicht so ohne weiteres als Kopie von einem Rechner auf einen anderen übertragen werden können. Clemens Düpmeier, 08.04.2017

Implementierung des entfernten Objektes public class ComputeEngine extends UnicastRemoteObject implements Compute { public ComputeEngine() throws RemoteException() { super(); } public <T> T executeTask(Task<T> t) { return t.execute(); } } Eine einfache Möglichkeit eine Implementierung für Remote Objekt bereitzustellen, ist es die Implementierungsklasse des Remote Interfaces von der Klasse UnicastRemoteObject abzuleiten. Hierbei erledigt die UnicastRemoteObject einiges, was man ansonsten selbst realisieren muss. Zunächst stellt UnicastRemoteObject einige auf Remote Objekte angepasste Implementierungen von Methoden der Objekt Klasse bereit (equals(), hasCode(), toString()). Dies müsste man ansonsten selbst bereitstellen. Im Konstruktor der UnicastRemoteObject Klass (immer direkt vom Konstruktor unserer eigenen Klasse aufgerufen) wird weiterhin ein erzeugtes Remote Objekt in der RMI Laufzeitinfrastruktur registriert (d.h. dadurch wird es von aussen zugreifbar). Realisiert man die eigene Implementierungsklasse eines Remote Objektes nicht durch Ableitung von UnicastRemoteObjekt, so muss man diese Registrierung von Objekten in der RMI Laufzeitinfrastruktur von Hand für jedes erzeugt Remote Objekt durchführen. Hierzu verwendet man dann die statische Methode UnicastRemoteObject.exportObject() und übergibt dieser dass das Remote Interface implementierende Objekt. Implementierungsklasse wurde von UnicastRemoteObject abgeleitet; dies macht aus Objekt in Konstruktor von UnicastRemoteObject einen Server Konstruktor registriert Remote Objekt gleichzeitig in RMI Laufzeitinfrastruktur und macht Objekt so von aussen referenzierbar Clemens Düpmeier, 08.04.2017

Alternative Implementierung public class ComputeEngine implements Compute { public <T> T executeTask(Task<T> t) { return t.execute(); } } // und später bei Instanzierung ComputeEngine engine = new ComputeEngine(); Compute engineStub =(Compute)UnicastRemoteObject.exportObject(engine,0); Eine weitere Möglichkeit, das entfernte Objekt zu implementieren, ist nur das Compute Interface zu implementieren und nicht von UnicastRemoteObjecdt abzuleiten. Dann muss man allerdings später sein Implementierungsobjekt manuell in der RMI-Laufzeitstruktur registrieren. Dies gescheiht mit einem Aufruf der Methode exportObject der UnicastRemoteObject-Klasse. Die exportObject-Methode registriert dann das übergebende implementierende Objekt in der Laufzeitinfrastruktur und gibt ein Stub (Proxyobjekt) zurück, dass den Zugriff auf die Implementierung kapselt. Der Stub enthält dann bereits die entfernte Objektreferenz, etc. Manuelles Registrieren des engine-Objektes in der RMI-Laufzeitinfrastruktur Laufzeitinfrastruktur liefert dabei Stub (Proxyobjekt) zurück Clemens Düpmeier, 08.04.2017

Namensauflösung bei RMI registry.lookup (liefert Stub) rmiregistry Client Programm 1099 registry.rebind(...) RMI Server rufe remote Methode durch Stub auf Wie bei RPC‘s benötigt man auch für RMI und aller weiteren Formen der Objektkommunikation eine Instanz zum Lookup (Namensauflösung) der Serverobjekte. Bei RMI wird dieser Dienst durch das rmiregistry bereitgestellt. Hierzu wird ein Java basierter Serverdaemon mit Namen rmiregistry (auf dem Serverrechner) gestartet, der normaler Weise auf Port 1099 zu erreichen ist, sofern man den Port nicht bei Aufruf des Daemon ändert. Ruft man anschließend ein RMI Serverprogramm auf, so kann sich dieses durch einen Naming.rebind() Aufruf im rmiregistry Daemon unter einem angegebenen RMI-Remote Objektnamen registrieren (siehe eine der folgenden Folien). Ein Client kann sich im Anschluss daran mit einem Aufruf von Naming.lookup() an das RMI Registry wenden, um ein Stub-Objekt zum Zugriff auf das gewollte Serverobjekt zu bekommen. Dabei gibt der Client den Namen des gewünschten Serverobjektes an. Durch Aufruf der Remote Interface Methoden auf dem zurückgelieferten Stub-Objekt kommuniziert im Anschluss der Client direkt mit der Objektimplementierung im RMI-Server. Stub Client System Server System Clemens Düpmeier, 08.04.2017

Registry Klasse Wie sieht RMI Name aus? //hostname[:port]/Objektname java.rmi.Registry static void rebind(String name, Remote obj) // registriere // obj im Namensdienst // mit Name name ... static Remote lookup(String name) // hole Stub zu Name // unter Anfrage beim // Namensdienst … Die InetSocketAddress Klasse enkapsuliert in Java Adressen, die Sockets zugeordnet werden, d.h. sie enthalten sowohl IP-Adressangaben als auch zugehörige Ports. Angelegt werden Sie über Konstruktoren, bei denen am den Hostnamen entweder als String oder bereits als ein InetAdress und die Portnummer als normale Integer angibt. Weiter gibt es einen Konstruktor für Wildcard IP-Adressen, d.h. bei Erzeugen einer lokalen Adressen gibt man keine IP-Adresse an und dies heisst, dass ein accept() auf allen Interface (falls also der Rechner mehr als eine IP-Adresse hat) erfolgen soll. Die Klasse besitzt weiter Methoden zur Abfrage der einzelnen Teile eines InetSocketAddress Objektes (also Portnummer, InetAddress und/oder Hostname). Wie sieht RMI Name aus? //hostname[:port]/Objektname Clemens Düpmeier, 08.04.2017

Basisstruktur RMI Server (1. Version) if (System.getSecurityManager() == null) System.setSecurityManager(new RMISecurityManager()); String name="//hostname/Compute"; try { Compute engineStub=new ComputeEngine(); Registry registry = LocateRegistry.getRegistry(); registry.rebind(name, engineStub); } catch (Exception e) { } Security Manager setzen = Schutz vor Clientcode Namen für das Serverobjekt definieren Serverobjekt erzeugen; hier Version mit extends UnicastRemoteObject Mit Namen im rmiregistry registrieren Diese Folie verdeutlicht die Basisfunktionsweise eines RMI Serverrumpfes (d.h. Teil der Main-Methode). Zunächst setzt der Server, sofern dies noch nicht erfolgt ist, einen Security Manager ein, der als Schutzwall die Möglichkeiten von Objekten, die eventuell vom entfernten Client auf den Server geladen und dort ausgeführt werden, begrenzt. Der oben verwendete RMISecurityManager bietet hier dem Server die gleichen Schutzbedingungen, wie sie im Fall von Applets durch den SecurityManager im Java Plugin (Java-Implementierung im Browser) bereitgestellt werden, d.h. Objekte, die vom Client geladen werden, dürfen keine lokalen Fileoperationen machen, oder hier betriebssystemspezifische Dinge aufrufen. Sie dürfen sich weiter zur Kommunikation nur auf den Rechner verbinden, von dem sie herkommen. Als erster Schritt zum Remote Serverobjekt wird ein Name für das Serverobjekt definiert (in der Form //hostname/Servicname) und dann ein Serverobjekt als Objekt der zugehörigen Implementierungsklasse instanziiert. Bei dieser Version des Servers gehen wir davon aus, dass die Objektimplementierung von UnicastRemoteObject ableitet und daher bereits durch den Konstruktor in der RMI-Laufzeitinfrastruktur registriert wird. Nun muss nur noch das Objekt unter dem gewählten Namen im rmiregistry durch Aufruf der Methode registry.rebind() Methode registriert werden (registry.rebind(name, remoteObj). Eine Referenz auf dem Server gestartete Registry bekommt man dabei durch LocateRegistry.getRegistry(). Clemens Düpmeier, 08.04.2017

Basisstruktur RMI Server (2. Version) if (System.getSecurityManager() == null) System.setSecurityManager(new RMISecurityManager()); String name="//hostname/Compute"; try { ComputeEngine engine=new ComputeEngine(); Compute engineStub = UnicastRemoteObject.exportObject(engine,0) Registry registry = LocateRegistry.getRegistry(); registry.rebind(name, engineStub); } catch (Exception e) { } Diese Folie verdeutlicht die zweite Form, wie man eine Implementierung des Serverobjektes in der RMI-Laufzeitinfrastruktur registrieren kann. Dies geschieht über den Aufruf der exportObject() Methode. Der zweite Parameter gibt dabei eine Portnummer an, unter der das exportierte Objekt verfügbar sein soll. Wenn 0 angegeben wird, wird irgendeine Portnummer verwendet. Man beachte weiter, dass bei der Registrierung zurückgegebende Stub (Proxyobjekt) und nicht engine in diesem Fall beim Namensdient registriert werden muss. Manuelle Registrierung in der Laufzeitinfrastruktur mit exportObject() Man beachte: das zurückgegebene Stubobjekt und nicht engine wird im Namensdienst registriert Clemens Düpmeier, 08.04.2017

Basisstruktur RMI Client if (System.getSecurityManager() == null) System.setSecurityManager(new RMISecurityManager()); String name="//hostname/Compute"; try { Registry registry = LocateRegistry.getRegistry(args[0]); Compute engine=(Compute)registry.lookup(name); // Methoden des Remote Objektes verwenden } catch .... Entsprechend einfach ist der Code eines RMI client. Auch dieser schützt sich bei Bedarf zunächst einmal durch Einsetzen eines Security Managers vor böswilligen Objekten, die vom RMI Server durch Aufruf von Remote Objektmethoden heruntergeladen werden. Mit dem Namen, der für ein Remote Objekt auf Serverseite definiert wurde, führt er dann ein Lookup des Objektes im rmiregistry durch (registry.lookup(name)). Als Returnwert erhält er dabei ein Objektreferenz auf ein zugehöriges Stubobjekt. Auf diesem kann er anschließend alle Methoden des Remote Interfaces aufrufen. Eine Referenz auf das Registry auf dem Serverrechner bekommt man dabei durch LocateRegistry.getRegistry("hostname"). In unserem Beispiel wird der Hostname als Argument auf der Kommandozeile übergeben. Security Manager setzen = Schutz vor Servercode Lookup des Serverobjektes im Registry Verwendung der Methoden des Remote Objektes Clemens Düpmeier, 08.04.2017

Basisstruktur RMI Client (2) ... try { Registry registry = LocateRegistry.getRegistry(args[0]); Compute engine=(Compute)registry.lookup(name); Pi task = new Pi(Integer.parseInt(args[1])); BigDecimal pi = engine.executeTask(task); System.out.println(pi); } catch .... Entsprechend einfach ist der Code eines RMI client. Auch dieser schützt sich bei Bedarf zunächst einmal durch Einsetzen eines Security Managers vor böswilligen Objekten, die vom RMI Server durch Aufruf von Remote Objektmethoden heruntergeladen werden. Mit dem Namen, der für ein Remote Objekt auf Serverseite definiert wurde, führt er dann ein Lookup des Objektes im rmiregistry durch (registry.lookup(name)). Als Returnwert erhält er dabei ein Objektreferenz auf ein zugehöriges Stubobjekt. Auf diesem kann er anschließend alle Methoden des Remote Interfaces aufrufen. Eine Referenz auf das Registry auf dem Serverrechner bekommt man dabei durch LocateRegistry.getRegistry("hostname"). In unserem Beispiel wird der Hostname als Argument auf der Kommandozeile übergeben. Client berechnet die Zahl PI über den Server Hierzu muss es eine Implementierung des Task-Interfaces geben, die innerhalb ihrer execute()-Methode PI berechnet und den Wert als BigDecimal zurückgibt Clemens Düpmeier, 08.04.2017

Implementierung der PI-Berechnungsklasse zu lang für Folie siehe aber Java Tutorial enthält die komplette Implementierung des Beispiels unter http://java.sun.com/docs/books/tutorial/rmi/client.html Clemens Düpmeier, 08.04.2017

Wie kommt der Server zum Code der Klasse PI? Der jar-File mit dem Code des Servers muss nicht notwendigerweise die Klasse PI enthalten Wie kommt dann aber der Klassencode der Klasse PI zum Server, wenn das PI-Berechnungsobjekt zum Server übertragen und dort ausgeführt wird? Java kann Code dynamisch über Netz laden! Hierfür muss der Code von PI irgendwo zum Download für den Server bereitgestellt werden Und die Infrastruktur so aufgesetzt werden, dass sie weiss, woher der Code geladen werden soll Clemens Düpmeier, 08.04.2017

Zusammenfassung: RMI Anwendung schreiben 1. Definiere die entfernte Schnittstelle 2. Implementiere die entfernte Schnittstelle durch eine Klasse (z.B. abgeleitet von UnicastRemoteObject) 3. Generiere Stubs und Skeletons mit rmic 4. Schreibe einen Server und Client 5. Starte den Namensdienst mit rmiregistry 6. Starte den Server auf der Maschine, wo das rmiregistry läuft 7. Starte den Client Clemens Düpmeier, 08.04.2017

RMI-Beispiel ablaufen lassen Vollständiger Code und Beschreibung im Java Tutorial von Sun Achtung: Beim Starten der Applikation (Client + Server) muss der Klassenlader richtig aufgesetzt werden (siehe Beschreibung im Tutorial), z.B. java -Djava.rmi.server.codebase=http://myhost/Compute/classes/ \ -Djava.rmi.server.hostname=zaphod.east.sun.com - \ -Djava.security.policy=java.policy \ ComputeEngine da sonst die Klassen, die über Netz gehen (z.B. das Stubobjekt vom Server, die Interfaces oder die Client Task Klasse), nicht geladen werden können Außerdem muss die Security-Policy Datei (wir schützen unsere Programme von fremder Code durch SecurityManger) richtig aufgesetzt werden Clemens Düpmeier, 08.04.2017

Verteilte Objekttechnologien Common Object Request Broker Architecture (CORBA) CORBA ist eine portable Implementierung für verteilte Objekte, die die Realisierung von entfernten Objekten auf verschiedenen Maschinen unter Nutzung verschiedener Programmiersprachen (C, C++, Java, etc.) ermöglicht. Clemens Düpmeier, 08.04.2017

Object Management Group (OMG) Gründung: April 1989 Ziele: Interoperabilität Anwendungsintegration Portabilität Mitglieder: über 800 Mitglieder darunter: Apple, AT&T, DEC, HP, IBM, Microsoft, SUN,... Entwicklungsprozeß: Request for Proposal (RFP) in heterogenen Umgebungen auf der Basis eines Objektmodells Distributed Component Object Model (DCOM) Clemens Düpmeier, 08.04.2017

Object Management Architecture (OMA) Application Objects spezifische Anwendungsgebiete gehören nicht zur Infrastruktur Common Facilities allgemein nützliche Dienste (Drucken, E-Mail, Datenbanken) nicht notw. Teil aller Infrastrukturen Object Request Broker (Objektbus) Infrastruktur für Kommunikation garantiert Interoperabilität Common Object Services allg. Funktionen zum Erstellen u. Unterhalten von Objekten Application Objects Common Facilities Common Object Services ORB Clemens Düpmeier, 08.04.2017

ORB Aufgabe Einbettung von Objekt-Implementationen ("Server-Objekte") Application Objects Common Facilities Common Object Services ORB Einbettung von Objekt-Implementationen ("Server-Objekte") Vergabe von Objektreferenzen Entgegennehmen von Aufrufen vom Client Transport der Aufrufe zum Server ggf. Aktivierung eines Server-Objektes Übergabe des Aufrufs zum Server-Objekt Entgegennehmen von Ergebnissen und Transport / Rückgabe zum Client Unterstützung von Sicherheits- und Abrechnungsfunktionen Clemens Düpmeier, 08.04.2017

CORBA Protokolle: GIOP und IIOP Mit CORBA 2.0 wurde GIOP = General Inter-Orb Protocol als netzwerkunabhängiges Wire Protocol spezifiziert Die (meist verwendete) TCP/IP-Variante heißt IIOP = Internet Inter-Orb Protocol GIOP spezifiziert Nachrichtentypen (Requests, Resultate, Ping, ...) Datenaustauschformat ("Common Data Representation") Interoperable Objektreferenzen (IORs) Service-Kontexte (Request-Anhängsel, mit denen Dienste transparent Informationen übermitteln können) Clemens Düpmeier, 08.04.2017

Aufbau eines CORBA Servers POA (Portable Objekt Adapter) dient als zentrale Zugriffsschnittstelle auf Objektimplementierungen erzeugt eindeutige Objektreferenzen hat Objekt Map nimmt Requests für Objekte vom ORB entgegen Applikationscode aktive Servants main (String args[]) { ORB orb = ORB.init(args); orb.connect ( new AServant() ); orb.connect( new BServant() ); orb.run(); } Haupt- programm Servant Activator i Default Servant statisch (mit Skeleton) dynamisch (ohne Skeleton) ... ORB- Schnittstelle Portable Object Adapter Fabrik für Objektreferenzen 1 2 ... n Active Object Map Servant Activator Default Servant ORB-Kern Event Loop Marshalling Engine Request Interceptors für verschiedene Services (optional) Netzwerk Clemens Düpmeier, 08.04.2017

Ablauf eines Methodenaufrufs Client Objekt Anwendung Implementierung 1) Aufruf 5) Auspacken und 4b) Aktivieren Aufruf IDL Stub IDL Skeletton Implementation Repository 4) Weiterleiten an 2) Parameter einpacken Schnittstelle und Aufruf weiterleiten Object Adapter 4a) Ermitteln der Implementierung Object Request Broker Core 3) Transport über den ORB mit GIOP (IIOP) Clemens Düpmeier, 08.04.2017

Object Services Object Services Naming Event Security Transactions Application Objects Common Facilities Common Object Services ORB Object Services Naming Event Security Transactions Trading Lifecycle Time (= Systemfunktionen) Licensing Properties Relationships Notification Persistence Concurrency Control Externalisation Nur Spezifikation der Schnittstellen und grundlegender Funktionsprinzipien! Clemens Düpmeier, 08.04.2017

Common Facilities Application Objects Common Facilities Common Object Services ORB Höherwertige Dienste für ein breites Spektrum an Anwendungsbereichen Bereitstellung allgemein interessanter Funktionalität (analog zu großen Klassenbibliotheken) Horizontale Common Facilities (Basisfunktionalität allgemein) User Interface Information Management (Speicherung komplexer Strukturen, Formatkonvertierung) Task Management (Workflow, lange Transaktionen) Internationalisierung („Sprachenübersetzung“) Vertikale Common Facilities (Basisfunktionalität speziell) für Marktsegemente, z.B. Banken, Gesundheitswesen, Finanzdienste vgl. „application frameworks“, „business objects“ Clemens Düpmeier, 08.04.2017

Application Objects (Business Objekte) Common Facilities Common Object Services ORB Application Objects (Business Objekte) Andere Schnittstellen Business-Objekte (M, Server) kapseln Speicher, Metadaten, Parallelität u. Regeln einer aktiven Business-Einheit legt fest, wie auf Änderungen in View/Modell reagiert wird Business-Prozeßobjekte (C, Server) kapseln Business-Logik Verwaltung vorwiegend langlebiger Prozesse (Workflow, Transaktion) Präsentationsobjekte (V, Client) grafische Darstellung des Objektes unterschiedliche Präsentationen möglich Komponenten eines Business- Objektes Präsentations- Objekt MVC Business- Prozeß- Objekt Business- Objekt Andere Business-Objekte Dokument Server

IDL (Interface Definition Language) Ada Basismechanismus zur Definition von Schnittstellen (Standard) Unabhängig von spezieller Sprache (dekla-rativ, d.h. ohne algorithmische Teile, d.h. ohne Implementierungsdetails) Sprachbindung für verschiedene Sprachen IDL-Grammatik ist Teilmenge von C++; zusätzlich Mittel für Verteilungskonzepte Beinhaltet Mehrfachvererbung Schnittstellenverzeichnis (Interface Repository), damit selbstbeschreibend IDL ist Kontrakt, der alle und alles zusammenbringt IDL C IDL C++ IDL ORB COBOL IDL Java IDL Smalltalk IDL Clemens Düpmeier, 08.04.2017

Beispiel für eine IDL Datei (1) module Bank { typedef sequence<string> StringArray; struct Person { string name; string vorname; }; // hier fehlt noch exception Definition interface Konto { readonly attribute float kontostand; readonly attribute long geheimzahl; readonly attribute long kontonummer; void einzahlen(in float betrag); void abheben(in float betrag); void unlock(); // Sperre freigeben }; // hier geht es weiter mit dem KontoManager }; Das obige Beispiel zeigt eine typische IDL Beschreibung. Innerhalb einer IDL Moduldeklaration können Datentypen, Strukturen und Objektinterfaces (IDL interface Konstrukt) definiert werden. Mit den typedef Konstrukten werden in Analogie zu C und C++ Namen (im obigen Beispiel StringArray) für zusammengesetzte Datentypen definiert. Ebenfalls in Analogie zu C bzw. C++ lässt sich die Struktur von Structs mit einem Namen verbinden. Solche Strukturdeklarationen lassen sich auch wieder in typedef Definitionen einbeziehen. Das interface Konstrukt der IDL erlaubt die Definition der Schnittstellen von (entfernten) Objekten. In einem Interface können Attribute und Methoden eines Interfaces definiert werden. Attribute sind in so fern spezielle Methodendeklarationen, als dass sie in Zielsprachen für gewöhnlich auf zwei Methoden (einer getter-Methode attribute_name() ohne Parameter und einer Setter Methode attribute_name(wert) umgesetzt werden. Attribute vom Typ readonly werden nur auf die getter Methode abgebildet. Bei der Angabe der Parameter von Methoden muss man mit den Schlüsselwörtern in, out bzw. inout angeben, ob der Parameter einen Werte in die Methoden hineingibt, ein Wert aus der Methode heraus an das aufrufende Programm zurückgegeben werden soll oder der Parameter Werte in beide Richtungen transportieren soll. Diese Angabe ist ungewöhnlich, da Computersprachen so eine Angabe in der Regel nicht besitzen. Wir werden noch sehen, das spezielle Hilfsklassen bzw. Hilfsfunktionen (oft Holder genannt) nötig sind, um als Container für die Werte von out bzw. inout Parametern zu dienen, die Werte an den Aufrufe zurückgeben sollen. Für die Typangabe der Parameter und Returnwerte von Methoden können gängige Standardtypbezeichnungen (wie float, long, void, int) usw. verwendet werden. Weiter werden von der IDL komplexere Typen bereitgestellt und bereits definierte interfaces sind auch erlaubt, wie wir auf den nächsten Folien noch darlegen werden. Clemens Düpmeier, 08.04.2017

Beispiel IDL Datei (2) module Bank { typedef sequence<string> StringArray; struct Person { string name; string vorname; }; exception KontoException { string begruendung; }; // hier war interface Konto definiert interface KontoManager { Konto anmelden(in long kontonr, in long geheimzahl) raises (KontoException); Konto oeffnen(in Person daten); void aufloesen(in Konto konto); StringArray holeKontenInfos(); }; }; Dies ist der zweite Teil unserer Beispiel IDL Datei. Hier wird das Interface KontoManager definiert. Es verwendet das Interface Konto, das auf der vorhergehenden Folie definiert wurde sowohl für Parameter von Methoden als auch als Returnwert von Methoden. Es zeigt weiter, dass Fehler bei entfernten Methodenaufrufen durch Senden eines Exception Objektes (Hier KontoException) über das Netzwerk übertragen werden können. Ein eigenes Exception Objekt kann mit einer exception Definition in der IDL Datei zu definiert werden. Clemens Düpmeier, 08.04.2017

Feature der IDL (1) Mehrere Interface Beschreibungen können in einer Modulbeschreibung zusammengefasst werden Es gibt die von anderen Sprachen bekannten Standardtypen (Gleitkomma, Integer, Zeichen-, bool, Byte und deren Subtypen) Es gibt Konstrukte zum Aufbau von struct's und union's Template Typen sequence und string sowie Arrays Neue Typen können mit typedef deklariert werden interface Definitionen entsprechen neu definierten Objekttypen (Klassen) Es gibt den Begriff Attribut mit name() und name(value) Zugriffsfunktionen Wie wir bereits angedeutet haben, sind die von anderen gängigen Sprachen her bekannten Standarddatentypen auch in der IDL verwendbar (float, int, long, short, char usw.). Weiter gibt es Standarddatentypen für Zeichenketten string und Bytefolgen byte und einen booleschen Typ (bool). Auch Konstrukte zum Aufbau von structs und union sind wie gewohnt vorhanden. Auch Arrays sind in IDL definierbar. Neu ist der Template Typ sequence, wie in unserem Beispiel sequence<string>. Interface Definitionen entsprechen Objektdefinitionen und die spezielle Bedeutung von Attributen haben wir bereits an Hand der vorhergehenden Folie erläutert. Clemens Düpmeier, 08.04.2017

Feature der IDL (2) Es gibt Enumerations (Aufzählungstypen) Man kann Konstanten deklarieren Weiter gibt es Exception Deklarationen für Ausnahmezustände Parameter von Methoden lassen sich als in, out oder inout Parameter definieren Weiter gibt es die Möglichkeit Methoden als vom Typ oneway (d.h. kein Returnwert erwartet) zu deklarieren, was eine nicht-blockierende Bearbeitung bedeutet (der Client wartet hier nicht auf den Server) Auch enumeration (also Aufzählungstypen wie in C++) lassen sich definieren und Konstanten deklarieren. Weiter lassen sich Ausnahmen für die Fehlerbehandlung mit dem exception Konstrukt definieren. Die Bedeutung der Schlüsselwörter in, out oder inout haben wir bereits erklärt. In Bezug auf die Synchronisierung eines entfernten Methodenaufrufes ist es interessant, dass man Methoden als vom Typ oneway deklarieren kann. D.h.: der Client wartet nach Aufruf der Methode nicht auf einen Returnwert oder auf eine Rückmeldung vom Server. Clemens Düpmeier, 08.04.2017

Ablauf einer CORBA Entwicklung Schnittstellendesigner Programmierer interfaces.idl Anwendungsentwickler IDL-Java Compiler IDL-C++ Compiler Client Server client.jar stubs.jar types.hh stubs.cc skels.cc servants.cc

RMI-IIOP Corba Objekte mit RMI Clemens Düpmeier, 08.04.2017

Beispiel-Interface Ganz normales RMI Interface //HelloInterface.java import java.rmi.Remote; public interface HelloInterface extends java.rmi.Remote { public void sayHello( String from ) throws java.rmi.RemoteException; } Ganz normales RMI Interface Clemens Düpmeier, 08.04.2017

Implementierung des Interfaces //HelloImpl.java import javax.rmi.PortableRemoteObject; public class HelloImpl extends PortableRemoteObject implements HelloInterface { public HelloImpl() throws java.rmi.RemoteException { super(); // invoke rmi linking and remote object initialization } public void sayHello( String from ) throws java.rmi.RemoteException { System.out.println( "Hello from " + from + "!!" ); System.out.flush(); Diese Folie zeigt den Rumpf eines CORBA Clients. Dieser muss sich ebenfalls zunächst einmal einen Zugriff auf das CORBA Laufzeitenvironment verschaffen und die Laufzeitstruktur des ORB initialisieren (Aufruf von ORB.init()). Damit sich der Client Zugriff auf das gewollte Serverobjekt verschaffen kann, benötigt er zunächst Zugriff auf den Namensdienst. Auch er verwendet wie der Server hierzu die Methode resolve_initial_references() der orb Objektes und castet die so gewonnene Objektreferenz vomTyp CORBA.Object in das richtige Interface NamingContext des Namensdienstobjektes mit der narrow() Methode der zugehörigen Hilfsklasse NamingContextHelper. Dann bildet der Client den Namen des gewollten CORBA Serverobjekts als Namenskomponentenarray und verschafft sich durch einen Aufruf von der resolve() Methode der NamingContext Klasse vom Namensdienstobjekt ncRef ein Objektreferenz auf das gewollte Serverobjekt. Man beachte, dass die zurückgegebene Objektreferenz wiederum vom generischen Typ CORBA.Object ist und erst in den spezifischen Interfacetyp Hello durch Aufruf der narrow() Methode der zugehörigen Hilfsklasse (HelloHelper) gecastet werden muss. Anschließend kann das Serverobjekt gemäß seinem Interface vom Client verwendet werden (helloRef.sayHello()). Leitet von PortableRemoteObject ab! Clemens Düpmeier, 08.04.2017

RMI-IIOP Serverprogramm //HelloServer.java import javax.naming.InitialContext; import javax.naming.Context; public class HelloServer { public static void main(String[] args) { try { HelloImpl helloRef = new HelloImpl(); // Step 2: Publish the reference using JNDI API Context initialNamingContext = new InitialContext(); initialNamingContext.rebind("HelloService", helloRef ); } catch (Exception e) { e.printStackTrace(); } Diese Folie zeigt den Rumpf eines CORBA Clients. Dieser muss sich ebenfalls zunächst einmal einen Zugriff auf das CORBA Laufzeitenvironment verschaffen und die Laufzeitstruktur des ORB initialisieren (Aufruf von ORB.init()). Damit sich der Client Zugriff auf das gewollte Serverobjekt verschaffen kann, benötigt er zunächst Zugriff auf den Namensdienst. Auch er verwendet wie der Server hierzu die Methode resolve_initial_references() der orb Objektes und castet die so gewonnene Objektreferenz vomTyp CORBA.Object in das richtige Interface NamingContext des Namensdienstobjektes mit der narrow() Methode der zugehörigen Hilfsklasse NamingContextHelper. Dann bildet der Client den Namen des gewollten CORBA Serverobjekts als Namenskomponentenarray und verschafft sich durch einen Aufruf von der resolve() Methode der NamingContext Klasse vom Namensdienstobjekt ncRef ein Objektreferenz auf das gewollte Serverobjekt. Man beachte, dass die zurückgegebene Objektreferenz wiederum vom generischen Typ CORBA.Object ist und erst in den spezifischen Interfacetyp Hello durch Aufruf der narrow() Methode der zugehörigen Hilfsklasse (HelloHelper) gecastet werden muss. Anschließend kann das Serverobjekt gemäß seinem Interface vom Client verwendet werden (helloRef.sayHello()). Clemens Düpmeier, 08.04.2017

RMI-IIOP Clientprogramm public class HelloClient { public static void main( String args[] ) { Context ic; Object objref; HelloInterface hi; try { ic = new InitialContext(); hi = (HelloInterface)ic.lookup("HelloService"); hi.sayHello( " MARS " ); } catch( Exception e ) {} } Diese Folie zeigt den Rumpf eines CORBA Clients. Dieser muss sich ebenfalls zunächst einmal einen Zugriff auf das CORBA Laufzeitenvironment verschaffen und die Laufzeitstruktur des ORB initialisieren (Aufruf von ORB.init()). Damit sich der Client Zugriff auf das gewollte Serverobjekt verschaffen kann, benötigt er zunächst Zugriff auf den Namensdienst. Auch er verwendet wie der Server hierzu die Methode resolve_initial_references() der orb Objektes und castet die so gewonnene Objektreferenz vomTyp CORBA.Object in das richtige Interface NamingContext des Namensdienstobjektes mit der narrow() Methode der zugehörigen Hilfsklasse NamingContextHelper. Dann bildet der Client den Namen des gewollten CORBA Serverobjekts als Namenskomponentenarray und verschafft sich durch einen Aufruf von der resolve() Methode der NamingContext Klasse vom Namensdienstobjekt ncRef ein Objektreferenz auf das gewollte Serverobjekt. Man beachte, dass die zurückgegebene Objektreferenz wiederum vom generischen Typ CORBA.Object ist und erst in den spezifischen Interfacetyp Hello durch Aufruf der narrow() Methode der zugehörigen Hilfsklasse (HelloHelper) gecastet werden muss. Anschließend kann das Serverobjekt gemäß seinem Interface vom Client verwendet werden (helloRef.sayHello()). Clemens Düpmeier, 08.04.2017

Aufruf RMI-IIOP Beispiel // start des Nameservers start orbd -ORBInitialPort 1050 // start des Servers java -classpath . -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory -Djava.naming.provider.url=iiop://localhost:1050 HelloServer // start des Clients java -classpath . -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory -Djava.naming.provider.url=iiop://localhost:1050 HelloClient Clemens Düpmeier, 08.04.2017

Was ist InitialContext()? Zugriff auf einen initialen Namenskontext (Context) eines Namensdienstes über die JNDI-API Java Native Directory Interface (JNDI) Ein JNDI Namenskontext ist eine Menge von JNDI-Namen-zu-Objekt Mappings Jeder Kontext kann weitere Kontexte enthalten (Hierarchische Struktur von Kontexten möglich) Clemens Düpmeier, 08.04.2017

Context Interface javax.naming.Context void bind(Name name, Object object) void bind(String name, Object object) … Context createSubContext(Name name) Context createSubContext(String name) Object lookup(Name name) Object lookup(String name) void rebind(Name name, Object object) void rebind(String name, Object object) Die InetAddress Klasse enkapsuliert in Java Internet Hostaddressen (141.53.44.26), also IP-Adressen. Sie besitzt statische Methoden (z.B. getByName() und getLocalHost()), um solche Adressobjekte zu erzeugen und nicht-statische Methoden, um sich verschiedene Repräsentationsformen der Adresse von einem Adressobjekt zurückgeben zu lassen. Achtung: In getByName() kann man Hostnamen, also mailhost.iai.fzk.de, aber auch Adressen in Dotted-Form also 141.52.44.1 als String angeben, um ein zugehöriges Adressobjekt zu erhalten. getHostName() liefert den Hostnamen (übrigens nicht unbedingt in kanonischer, also Langform mit allen Domain: hiefür gibt es eine weitere Methode) getHostName als String die IP-Adresse in Dotted-Form und getAddress() liefert die IP-Adresse als Array von 4-Bytewerten. Clemens Düpmeier, 08.04.2017

Wie bekomme ich initialen Context? Context ctx = new InitialContext() // falls INITIAL_CONTEXT_FACTORY und PROVIDER_URL bereits definiert // z.B. durch Setzen von java.naming.* Properties // oder Hashtable env=new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.cosnaming.CNCtxFactory"); env.put(Context.PROVIDER_URL, "iiop://localhost:1050"); Context ctx=new InitialContext(env) Die InetAddress Klasse enkapsuliert in Java Internet Hostaddressen (141.53.44.26), also IP-Adressen. Sie besitzt statische Methoden (z.B. getByName() und getLocalHost()), um solche Adressobjekte zu erzeugen und nicht-statische Methoden, um sich verschiedene Repräsentationsformen der Adresse von einem Adressobjekt zurückgeben zu lassen. Achtung: In getByName() kann man Hostnamen, also mailhost.iai.fzk.de, aber auch Adressen in Dotted-Form also 141.52.44.1 als String angeben, um ein zugehöriges Adressobjekt zu erhalten. getHostName() liefert den Hostnamen (übrigens nicht unbedingt in kanonischer, also Langform mit allen Domain: hiefür gibt es eine weitere Methode) getHostName als String die IP-Adresse in Dotted-Form und getAddress() liefert die IP-Adresse als Array von 4-Bytewerten. Factory-Klasse definiert "Art des Namensdienstes", auf den zugegriffen werden soll PROVIDER_URL die URL zum Zugriff Clemens Düpmeier, 08.04.2017

Zugriff auf JNDI-Namensdienste CORBA konformer Namensdienst Factory: com.sun.jndi.cosnaming.CNCtxFactory URL: iiop://localhost:1050 Context ctx = new InitialContext() LDAP Directory Server Factory: com.sun.jndi.ldap.LdapCtxFactory URL: ldap://localhost:389/o=MyOrg DirContext ctx=new InitialDirContext() Clemens Düpmeier, 08.04.2017

RMI-IIOP / JNDI / EJB EJB (Enterprise Java Beans) können RMI-IIOP basierte entfernte Schnittstelle anbieten Zugriff von Clientseite erfolgt dabei typischer Weise über JNDI Context ctx = new InitialContext(); Object ref=ctx.lookup("Calculator/remote"); CalculatorRemote rechner=(CalculatorRemote)PortableRemoteObject .narrow(ref, CalculatorRemote.class); System.out.println("2 + 5 =" + rechner.add(2,5)); Clemens Düpmeier, 08.04.2017

Namens- und Verzeichnisdienste Clemens Düpmeier, 08.04.2017

Namensdienst bind (Name, Zugriffsinf.) lookup("name") Adresse / Zugriffsinform. Adresse / Zugriffsinform. P Resource Zugriff auf Resource Ein Namensdienst (Naming Service) bildet Namen auf Zugriffsinformationen (Adressen) zum Zugriff auf Ressourcen ab Den Vorgang der Zuordnung eines Namens zur Zugriffsinformation nennt man Binden (bind) Clemens Düpmeier, 08.04.2017

Warum Namensdienste Entkoppelung des Zugriffs auf eine Resource von den Adressierungsdetails erhöht die Konfigurierbarkeit (Adressdetails nicht hardcodiert in Client) schafft Ortstransparenz – d.h. Resourcen können relokiert werden ermöglicht Lastverteilung Es können administrative Entscheidungen zum Resource-Management getroffen werden, ohne die Clients neu compilieren zu müssen Clemens Düpmeier, 08.04.2017

Was ist ein Name Namen können verschiedene äquivalente Formen haben Im Programmierkontext häufig strukturierte Objekte, i.e. Array von NamingComponent Objekten in Corba oder CompoundName, CompositeName in JNDI lassen sich typischer Weise äquivalent auch durch Strings beschreiben, z.B. als "cn=HomeDir,cn=John,ou=Marketing,ou=East" oder "ejb/Calculator/Remote" oder meier@iai.fzk.de Benötigen zur Interpretation einen Kontext, in dem die Namensauflösung stattfindet Clemens Düpmeier, 08.04.2017

Was ist die Adresse (Zugriffsinformation) definiert alle für den Zugriff auf die Resource notwendigen Informationen Je nach Kontext und Anwendungssituation nahezu beliebig Kann physikalische Adresse sein: IP-Adresse Kann Name bzgl. eines anderen Namensdienstes oder Auflösungssystem sein Oder Kombination von beiden Oder Objektreferenz In objektorientierten Systemen häufig wieder in Form von Objekten gekapselt z.B. DataSource-Objekte zum Zugriff auf Datenbanken Oder entfernte Objektreferenz oder direkt serialisiertes Proxyobjekt Clemens Düpmeier, 08.04.2017

Kontext Der Kontext eines Namensdienstes definiert bzw. enthält Die Menge der erlaubten Namen (Namensraum) Die Menge der Bindings, die Namen an zugehörige Resourcen bindet Er hat typischer Weise wieder einen Namen und kann als Resource innerhalb eines übergeordneten Kontextes beschrieben sein Clemens Düpmeier, 08.04.2017

Hierarchische Kontexte Kontext "Root oder InitialContext" zugehöriger Name: Kunde/Privatkunde/"Peter Meier" Kontext "Kunde" Kontext "Privatkunde" Kontext "Geschäftskunde" Namen können hierarchisch strukturiert sein Jede Teilkomponente des Namens wird über eigenen Kontext aufgelöst Kontexte können mit gleichen Namensräumen oder vollständig unterschiedlichen Namensräumen arbeiten Clemens Düpmeier, 08.04.2017

Zusammenspiel mehrerer Namensdienste (Federation) zugehöriger Name: clemens@duepmeiers.de DNS-Service Benutzerverwaltung Nutzername Domainname Namen können als zusammengesetzte Namen Komponenten haben, die über verschiedene Namensräume definiert sind Zur Auflösung müssen verschiedene Dienste oder Kontext-Provider zusammenspielen (Federation) Clemens Düpmeier, 08.04.2017

Beispiele für Namensdienste / -räume DNS (Domain Name Service)-Dienst mailhost.iai.fzk.de User-Namen-, Gruppennamenauflösung in Rechnern typischer Weise über Verzeichnisdienste, siehe später, wie YP, NIS oder LDAP Email-Adressen mailto:clemens.duepmeier@iai.fzk.de RPC-registry, RMI-registry, CORBA-Namensdienst rmi://servername/objektname Clemens Düpmeier, 08.04.2017

Verzeichnisdienste Ein Verzeichnisdienst ist ein Namensdienst, der Resourcen neben den physikalischen Adressen weitere beschreibende Metadaten zuordnet oder auch nur beschreibende Metadaten für eine Resource bereitstellt (Metadatendienst oder Metaverzeichnis) Clemens Düpmeier, 08.04.2017

Typische Verzeichnisdienste YP (Yellow Page)-Dienst, NIS (Network Informationsdienst) für Betriebssysteme lösen Anfragen nach Rechnern, Usern, Zugriffsrechten, Druckern, Netzwerkdateisystemen, etc. auf LDAP (Leigweight Directory Service Access Protocol) Services dieselben Informationen wir bei YP, NIS darüberhinaus Organisationsdaten Organsiation, Unterorganisation, Mitarbeiter inklusiver Telefonnummer, etc. beliebige weitere Objekte, insbesondere häufig als Verzeichnisdienst für entfernte Objekte, Datenbankresourcen, etc. eingesetzt UDDI-Verzeichnisse für Web-Services Clemens Düpmeier, 08.04.2017

Beispiel LDAP-Server Lightweight Directory Access Protocol (LDAP) Spezifiziert in RFC 2251 Protokoll zum Zugriff auf Verzeichnisdienste, die auf Basis von OSI X.500 arbeiten (ASN.1 codierte Daten) Namensbeschreibung hierarchisch in der Gestalt "cn=HomeDir,cn=John,ou=Marketing,ou=East" Unter Namen können beliebige LDAP-Objekte (beschrieben durch Attributname-Value Paare) gespeichert werden flexibles Typsystem erlaubt hier beliebige Typen für Attribute eigene Erweiterungen der Schema für LDAP-Objektklassen über Schemabeschreibungssprache möglich Definiert Security-Interfaces, etc und weitere Infrastrukturdienste Clemens Düpmeier, 08.04.2017

binäres Bild Clemens Düpmeier, 08.04.2017

Review – Was ist JNDI? Universelle Client-seitige Java-Schnittstelle zum Zugriff auf Namensdienste unterstützt alle möglichen Arten u.a. DNS, etc. LDAP-Verzeichnisdienste Namens- und Verzeichnisdienste von Business-Obektservern besitzt eine Art von Treiberschnittstelle zum Zugriff auf konkrete Dienste siehe Folie: wie bekomme ich einen Initial-Kontext Clemens Düpmeier, 08.04.2017

Zentrale Schnittstelle: Context Interface javax.naming.Context void bind(Name name, Object object) void bind(String name, Object object) … Context createSubContext(Name name) Context createSubContext(String name) Object lookup(Name name) Object lookup(String name) void rebind(Name name, Object object) void rebind(String name, Object object) Die InetAddress Klasse enkapsuliert in Java Internet Hostaddressen (141.53.44.26), also IP-Adressen. Sie besitzt statische Methoden (z.B. getByName() und getLocalHost()), um solche Adressobjekte zu erzeugen und nicht-statische Methoden, um sich verschiedene Repräsentationsformen der Adresse von einem Adressobjekt zurückgeben zu lassen. Achtung: In getByName() kann man Hostnamen, also mailhost.iai.fzk.de, aber auch Adressen in Dotted-Form also 141.52.44.1 als String angeben, um ein zugehöriges Adressobjekt zu erhalten. getHostName() liefert den Hostnamen (übrigens nicht unbedingt in kanonischer, also Langform mit allen Domain: hiefür gibt es eine weitere Methode) getHostName als String die IP-Adresse in Dotted-Form und getAddress() liefert die IP-Adresse als Array von 4-Bytewerten. Clemens Düpmeier, 08.04.2017

Wie bekomme ich nochmal einen Root-Kontext? Context ctx = new InitialContext() // falls INITIAL_CONTEXT_FACTORY und PROVIDER_URL bereits definiert // z.B. durch Setzen von java.naming.* Properties // oder Hashtable env=new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.cosnaming.CNCtxFactory"); env.put(Context.PROVIDER_URL, "iiop://localhost:1050"); Context ctx=new InitialContext(env) Die InetAddress Klasse enkapsuliert in Java Internet Hostaddressen (141.53.44.26), also IP-Adressen. Sie besitzt statische Methoden (z.B. getByName() und getLocalHost()), um solche Adressobjekte zu erzeugen und nicht-statische Methoden, um sich verschiedene Repräsentationsformen der Adresse von einem Adressobjekt zurückgeben zu lassen. Achtung: In getByName() kann man Hostnamen, also mailhost.iai.fzk.de, aber auch Adressen in Dotted-Form also 141.52.44.1 als String angeben, um ein zugehöriges Adressobjekt zu erhalten. getHostName() liefert den Hostnamen (übrigens nicht unbedingt in kanonischer, also Langform mit allen Domain: hiefür gibt es eine weitere Methode) getHostName als String die IP-Adresse in Dotted-Form und getAddress() liefert die IP-Adresse als Array von 4-Bytewerten. Factory-Klasse definiert "Art des Namensdienstes", auf den zugegriffen werden soll PROVIDER_URL die URL zum Zugriff Clemens Düpmeier, 08.04.2017

Und wie frage ich eine Resource ab? JNDI-Verzeichnisse können (je nach Art) eine Vielzahl von Resourcen zurückliefern Datenbanken stellen solche Resourcen da Man kann den Zugriff auf eine Datenbank durch DataSource-Objekte kapseln (Verbindungsdetails) Und diese in Verzeichnissen bereitstellen Context ctx = new InitialContext(); DataSource ds= (DataSource)ctx.lookup("jdbc/mondialDB"); Connection con = ds.getConnection(); Clemens Düpmeier, 08.04.2017

Und wie war das nochmal mit Entfernten Objekten? EJB (Enterprise Java Beans) können RMI-IIOP basierte entfernte Schnittstelle anbieten Zugriff von Clientseite erfolgt dabei typischer Weise über JNDI Context ctx = new InitialContext(); CalculatorRemote rechner= (CalculatorRemote)ctx.lookup(" Calculator/remote "); System.out.println("2 + 5 =" + rechner.add(2,5)); Clemens Düpmeier, 08.04.2017

Zusammenfassung Namensdienste eignen sich herorragend dazu, um Resourcen von ihren Clients zu entkoppeln Resourcen können logisch benannt werden Applikationen werden dadurch ortstransparent Mit Namensdiensten kann man Lastverteilung / Skalierbarkeit erreichen Client muss Adressdetails nicht kennen und diese können konfigurierbar gehalten werden Der Client wird von Implementierungsdetails entkoppelt Durch Anwendung des Proxy-Design-Patterns kann man Server-seitige Resourcemanagement Funktionalitäten integrieren und rekonfigurieren, ohne die Clients neu übersetzen zu müssen Clemens Düpmeier, 08.04.2017