Client-Server-Praktikum: Aufgabe 1 – CORBA In diesem Tutorial werden Sie die CORBA-Spezifikation kennenlernen und grundlegendes Wissen darüber sammeln. Am Ende des Tutorials sollten Sie in der Lage sein, einfache Anwendungen zu entwickeln welche mit Hilfe von CORBA kommunizieren. 1. Was ist CORBA? Die Common Object Request Broker Architecture (CORBA) ist ein Standard zum Verteilen von Objekten über ein Netzwerk. Er wurde von der Object Management Group (OMG), einem nicht profitorientierten Standardisierungsgremium mit mehr als 700 Mitgliedern (Softwareentwickler, Netzwerkbetreiber, Hardwareproduzenten und kommerzielle Anwender von Computersystemen, unter anderem SUN und IBM) 1991 in der ersten Version definiert. Ziel war, eine Middleware zu schaffen, welche eine orts-, plattform- und implementierungsunabhängige Kommunikation zwischen Applikationen erlaubt. Ein Vermittlungsdienst (Object Request Broker = ORB) gewährleistet dabei das Zusammenarbeiten von Objekten über Rechnergrenzen hinweg. Wirklich interessant geworden ist CORBA seit der Verabschiedung der Version 2.0 im Dezember 1994. Diese Version brachte das Kommunikationsprotokoll IIOP, welches die Kommunikation zwischen Object Request Brokern (ORB) verschiedener Hersteller und vor allem auch über das Internet ermöglicht. CORBA zeichnet sich durch folgende Eigenschaften aus: • Objektorientierung. Die grundlegenden Einheiten der Architektur sind Objekte. • Verteilungstransparenz. CORBA-Programme greifen auf entfernte Objekte mit denselben Mechanismen zu, wie auf lokale Objekte. Der genaue Aufenthaltsort eines Objekts bleibt für seine Klienten in der Regel unbekannt. • Effizienz. Die Architektur für den ORB ist von der OMG bewußt so gehalten, daß effiziente Implementationen möglich sind, die z.B. im Falle rein lokaler Kommunikation dem traditionellen Funktionsaufruf nur unwesentlich nachstehen. • Hardware-, Betriebssystem- und Sprachunabhängigkeit. Die Komponenten eines CORBA-Programms können auf verschiedenen Betriebssystemen, Hardwarearchitekturen und mit verschiedenen Programmiersprachen realisiert werden. • Offenheit. Über den ORB können Programme verschiedener Hersteller zusammenarbeiten. Der Anwender erhält dadurch die Freiheit, jede Komponente bei dem Anbieter kaufen zu können, der seinen individuellen Bedürfnissen am besten gerecht wird. Softwareentwickler erhalten die Chance, am Softwaremarkt von morgen teilzuhaben und Angebote großer Firmen mit spezialisierten Produkten zu ergänzen. CORBA stellt also zum einen eine beachtliche Menge technologischen Know-hows und zum anderen einen selten erreichten Konsens innerhalb der Computerindustrie dar. 1/7 2. Begriffe und Abkürzungen • ORB: Der Object Request Broker (ORB) ist der Kommunikationsbus zwischen CORBA-Objekten. Er bietet einen Mechanismus an, um Anfragen des Clients an die entsprechenden Objekt-Implementierungen weiterzuleiten, und zwar unabhänigig davon, an welchem Ort sich diese im Netzwerk befinden und unter welchem Betriebssystem sie dort laufen. Der Client braucht dabei nicht zu wissen, ob sich das Objekt auf dem gleichen Computer befindet oder auf einem Remotecomputer irgendwo im Netz sitzt. Er muß nur den Namen des Objekts oder die Objektreferenz kennen und wissen, wie man die Schnittstelle des Objekts benutzt. Der ORB kümmert sich um die Details: Das Lokalisieren des Objekts, die Weiterleitung des Aufrufs und das Zurückliefern des Resultats. Hinter einem einfachen Methodenaufruf des Clients verbirgt sich also eine komplexe Netzwerkkommunikation, die vom ORB gehandhabt wird: Eine Anfrage des Clients, bestehend aus dem Methodenaufruf und den Parametern, wird in einem binären Strom umgesetzt (marshalling) und über das Netzwerk an den Server geschickt. Die Informationen werden auf der Server-Seite wieder decodiert (unmarshalling) und die gewünschte Operation ausgeführt. Rückgabewerte werden auf die gleiche Weise wieder über den ORB an den Client gesendet. Zusammengefaßt hat der ORB die Aufgabe, die dem Aufruf des Clients entsprechende Objektimplementierung zu finden, sie falls erforderlich zu aktivieren, die Anfrage an das Objekt zu leiten und entsprechende Rückgabewerte wieder an den Client zurückzugeben. Abbildung 1 – aus VisiBroker 3.0 Programmers Guide • Stubs und Skeletons: Stubs stellen für den Client die Schnittstellen zu den Server-Diensten (Objektmethoden) bereit. Aus der Sicht des Clients verhält sich der Stub wie ein Proxy-Objekt für ein entferntes Server-Objekt. Die ServerObjekte werden mit Hilfe von IDL definiert, ihre zugehörigen Client-Stubs von einem IDL-Compiler generiert. Ein Stub beinhaltet Code für die Umsetzung der Methodenaufrufe mit ihren Parametern in einfache Nachrichtenströme, die an den Server gesendet werden. Die zugrundeliegenden Protokolle oder Dinge wie Datenanordnungen bleiben für den Client vollkommen transparent, der die Dienste als einfache Methodenaufrufe auffasst. Skeletons stellen das Gegenstück zu den Client-Stubs dar. Sie stellen die statischen Schnittstellen für jeden vom Server unterstützten Dienst bereit. Sie beinhalten Code, um eingehende Nachrichten in normale Methodenaufrufe umzusetzen und diese auszuführen. Rückgabewerte werden wieder über die Skeletons in einem binären Strom umgewandelt und an den Client zurückgeschickt. Wie die Stubs werden die Skeletons vom IDL-Compiler aus IDL-Interfaces generiert. 2/7 • • • • • • IDL: CORBA wurde so spezifiziert, daß es sprach- und betriebssystemunabhängig ist. Dazu ist eine einheitliche Schnittstellenbeschreibung der zu verteilenden CORBA-Objekte erforderlich. Diese Beschreibungssprache ist im CORBA-Standard als IDL (Interface Definition Language) definiert und an die Syntax von C/C++ angelehnt. Die Operationen und Attribute, die von einem Server der "Außenwelt" zur Verfügung gestellt werden sollen, werden zunächst in einem Interface mittels IDL beschrieben. Aus einem vollständig beschriebenen IDL-Interface werden dann mit einem IDL-Compiler Stub-Klassen für die Clients und Skeleton-Klassen für den Server in der jeweiligen Programmiersprache erzeugt. Ein IDL-Interface beschreibt dabei lediglich die Schnittstellen der zu veröffentlichenden Dienste und Komponenten des Servers. Es enthält keine Implementierungen. Dadurch wird ermöglicht, daß beispielsweise in Java erstellte Clients auf in C++ realisierte Server-Objekte zugreifen. Interface Repository: Das Interface Repository ist eine vom ORB unterhaltene Online-Datenbank, die zu jeder Objekt-Klasse die Beschreibung ihrer Interfaces enthält. Implementation Repository: Das Implementation Repository enthält Informationen zu allen Objekt-Instanzen. Jedes Objekt wird darin durch eine eindeutige Objektreferenz identifiziert. Da CORBA-Objekte keine laufenden Prozesse sein müssen, ermöglicht das Implementation Repository jederzeit die Aktivierung eines angesprochenen Objekts. BOA: Der BOA (Basic Objekt Adapter) ist für die Verbindung der Server-Objekte mit dem ORB zuständig. Er hat die Aufgabe, Objekte im Implementation Repository zu registrieren und Objekte zu aktivieren und zu deaktivieren. Da der BOA serverseitig Portabilitätsprobleme mit ORBs unterschiedlicher Hersteller hatte, wurde seit dem Corba Standard 2.2 der BOA durch einen POA (Portable Objekt Adapter) ersetzt, welcher außer Portabilität noch zusätzliche, hier nicht erwähnte, Features enthält. Objektreferenzen und IOR: Eine Objektreferenz ist eine Zeichenkette, die ein Objekt innerhalb eines verteilten CORBA-Systems eindeutig kennzeichnet. ORBs unterschiedlicher Hersteller übermitteln Objektreferenzen nach dem IOR-Standard (IOR = Interoperable Object Reference). IIOP: Das IIOP (Internet Inter ORB Protocol) ist ein Netzwerkprotokoll für die Kommunikation zwischen ORBs. 3. Das Vorgehen bei der Entwicklung mit CORBA Prinzipiell erfolgt die Entwicklung einer CORBA-Anwendung stets in den gleichen drei Schritten: 1. IDL-Datei schreiben, d.h. die Schnittstelle der (Server-)Objekte spezifizieren, und mit dem IDL-Compiler kompilieren 2. Server implementieren 3. Client implementieren Der von uns im Praktikum verwendete Object Request Broker ist der Open Source ORB JacORB. Dieses Paket enthält unter anderem die CORBA-Klassen, den IDL-Compiler, sowie weitere für die Entwicklung und den Betrieb von CORBA-Anwendungen nötige Werkzeuge und Programme. Die Online-Produktdokumentation dazu finden Sie unter der URL http://www.jacorb.org/documentation.html. 3/7 Bei der Programmierung gehen Sie wie folgt vor: IDL-Datei schreiben Nehmen wir an, Sie möchten eine Klasse "MeineKlasse" mit vier Methoden im Netz zur Verfügung stellen. Ihr IDL-Interface könnte dann in etwa so aussehen: module Test { interface MeineKlasse { void tunix(); long tuwas(in float zahl); short tuwas2(inout long zahl); float tuwas3(out short zahl); }; }; Die Art eines jeden Parameters (in, inout, out) gibt dabei an, ob mit dem jeweiligen Parameter nur ein Wert an die Methode übergeben werden soll (in), oder ob über diesen Parameter auch ein Wert zurückgegeben wird (inout, out). Sie schreiben also die IDL-Datei und speichern sie z.B. unter dem Namen Test.idl ab. Anschließend kompilieren Sie sie mit dem Kommando idl Test.idl . Nicht erschrecken: Der IDL-Compiler legt Ihnen nun ein Verzeichnis mit dem Namen Test an, in dem sich eine Unzahl von Dateien befindet, die sich von den ORB-Klassen ableiten und über weitere Vererbung die entsprechenden Methoden soweit anpassen, bis sie mit den IDL-Interfaces übereinstimmen. Für Java werden dabei sehr viele Dateien erzeugt, da Java keine Mehrfachvererbung unterstützt und außerdem nur eine Klasse pro Datei erlaubt ist. Je nach Compileroptionen und Art der Klasse werden so pro in der IDL-Datei definierter Klasse ca. fünf Dateien generiert, die alle zusammen das Package Test bilden. Wir werden weiter unten noch auf diese Dateien zurückkommen. Dieses Verzeichnis muss dem Compiler für die Übersetzung des Servers und des Clients bekannt sein. Server (in Java) implementieren Hier müssen Sie zunächst die Klassen mit den Methoden, die Sie bereitstellen möchten, implementieren. Nach erfolgreicher Implementierung müssen Sie den ORB und POA im Server initialiseren und mittels des POA die Objekte beim ORB registrieren. Zuletzt muss dann noch die Objektreferenz in einer globalen IOR-Datei gespeichert werden, falls kein Nameserver benutzt wird. Client (in Java) implementieren Die Methoden, mit denen der Client das von ihm gewünschte Objekt erhält, befinden sich in der vom IDL-Compiler generierten Klasse MeineKlasseHelper.java. Besonders wichtig ist hierbei die Methode narrow. Prinzipiell muss wieder, falls kein Nameserver benutzt wird, die Objektreferenz aus einer globalen IOR-Datei gelesen werden und mit der oben genannten Methode dann zu dem entsprechenden Objekt gecasted werden. Anschließend kann man damit problemlos wie mit einem lokalen Objekt umgehen. Den Code kompilieren Sie haben nun also folgende Dateien vorliegen, die Sie mit dem Compile-Kommando javac *.java compilieren können: MeinServer.java, MeineKlasseImpl.java und MeinClient.java, sowie das generierte Verzeichnis Test. Auf der Serverseite benötigen Sie MeinServer.java, MeineKlasseImpl.java und das Verzeichnis Test, auf den Clientrechnern 4/7 hingegen nur MeinClient.java und das Verzeichnis Test. Beachten Sie bitte die Hinweise zur Java-Laufzeitumgebung. Die Programme ausführen Ausgeführt werden Client sowie auch Server durch das Kommando jaco Client bzw. jaco Server. Falls kein Namerserver benutzt wird, muss als Parameter noch der Pfad zur IORDatei mitangegeben werden. 4. Die vom IDL Compiler erzeugten Dateien MeineKlasse.java Enthält das Interface Ihrer Klasse MeineKlasseHelper.java Enthält nützliche Methoden, um das damit verbundene Objekt zu handhaben. Für Objekte wie structures, enumerations, und unions hält die Helperklasse Methoden zum Schreiben und Lesen bereit. Außerdem bietet sie Methoden wie z.B. narrow MeineKlasseHolder.java Zuständig für die Übergabe von out und inout Parameter _MeineKlasseStub.java Die Stub-Klasse MeineKlassePOA.java und MeineKlassePOATie.java Die Skeleton-Klassen 5. Installation von JacORB Folgende Aufgabenstellung wurde mit den JacORB Binaries 2.2.4 getestet. Hier wird Ihnen nun ein kurzer Überblick gegeben wie Sie JacORB installieren. Installation auf den Pool-Rechnern Sand 6/7 Zuerst muss das heruntergeladene JacORB Archiv in einen Ordner entpackt werden, z.B. in den Ordner /home/[user]/jacorb wobei [user] Ihr Username auf Ihrem Linux System darstellt. Anschließend muss der System-Pfad um den Jacorb BIN-Ordner erweitert werden. Dazu fügen Sie einfach der Datei /home/[user]/.bashrc folgende Zeile hinzu: > export PATH=$PATH:/home/[user]/jacorb/bin Anschließend sollten alle offenen Terminals neugestartet werden. Im JacORB Verzeichnis müssen Sie nun noch folgenden Befehl ausführen: > ant idlcmd > ant jaco Anschließend müssen Sie noch den JacORB Nameservice konfigurieren. Dazu müssen Sie die Konfigurationsdatei jacorb.properties durch den nun folgenden Befehl erstellen: > cp /home/[user]/jacorb/etc/jacorb_properties.template jacorb.properties 5/7 In der Konfigurationsdatei müssen nun folgende Zeilen entsprechend angepasst werden: ORBInitRef.NameService=file:/home/[user]/jacorb/ns.file jacorb.naming.ior_filename=/home/[user]/jacorb/ns.file Wobei die Datei /home/[user]/jacorb/ns.file eine schreibbare Datei sein sollte und in unserem Fall die IOR-Datei repräsentiert. Eine ausführlichere Anleitung finden Sie ebenfalls in der JacORB-Dokumentation. 6. Ihre Aufgabe Stellen Sie eine halbfertige Implementation eines „verteilten Minitaschenrechners“ fertig. Die dazu notwendigen Dateien finden Sie auf der Praktikumsseite. Der Minitaschenrechner unterstützt die Operationen Addition, Subtraktion, Multiplikation, Division und zusätzlich das Quadrieren und Potenzieren. Da wir in dieser Aufgabe fiktiv annehmen dass der Client sehr leistungsschwach ist und keine Rechenoperationen ausführen kann, benutzt er die vom Server bereitgestellten „Rechenobjekte“ BasicArithemtics und SpecialArithmetics um die Operationen remote auf dem Server auszuführen. Der Code des Minitaschenrechners ist folgendermaßen aufgebaut: Calc calc.idl Client Client.java Server BasicArithmeticsImpl.java SpecialArithmeticsImpl.java Server.java In der Datei calc.idl finden sie die Schnittstellenbeschreibungen für die Objekte BasicArithmetics und SpecialArithmetics. Erweitern Sie diese Datei um eine Subtraktion und eine Multiplikation für das Objekt BasicArithmetics. In die Dateien BasicAritmeticsImpl.java und SpecialArithmeticsImpl.java kommt die Implementierung der Objekte. Dies ist ebenfalls Teil Ihrer Aufgabe. Die Datei Server.java implementiert den Server. Hier muss von Ihnen der ORB und POA initialisiert werden, die Objekte instanziiert und die Referenzen der IOR-Datei hinzugefügt werden. Zum Schreiben in die Datei finden Sie im Code bereits einen PrintWriter pw über den Sie mit pw.println(String) zeilenweise in die Datei schreiben können. Zuletzt müssen Sie den Client in der Datei Client.java vervollständigen. Hierzu müssen Sie aus den aus der IOR-Datei eingelesenen Objektreferenzen lokale Remote-Objekte erstellen. Testen Sie anschließend Ihre Implementation indem Sie sämtliche Java-Dateien mit javac übersetzen und anschließend den Server und Client mit folgendem Befehl starten: > jaco Server /home/[user]/jacorb/ns.file > jaco Client /home/[user]/jacorb/ns.file Abzugeben ist der funktionierende Code, ein Screenshot der erfolgreichen Ausführung des Servers und Clients und nachfolgend beantwortete Fragen gepackt im zip oder tar.gz Format. 6/7 Folgende Verständnisfragen sollten ebenfalls beantwortet und mit abgegeben werden: 1. Warum benötigt man bei diesem Versuch eine IOR-Datei? 2. Nennen Sie mindestens drei ORBs von anderen Herstellern. 3. Beschreiben Sie ein Szenario in dem es sinnvoll ist CORBA zu benutzen. Optionale Aufgabe: 4. Testen Sie die CORBA-Aufgabe über das Netzwerk! Benutzen Sie hierzu zwei Rechner mit unterschiedlichen ZDV-Accounts. Achten Sie darauf dass die IORDatei von beiden Accounts aus gelesen werden kann. Ein hierfür nützliches Kommando zur Rechtevergabe ist im Andrew File System der Befehl fs. 7/7