Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

COM (Component Object Model) / DCOM (Distributed COM)

Ähnliche Präsentationen


Präsentation zum Thema: "COM (Component Object Model) / DCOM (Distributed COM)"—  Präsentation transkript:

1 COM (Component Object Model) / DCOM (Distributed COM)
Evgenij Kuznecov

2 Gliederung Einführung COM Entwicklungsziele Binäre Interoperabilität
COM- Objekte Interfaces / Schnittstellen Klassen Registry

3 Gliederung (2) DCOM Ausblick auf COM+ Serverarten
Sicherheitsmechanismen Kommunikationsaufbau Wiederverwendung von Objekten Automation Threads von DCOM Ausblick auf COM+

4 Einführung komponentenbasierte Softwareentwicklung in Windows-Umgebungen Basistechnologie für verteilte Systeme ActiveX, DNA(Dynamic InterNet Applications ) oder OLE(Object Linking & Embedding) basieren letztendlich auf COM 1996 ein verteiltes Komponenten-Modell entwickelt. Um dies auszudrücken wurde COM um den Buchstaben D für distributed erweitert und hieß damit DCOM. 1 Einführung Microsofts COM hat sich ursprünglich auf komponentenbasierte Softwareentwicklung in Windows-Umgebungen fokussiert, versteht sich inzwischen aber ebenfalls als Basistechnologie für verteilte Systeme. Das Ziel des Softwaregiganten aus Redmond lautet dabei schlicht und einfach "COM überall", sei es im Betriebssystem oder im Internet. Die meisten modernen Microsoft-Technologien, egal ob ActiveX, DNA oder OLE(Object Linking & Embedding), basieren letztendlich auf COM. Grund genug, diese Technologie einmal näher zu durchleuchten. Als Microsoft erkannte, dass es nicht ausreicht Komponenten auf einer lokalen Maschine zu haben, wurde 1996 ein verteiltes Komponenten-Modell entwickelt. Um dies auszudrücken wurde COM um den Buchstaben D für distributed erweitert und hieß damit DCOM. Zunächst wird der grundlegende Aufbau sowie die Funktionsweise des COM beschrieben, worauf dann eine Erläuterung des DCOM folgt.

5 Entwicklungsziele Interoperabilität Skalierbarkeit
Zusammenarbeit zwischen Applikationen in verschienenen Programmiersprachen Skalierbarkeit Keine Beschränkung hinsichtlich der Zahl von Kommunikationspartnern oder ihrer Größe Sprachenunabhängigkeit Unterstützung beliebiger Programmiersprachen Verteilungstransparenz Für einen Client bleibt verborgen, wo die verwendete Komponente liegt Robustheit gegenüber Weiterentwicklung Änderung von Komponenten soll keine Auswirkung auf existierende Clients haben COM verwendet als architekturelles Prinzip das Broker-Pattern. 1.2 Entwicklungsideen Um Microsofts Komponententechnologie zu verstehen, ist zunächst ein Blick auf deren ursprünglichen Entwurfsziele aufschlussreich. Bei der Entwicklung bildeten folgende Anforderungen die Antriebsfeder: Interoperabilität: Ein fundamentales Ziel bestand darin, Kommunikations- und Interaktionsmechanismen zwischen beliebigen Applikationen zu ermöglichen. Skalierbarkeit: Dabei sollen Anwendungen beliebig nach oben skalieren können. Die Verwendung von COM darf also keinerlei Beschränkung hinsichtlich der Zahl von Kommunikationspartnern oder ihrer Größe mit sich führen. Sprachenunabhängigkeit: COM soll beliebige Programmiersprachen unterstützen. Verteilungstransparenz: Greift eine Applikation über COM auf die Funktionalität einer anderen Applikation oder Bibliothek zu, so muss für den Client verborgen bleiben, ob sich diese Funktionalität im selben Adressraum, auf einem anderen Prozess oder sogar auf einem entfernten Netzknoten befindet. Robustheit gegenüber Weiterentwicklung: Wer Funktionalität über COM- Mechanismen zur Verfügung stellt, soll eine Evolution dieser Funktionalität derart durchführen können, dass existierende Clients von Änderungen nicht betroffen sind. Um diese Ziele zu realisieren, verwendet COM als architekturelles Prinzip das Broker-Pattern. Im folgenden steht deshalb die Umsetzung der genannten Entwurfsziele auf Basis dieses architekturellen Musters im Vordergrund. Zu beachten ist dabei, dass COM im wesentlichen ein Modell darstellt. Allgemein benötigte Funktionalität steht jedoch in Form von dynamischen Bibliotheken zur Verfügung.

6 Broker-Pattern Struktur
Bild 1: COM folgt dem Broker-Architekturmuster. Clients greifen nicht direkt auf Server zu, sondern benutzen Proxies. Diese besitzen die gleichen Schnittstellen wie die Server-Objekte. Dadurch bleiben alle Aktivitäten für den Client unsichtbar, die für verteilte Kommunikation notwendig sind. Auf der Server-Seite ist der Stub das Pendant zum Proxy.

7 COM Zusammenarbeit verschiedener Applikationen
Client / Server - Prinzip. Einem Client zu ermöglichen, auf die Dienste eines Servers zugreifen binäres Format wie die auszutauschenden Objekte im Speicher abzulegen sind Dienste durch Interfaces  2. COM Beim COM handelt es sich um Microsofts Variante eines Models, dass die Zusammenarbeit verschiedener Applikationen ermöglichen soll. Es handelt sich um ein objektbasiertes Programmiermodell nach dem Client / Server - Prinzip. Hauptaufgabe des COM ist es, einem Client zu ermöglichen, auf die Dienste eines Servers zuzugreifen, unabhängig davon wer sie wann und mit welcher Sprache erstellt hat (sowohl die Clients als auch die Server). Um dies zu erreichen wird innerhalb des COM ein binäres Format festgelegt, wie die auszutauschenden Objekt im Speicher abzulegen sind. Dieses festgelegte Format ermöglicht es jeder Programmiersprache die in der Lage ist Objekte in der geforderten Form im Speicher abzulegen, COM - Objekte zu erstellen. Ein COM - Objekt stellt seine Dienste einem anderen COM - Objekt durch ein (oder auch mehrere) Interface zur Verfügung. Die Module in denen COM - Objekte enthalten sind (.EXE oder .DLL) werden als COM - Server bezeichnet.

8 Binäre Interoperabilität
Motivation unabhängige binäre Anwendungen Lösung virtuelle Tabellen (VTBL) einheitliche Position von Methoden aus Interface in jeder VTable (Handle) 2.3 Binäre Interoperabilität Bisher standen die Konzepte von COM- Schnittstellen im Vordergrund. Ein Client kann demnach über COM- Schnittstellen auf die Funktionalität beliebiger COM- Objekte zugreifen. Die Implementierung dieser Mechanismen wäre weitgehend trivial, wenn es sich um eine einzelne Applikation und um eine festgelegte Programmiersprache handeln würde. Im Falle von COM liegen Clients und Objekte jedoch als unabhängige binäre Anwendungen vor, deren Realisierung in unterschiedlichen Programmiersprachen erfolgen kann. Wie lässt sich in diesem Kontext Interoperabilität erzielen? COM legt die physikalische Struktur von sogenannten virtuellen Tabellen fest, die auf die eigentlichen Methoden verweisen. Der Zugriff auf die von einem COM- Objekt implementierte Schnittstelle geschieht indirekt über einen Schnittstellenzeiger. Dieser wiederum verweist auf die Tabelle von Methodenzeigern, die ihrerseits die eigentlichen Implementierungen referenzieren. Diese doppelte Indirektion entspricht dem Vorgehen des Microsoft C++- Compilers beim Zugriff auf virtuelle Methoden abstrakter Basisklassen. In C++ verweisen Zeiger auf virtuelle Tabellen, die wiederum Methodenzeiger beinhalten. Dadurch erst ist ein dynamischer Zugriff auf Schnittstellen von COM- Objekten möglich. Wenn der Hersteller einer Programmierumgebung nun den Zugriff auf COM- Objekte ermöglichen möchte, muss er in seinem Produkt das physikalische Layout von virtuellen Tabellen nachbilden. Er kann dies aber vor dem Entwickler verbergen, indem er den Zugriff auf COM- Objekte derart abstrahiert, dass diese wie native Objekte der jeweiligen Programmiersprache erscheinen. Exakt dieses Vorgehen findet sich in Programmiersystemen wie Visual Basic, Delphi, Visual J++ oder Powerbuilder. Virtual Function Table Um die Interoperabilität sowohl sprach- als auch architekturübergreifend zu gewährleisten, legt die DCOM- Spezifikation unter anderem eine Datenstruktur für den Zugriff auf die Memberfunktionen der Interfaces fest. Da ist einmal, wie oben dargestellt, die Interfacereferenz, die auf die „Virtual Function Table"(VTBL)-Referenz zeigt, welche wiederum auf die VTBL selbst zeigt. Die VTBL enthält die Referenzen auf die einzelnen Memberfunktionen. Die Funktionen liegen in binärem Code vor, was wiederum zu einer Sprachunabhängigkeit führt. An erster Stelle in der VTBL stehen immer die Funktionen, welche das Interface IUnknown anbietet. Dies liegt daran, dass IUnknown die Basis für alle anderen Interfaces bildet. Bild 8 Die oben beschriebene Datenstruktur lehnt sich stark an die VTBL von C++ an. Dadurch bedingt war C++ die erste Sprache, die COM- Objekte unterstützte.

9 COM - Objekte Bei COM - Objekten handelt es sich um die Instanzen zuvor definierter Klassen eindeutiger Identifikator (Class Identifier CLSID) Vermeindung der Namenskonflikte Festlegung noch vor der Entwicklung einer Klasse Binärer Format API mit der Bezeichnung "CoCreateGuid„ GUIDGEN.EXE oder UUIDGEN.EXE erstellten CLSID's werden in den Headerdateien abgelegt Werden nur von Entwickler des jeweiligen COM- Objektes benötigt oder von Entwicklern die dieses Objekt in einem Ihrer Projekte weiterverwenden 2.1 COM - Objekte Bei COM - Objekten handelt es sich um die Instanzen zuvor definierter Klassen. Ein Unterschied besteht allerdings in deren Bezeichnung, die nicht in umgangsprachlicher Form, sondern durch einen eindeutigen Identifikator (Class Identifier CLSID) geschieht. Es handelt sich hierbei um einen Bit Wert der sicherstellen soll, dass auch tatsächlich Eindeutigkeit im System vorliegt und somit Namenskonflikte vermieden werden. Der Identifikator für ein COM - Objekt muss bereits bei der Entwicklung festgelegt werden, da er für die späteren Nutzer lediglich in binärer Form vorliegen und somit nicht mehr geändert werden kann. Um die Erzeugung eines solchen eindeutigen Schlüssels zu ermöglichen unterstützt das COM eine entsprechende API mit der Bezeichnung "CoCreateGuid". Diese API kann zur CLSID - Generierung genutzt werden, wie dies zum Beispiel durch die Programme GUIDGEN.EXE sowie UUIDGEN.EXE geschieht, die dem Microsoft Visual C++ - Compiler beiliegen. Die so erstellten CLSID's werden in den Headerdateien abgelegt, da sie entweder nur von Entwickler des jeweiligen COM- Objektes benötigt werden, oder aber von Entwicklern die dieses Objekt in einem Ihrer Projekte weiterverwenden möchte.

10 Guid 48 Bits = Rechnerspezifisch 60 Bits = Zeitstempel (100-
Nanosekunden-Intervalle seit dem ) Überlauf ca. im Jahr 3400 4 Bits = GUID-Versionsnummer 16 Bits = aus Systemzeit und Adresse der Netzwerkkarte berechnet Typedef struct GUID { DWORD Data1; // 32 Bit WORD Data2; // 16 Bit WORD Data3; // 16 Bit Byte Data4[8]; // 64 Bit } Solch eine GUID besitzt laut Spezifikation eine 128 Bit-Struktur. 48 Bit davon werden computerspezifisch generiert (wenn eine Netzwerkkarte vorhanden ist von dieser), weitere 60 Bit dienen als Zeitstempel mit einer Auflösung von 100 Nanosekunden. Ein Überlauf des Zeitstempels findet erst ca. im Jahr 3400 statt und er sollte somit groß genug dimensioniert sein. Zur Erzeugung einer GUID dienen die Programme UUIDGEN.EXE bzw. GUIDGEN.EXE.

11 Interfaces Zugriff auf die Funktionalität von Komponenten
Mehrere Interfaces sind erlaubt semantisch zusammengehörige Gruppe von Methoden Facette eines Objekts Erzeugen: Interface Definition Language (IDL) [Attributes] Elementname Typename {memberdescriptions} Kontrakt zwischen dem Anbieter und dem Nutzer zum Beispiel Methoden wie save() zum Datensichern und nicht etwa zum Löschen zu verwenden. 2.2 Interfaces Der Zugriff auf die Funktionalität von Komponenten erfolgt im COM stets über Schnittstellen. Im Gegensatz zu einem reinen objektorientierten Ansatz, kann ein COM- Objekt seine Funktionalität mit Hilfe mehrerer Schnittstellen zur Verfügung stellen, ist also nicht mehr auf eine einzelne Schnittstelle beschränkt (siehe Bild2). Zur Definition eines Interfaces wird die Interface Definition Language (IDL) verwendet. Sie besitzt eine C-ähnliche Syntax und dient zur Definition von COM – Elementen wie Objekte, Interface und Type – Bibliotheken. Um beispielsweise ein Objekt zu beschreiben ist folgende Syntax notwendig : [Attributes] Elementname Typename {memberdescriptions} Die Definition des IProfessoren Interfaces ist folgendermaßen möglich : Jede Schnittstelle enthält dabei eine semantisch zusammengehörige Gruppe von Methoden, was anhand folgender Abbildung eines COM- Objektes verdeutlicht werden soll(siehe Bild2). Anders betrachtet, repräsentiert jede COM- Schnittstelle eine mögliche Rolle oder Facette eines Objekts. Zwischen dem Anbieter und dem Nutzer einer Schnittstelle kommt dabei ein Kontrakt zustande. Der Nutzer muss die Methoden entsprechend ihrer Spezifikation aufrufen, also in der richtigen Reihenfolge und unter Berücksichtigung der für die Parameter vorgesehenen Wertebereiche. Im Gegenzug garantiert das COM- Objekt, die Schnittstelle gemäß ihrer Spezifikation zu implementieren, also zum Beispiel Methoden wie save() zum Datensichern und nicht etwa zum Löschen zu verwenden.

12 IStudenten und IProfessoren
Beispiel erzeugeST löscheSt bearbeiteSt IStudenten IProfessoren erzeugePr löschePr bearbeitePr Das COM - Objekt in der Abbildung besitzt zwei Interface : IStudenten und IProfessoren ("I" ... Interface) mit den jeweiligen Funktionen. Wie das Objekt besitzt auch jedes Interface einen eindeutigen Identifikator (interface identifier IID) der auch mittels der oben erwähnten API und den entsprechenden Tools erzeugt werden kann und ebenso verwendet wird. [Sowohl die Gruppe der CLSID's als auch die der IID's gehören zu den sogenannten GUID's, (Globally Unique Identifiers) deren Format folgendermaßen festgelegt wurde: //IProfessoren.idl // import "unknwn.idl"; //IID_IProfessoren //attribute fuer das IProfessoren - interface [ object, uuid(45C0C4DD-E356-45B7-AB8F-A776AB5735DB), helpstring("IProfessoren - Interface.") ] //Deklaration des IProfessoren - Interface interface IProfessoren: IUnknown { //liste von funktionsdefinitionen fuer durch das interface //unterstuetzte funktionen //[attributes] returntype [calling convention] funcname(params); [propget, helpstring("Ein Eintrag für einen neuen Professor wird erstellt.")] HRESULT erzeugePr([in] LPSTRlprName); [propput, helpstring("Ein Eintrag für einen Professor wird gelöscht.")] HRESULT löschePr([in] LPSTR prName); [propput, helpstring("Setzt den Namen des Termineintrags.")] HRESULT bearbeitePr([in] LPSTR prName, [in] LPSTR prNameNeu); } Nach Aufruf des dem Visual C++ - Compiler beiliegendem Tool MIDL.EXE und Übergabe der Datei IProfessoren.idl werden die Dateien dlldata.c, kartei.h, kartei.tlb, kartei_i.c sowie kartei_p.c generiert. kartei.tlb    : enthält die aktuelle Type Library kartei_i.c, kartei.h: enthalten den aktuellen C++ - Quellcode für das IProfessoren – Interfaces des Kartei – Objektes. kartei_p.c, dlldate.c: enthalten Quellcode, um einen Proxy /Stub zum ein und auspacken der Daten zu entwickeln (wird später erläutert). Das COM - Objekt in der Abbildung besitzt zwei Interfaces: IStudenten und IProfessoren

13 Beispiel Microsoft Interface Definition Language MIDL
[Attributes] Elementname Typename {memberdescriptions} // interface IStudenten [ object, uuid( a2b-3d4e abc), helpstring(“Studenten") ] interface IStudenten : IUnknown { HRESULT erzeugeST([in] LPSTR eStudent); HRESULT löscheST([in] LPSTR lStudent); HRESULT bearbeiteST( [in] LPSTR bStudentAlt, [in] LPSTR bStudentNeu); }; Spätestens an dieser Stelle stellt sich dem Entwickler die Frage, wer eigentlich bei der Realisierung einer neuen COM- Schnittstelle die benötigten Proxies und Stubs sowie den Code für Marshaling und Demarshaling bereitstellen muss. Diese Aufgabe kann nur der Implementierer selbst leisten. Allerdings bietet Microsoft den COM- Entwickler Hilfe durch die Microsoft Interface Definition Language MIDL. Mittels dieser vom DCE- Standard übernommenen und erweiterten Definitionssprache lassen sich COM- Schnittstellen, Typbibliotheken und COM- Klassen festlegen. Hier ein einfaches Beispiel: // interface IFoo [ object, uuid( a2b-3d4e abc), helpstring("Foo"), pointer_default(unique) ] interface IFoo : IUnknown { HRESULT set_foo([in] anytype x); HRESULT get_foo([out] anytype *px); }; Der Programmierer legt diese Spezifikation in einer Datei ab und startet den MIDL- Compiler, der aus dieser Definition automatisch den benötigten Code für Proxies, Stubs und Datenkonvertierung erzeugt, ebenso wie Typbibliotheken. Henne und Ei Im Zusammenhang mit COM- Objekten ist noch darauf hinzuweisen, dass im Gegensatz zu CORBA COM- Objekte keine persistente Identität besitzen. Wer alle Schnittstellenzeiger auf ein bestimmtes COM- Objekt freigibt, kann später nie mehr auf das gleiche Objekt zugreifen. Genau genommen, gibt es in COM überhaupt keine Objekte, sondern lediglich Schnittstellenzeiger auf Objekte. Zum Adressieren und Lokalisieren von Objekten muss entsprechende Registrierungsinformation verwaltet werden. Im Falle von Win32-Systemen wie Windows NT oder Windows 95 steht zu diesem Zweck die sogenannte Systemregistratur zur Verfügung. In dieser hierarchisch organisierten Datenbank erfolgt die Eintragung von Information über COM- Klassen, entweder programmatisch oder manuell (siehe Bild 16). Als Primärschlüssel dient dabei der Klassenidentifikator (CLSID). Das COM- Laufzeitsystem kann auf Basis dieses Schlüssels feststellen, welches Programm oder welche DLL für ein angegebenes COM- Objekt zuständig ist, und dieses daraufhin aktivieren und aufrufen. Bild 16: Für die Abbildung von Klassen- Identifikatoren auf konkrete Implementierungen verwendet COM die Sektion HKEY_CLASSES_ROOT in der Windows- Registry. Im obigen Beispiel gibt es für die COM- Klasse Search eine Implementierung als ausführbares Programm in c:\bin\shape.exe.   Während COM im wesentlichen eine Spezifikation darstellt, implementiert die dynamisch ladbare Bibliothek OLE32.DLL generische API- Funktionen wie zum Beispiel CoCreateInstance(). Der Aufrufer übergibt dieser Methode die CLSID der gewünschten Klasse, worauf das Laufzeitsystem die entsprechende Implementierung mittels der Registrierungsinformation lokalisiert, das Programm oder die Bibliothek gegebenfalls startet und den gewünschten Schnittstellenzeiger an den Aufrufer zurückliefert (siehe Abb. Lokalisierung). Für den Client bleiben all diese Aktivitäten verborgen. Den bisherigen Ausführungen zufolge ließe sich von jeder COM- Klasse lediglich eine Instanz kreieren. Eine solche Einschränkung wäre jedoch mehr als inakzeptabel. Warum sollten verschiedene Applikationen zum Beispiel nur mit einem einzigen Excel-Objekt zusammenarbeiten können. Um mehrere Objekte pro COM- Klasse instanziieren zu können, ist ein Mechanismus wie der new- Operator in C++ notwendig. Genau diese Art von Factory- Konzept schreibt Microsoft in COM zwingend vor. Dabei muss jede Implementierung einer bestimmten COM- Klasse, sei es ein ausführbares Programm eine oder Bibliothek, die Standardschnittstelle IClassFactory exportieren: interface IClassFactory : IUnknown {     HRESULT CreateInstance(IUnknown *punkOuter, const IID& iid, void **ppv);     HRESULT LockServer(BOOL block); }; Die Methode LockServer dient lediglich zu Optimierungszwecken und sei nur der Vollständigkeit halber erwähnt. Interessant an dieser Stelle ist die Methode CreateInstance(), deren Aufgabe darin besteht, Objekte einer bestimmten COM- Klasse zu erzeugen. Der Aufrufer verwendet die Methode CoGetClassObject() aus der Standardbibliothek OLE32.DLL, um unter Angabe der gewünschten CLSID einen Schnittstellenzeiger auf die jeweilige Class- Factory zu besorgen. Sodann lässt sich mit CreateInstance() über die der COM- Klasse zugeordneten Factory eine beliebige Anzahl von Objekten erzeugen.

14 Interfaces (2) Der Zugriff über Schnittstellenzeiger (Handles)
Der Wechsel des Zugriffes von einem Interface auf ein anderes wird als "interface navigation" bezeichnet Interface Iunknown QueryInterface: liefert "Handle" auf gewünschtes Interface AddRef: explizite Speicherverwaltung Release: explizite Speicherverwaltung interface Iunknown { virtual HRESULT QueryInterface(IID& iid, void **ppv) = 0; virtual ULONG AddRef() = 0; virtual ULONG Release() = 0; } Der Zugriff auf COM- Objekte durch Clients erfolgt dabei stets über Schnittstellenzeiger. Ein direkter Zugriff auf das COM- Objekt ist nicht vorgesehen. Um beispielsweise auf erzeugeSt zuzugreifen wird ein Zeiger auf das Interface IStudent benötigt. Um auf die Funktion löschePr zugreifen zu können, wird ein Zeiger auf das Interface IProfessoren benötigt. Der Wechsel des Zugriffes von einem Interface auf ein anderes wird als "interface navigation" bezeichnet. Um diesen Wechsel zu ermöglichen muss jedes Interface die Funktion "QueryInterface" implementieren. Diese Funktion benötigt zwei Parameter, zum einen die IID des gewünschten Interfaces und zum anderen einen Verweis, wo der Zeiger auf das Interface abgelegt werden soll. Beispiel: HRESULT hr; IStudenten *pIStudenten; // Zeiger auf das IStudenten – Interface IProfessoren *pIProfessoren; // Zeiger auf das IProfessoren – Interface //Wechsel des Interfaces von IProfessoren auf Istudenten hr = pIProfessoren->QueryInterface(IID_IStudenten, &pIStudenten); Queryinterface dient dazu, ein Objekt nach der Unterstützung für ein bestimmtes Interface zu fragen. Als Argument wird dabei die IID des gewünschten Interfaces übergeben. Als Ergebnis wird eine Referenz auf das Interface zurückgegeben, wenn es unterstützt wird, bzw. NULL, wenn es nicht unterstützt wird. Neben QueryInterface existieren noch zwei Funktionen die jedes Interface implementieren muss : AddRef und Release. Diese drei Funktionen stellen die Grundfunktionalität jedes Interfaces dar. Sie wurden zusammengefasst in einem Interface mit der Bezeichnung IUnknown . Der eigentliche Clou in der COM- Architektur besteht darin, dass jede COM- Schnittstelle von dieser universellen Basisschnittstelle abgeleitet wird, und damit deren Methoden erbt, was bei der Implementierung zu einem signifikanten Overhead führt. Die Funktionen AddRef und Release werden zum sogenannten LifeTime - Management eines COM - Objektes benötigt. Ein COM - Objekt wird durch einen Client erzeugt sobald es benötigt wird und zerstört, sobald es nicht mehr benötigt wird. Da ein COM - Objekt mehrere Clients besitzen kann muss gewährleistet werden, dass es nicht von einem dieser Clients zerstört wird solange noch andere darauf zugreifen. Aus diesem Grund besitzt jedes Objekt einen sogenannten ReferenzCounter, der durch AddRef erhöht und durch Release verringert wird. Wird ein COM - Objekt erzeugt wird der Counter auf 0 gesetzt. Sobald ein Interface - Pointer mittels der QueryInterface - Funktion einem COM - Objekt "zugeordnet" wird, ruft das COM - Objekt die Funktion AddRef auf, um den ReferenzCounter zu erhöhen. Benötigt der Client die Schnittstelle nicht mehr, ruft es über den jeweiligen Schnittstellenzeiger Release() auf. In Reaktion darauf dekrementiert das COM- Objekt seinen internen Referenzzähler. Fällt dieser auf 0, lässt sich das Objekt mangels Clients aus dem Speicher entfernen. Da dieser Mechanismus sich auf das kooperative und korrekte Verhalten der beteiligten Clients verlässt, lassen sich Fehlersituationen nicht ausschließen. Ruft ein Client beispielsweise zu oft Release() auf, kann dies durch Freigabe des Objekts zu ungültigen Zeigern in anderen Clients führen.

15 Beispiel Addref wird automatisch bei der Erzeugung eines Objektes aufgerufen Release wird automatisch bei der Löschung eines Objektes aufgerufen class CBeispielObjekt : Iunknown { private: ULONG cRef;} CBeispielObjekt::AddRef(void){  //AddRefULONG return ++cRef; } CBeispielObjekt::Release(void){ //ReleaseULONG cRef--; if (cRef == 0) { delete this; } return cRef;

16 Klassen Klassen sind von einer oder mehreren Schnittstellen abgeleitet
Aufgaben: Interfaces implementieren Memberfunktionen implementieren eindeutige GUID - „Class Identifier" (CLSID) 3.3 DCOM- Klassen Vergleichen lassen sich COM- Schnittstellen mit abstrakten Klassen in C++, deren Methoden allesamt als "pure virtual" spezifiziert sind. Java-Schnittstellen entsprechen ihren Pendants in Microsoft COM weitestgehend, weshalb Java eine ideale Plattform für die COM- Programmierung darstellt. COM- Klassen sind von ein oder mehreren Schnittstellen abgeleitet. COM- Objekte wiederum lassen sich als Instanzen von COM- Klassen verstehen. Eine DCOM- Klasse hat die Aufgabe, ein oder mehrere Interfaces zu implementieren. Von fundamentaler Bedeutung ist nun, dass sie sich genau an den vordefinierten Kontrakt hält, da die Clients darauf angewiesen sind. Desweiteren muss jede Memberfunktion eines angebotenen Interfaces auch implementiert werden, da die Clients davon ausgehen auf jede Funktion zugreifen zu können. Ähnlich wie die Interfaces mit ihren IIDs besitzen auch die DCOM- Klassen eine eindeutige GUID. Diese heißt bei ihnen allerdings „Class Identifier" (CLSID). Um eine Instanz eines Objekts erzeugen zu können, besitzt jede DCOM- Klasse ein eigenes Interface, die sogenannte „Class Factory". Dieses wird angesprochen, wenn eine Instanz erzeugt werden soll, generiert diese dann und liefert eine Referenz auf diese Instanz an den Client zurück. Gegenwärtig muss auch die „Class Factory“ für jede DCOM- Klasse von Hand implementiert werden. Zur besseren Handhabbarkeit können DCOM- Klassen noch in Kategorien eingeteilt werden. In diesen Kategorien werden Klassen zusammengefasst, die alle Interfaces einer festvorgegebenen Menge von Interfaces unterstützen. Das hat den Vorteil, schneller fündig zu werden, wenn ein bestimmtes Interface gesucht wird. Neben den verlangten Interfaces kann eine solche Klasse aber auch noch andere Interfaces unterstützen und somit auch zu anderen Kategorien gehören. Um eine Kategorie eindeutig identifizieren zu können, besitzen sie wiederum ein GUID, die CATID (Category Identifier).

17 Registry alle wichtigen Informationen zu den COM- Klassen
friendly name, in diesem Fall “Tail Rotor Simulator” Servertype, hier InprocServer32 Ort des Servers: „C:\Helicopter\TailRotor.dll“ Welche Threads unterstützt werden, hier „Apartment Threads“ ProgID: ist nicht eindeutig ist TypeLib: Die TypeLibraries enthalten Typinformationen über die Komponente, ihre Interfaces, ihre Methoden. Sie liegen als Binärfile vor 3.4 Registry Eine zentrale Rolle in DCOM spielt die Registry von Windows. Das liegt daran, dass in ihr alle wichtigen Informationen zu den DCOM- Klassen gespeichert sind und somit erst das Auffinden von DCOM- Servern ermöglicht wird. Für remote Server ist der Application Identifier (AppID) wichtig, da er dessen Informationen beinhaltet. Um einen remote Zugriff durchführen zu können, muss die gewünschte DCOM- Klasse auch in der lokalen Registry registriert sein. Die einzelnen Klassen sind indiziert durch ihre CLSID abgespeichert, was gut in dem unten abgebildeten Auszug aus der Registry zu sehen ist. Als obersten Key gibt es dort den Key „HKEY_CLASSES_ROOT". Unter diesem Key stehen die eigentlichen Klassen, indiziert durch ihre CLSID, die im Format allerdings recht lang und kompliziert ist (Nachteilig vor allem, weil sie in dieser Form auch direkt im Code verwendet wird.). Unter der CLSID folgen dann die weiteren Keys, die die Informationen beherbergen: ·                    friendly name, in diesem Fall “Tail Rotor Simulator” ·                    Servertype, hier InprocServer32 ·                    Ort des Servers: „C:\Helicopter\TailRotor.dll“ ·                    Welche Threads unterstützt werden, hier „Apartment Threads“ ·                    ProgID: Diese kann statt der CLSID verwendet werden, hat aber den Nachteil, dass sie nicht eindeutig ist ·                    TypeLib: Die TypeLibraries enthalten Typinformationen über die Komponente, ihre Interfaces, ihre Methoden. Sie liegen als Binärfile vor und dienen somit dazu Programmiersprachenunabhängigkeit zu erreichen. Bild 9

18 DCOM TCP : Transmission Control Protocol Erweiterung des COMs
Bearbeitung der Objekte,die sich auf verschiedenen Rechnern befinden Aufsetzt auf RPC(Remote Procedure Call) – Verfahren unterstützt TCP : Transmission Control Protocol UDP : User Data Protocol IPX : Internetwork Packet Exchange 3. DCOM Beim DCOM handelt es sich um eine Erweiterung des COM dahingehend, dass es nun COM Clients möglich ist Objekte zu bearbeiten die sich auf verschiedenen Rechnern befinden. Ermöglicht wird dies durch Nutzung des weiter oben bereits erwähnten RPC – Verfahrens. Da DCOM auf dem RPC – Verfahren aufsetzt war es möglich, zahlreiche verbindungsorientierte und verbindungslose Netzwerkprotokolle, wie etwa TCP, UDP,IPX, zu unterstützen.

19 Serverarten Klasse jedes COM – Objektes liegt in binärer Form (entweder EXE oder DLL) vor und wird als COM-Server bezeichnet in-process-server Server die als DLL ( Dynamic-Linked-Library ) vorliegen werden direkt in den Adressraum des Clients geladen hohe Geschwindigkeit out-process-server (.EXE : Programm) ein eigener Adressraum Die reservierten Ressourcen werden zwischen den die Dienste des Servers in Anspruch nehmenden Clients aufgeteilt 2.4. COM - Server Wie oben bereits erwähnt liegt die Klasse jedes COM - Objektes in binärer Form (entweder EXE oder DLL) vor und wird als COM - Server bezeichnet. Server die als DLL vorliegen werden direkt in den Adressraum des Client geladen. Solche Server werden als in-process-server bezeichnet, da sie keinen eigenen Adressraum, sondern den Adressraum des Client benutzen. Dies bedeutet auch, dass jeder Client "Besitzer" aller durch den Server reservierter Ressourcen ist. Bild3 : IN-PROCESS-SERVER Ein Vorteil dieser in-process-server liegt in ihrer hohen Geschwindigkeit, resultierend aus der Tatsache, dass zum Zugriffe auf den Code des Servers keine Taskumschaltung erfolgen muss, da der Adressraum innerhalb des Client liegt. Die COM – Server die als .EXE Version erstellt wurden werden als out-process-server bezeichnet, da sie einen eigenen Adressraum besitzen sowie eigene Ressourcen reservieren können. Bild4 : OUT-PROCESS-SERVER Die reservierten Ressourcen werden zwischen den die Dienste des Servers in Anspruch nehmenden Clients aufgeteilt. 3.7 Kommunikation zwischen Client und Server

20 Ablauf de Kommunikation
Proxy exakt dieselben Schnittstellen wie das ihm zugeordnete COM- Objekt Clients verweisen auf die Schnittstellenimplementierung des Proxy Einrichtung eines Kommunikationskanals Konvertierung der Parameter (Marshaling) Weiterleitung der Anfrage Rückmeldung der Ergebnisse Stub Verbindungsaufbau mit dem Client Empfang von Aufrufen Entpacken von Parametern (Demarshaling) Aufruf des COM- Objekts (Dispatching). LPCs (Local Procedure Calls) - Kommunikation von Proxies und Stubs auf derselben Maschine RPCs (Remote Procedure Calls ) - Kommunikation über Maschinengrenzen Damit allein ist es aber noch nicht getan. Würden in einer Tabelle die Methodenzeiger direkt auf die Implementierung der Schnittstelle im COM- Objekt verweisen, wäre lediglich ein Zugriff auf lokale Objekte möglich, deren Realisierung in Gestalt dynamisch ladbarer Bibliotheken (DLLs) vorliegt – diese werden zur Laufzeit dynamisch in den Adressraum des Client eingebunden. Mit Hilfe sogenannter Proxies lässt sich diese Einschränkung jedoch umgehen. Möchte ein Client auf ein Objekt zugreifen, das sich in einem anderen Prozess befindet und zum Beispiel als ausführbares Programm vorliegt, lassen sich sogenannte Proxies einsetzen. Ein Proxy implementiert dabei exakt dieselben Schnittstellen wie das ihm zugeordnete COM- Objekt, liegt aber im Gegensatz zu dem eigentlichen Zielobjekt als dynamisch ladbare Bibliothek vor. Die Methodenzeiger des Clients verweisen nicht mehr auf die eigentliche Schnittstellenimplementierung des COM- Objekts, sondern stattdessen auf die Schnittstellenimplementierung des Proxy- Objekts. Bei einem Methodenaufruf erfolgt dementsprechend – für den Aufrufer unsichtbar - der Aufruf einer Methode im Proxy statt des direkten Aufrufs der eigentlichen Methodenimplementierung. Aufgabe des Proxy ist die Einrichtung eines Kommunikationskanals mit dem jeweiligen COM- Objekt, die Konvertierung der Parameter (Marshaling), die Weiterleitung der Anfrage und die Rückmeldung der Ergebnisse. Die Kommunikation des Proxy mit dem COM- Objekt erfolgt ebenfalls nicht direkt im COM- Objekt sondern über ein vorgeschaltetes Stub- Objekt. Ein Stub- Objekt befindet sich im Adressraum des COM- Objekts und tritt diesem gegenüber als Client in Erscheinung. Aufgabe des Stubs ist der Verbindungsaufbau mit dem Client, der Empfang von Aufrufen, das Entpacken von Parametern (Demarshaling) und der eigentliche Aufruf des COM- Objekts (Dispatching). Für die Kommunikation von Proxies und Stubs auf derselben Maschine verwendet COM LRPCs (Lightweigh Remote Procedure Calls), die auf gemeinsamen Speicher basieren und damit sehr gute Performanz aufweisen. Für Kommunikation über Maschinengrenzen finden entfernte Methodenaufrufe (RPCs) Verwendung. Wie bereits erläutert: All dies geschieht transparent für den Programmierer. Erwähnenswert ist in diesem Zusammenhang ein ungeschriebenes COM- Gesetz. Stellt ein Entwickler eine COM- Schnittstelle, etwa IMyInterface bereit, bleibt diese Schnittstelle für alle Zukunft unveränderbar. Möchte der Entwickler Modifikationen vornehmen, muss er dazu eine neue Schnittstelle definieren, zum Beispiel IMyInterface2. Dadurch lässt sich sicherstellen, dass sich Änderungen niemals auf existierende Clients auswirken können. In einer neuen Version eines COM- Objekts würden die Entwickler beide Schnittstellen, IMyInterface und IMyInterface2 anbieten. Während bisherige Client nach wie vor über IMyInterface auf das Objekt zugreifen würden, könnten jüngere Clients die neue Schnittstelle benutzen. Von zentraler Bedeutung für den Kontrakt ist die eindeutige Identifizierbarkeit eines Interfaces. Daraus folgt, dass jede neuere Version eines Interfaces auch eine neue IID besitzen muss. Eine Versionskontrolle für ein Interfaces ist nicht fest vorgegeben, wird aber meistens durch das Anfügen einer Zahl an den Interfacenamen realisiert. Angesichts der Tatsache, dass es mehrere Versionen eines Interfaces geben kann, folgt, dass ein Objekt mehrere Interfaces unterstützen muss, um die Stabilität von Clients zu gewährleisten, die nur ältere Versionen kennen. Bei der Kommunikation ist zu bemerken, dass es drei verschiedene Arten von Servertypen gibt. Zunächst ist da der In-Proc Server. Dieser Server liegt als Dynamic- Linked- Library (DLL) vor. Zur Laufzeit wird er im selben Prozess wie der Client ausgeführt und besitzt somit den gleichen Adressraum. Ein Zugriff auf den Server ist somit recht unproblematisch. Bei „Local Server" und „Remote Server" dies schon etwas schwieriger. Diese laufen nämlich nicht im selben Prozess wie der Client ab, sondern besitzen ihren eigenen Prozess. Somit besitzen sie aber auch unterschiedliche Adressräume. Aus diesem Grund muss dafür gesorgt werden, dass Parameter, die zwischen Client und Server ausgetauscht werden, in ein Standardformat gebracht werden. Dieser Vorgang nennt sich „Marshalling“. Das Marshalling geschieht in DCOM durch Proxy und Stub. Diese liegen wie der In-Proc Server als DLLs vor. Das ist wichtig, da sie somit zur Laufzeit den selben Adressraum wie der Client besitzen und dieser einfach einen Zugriff durchführen kann, so als ob der Server im selben Prozess wäre. Die DLL-Dateien werden erzeugt, indem die Interfaces des Servers in der „Interface Definition Language“ (IDL) beschrieben werden und anschließend mit dem Microsoft IDL-Compiler (MIDL) übersetzt werden. Die IDL orientiert sich, wie die GUIDs, an der DCE Spezifikation. Der Aufruf einer Memberfunktion geht so vonstatten, dass der Client den Aufruf so durchführt, als läge der Server im gleichen Adressraum. In Wirklichkeit geht der Aufruf aber an den Proxy. Letzterer führt dann das Marshalling durch und sendet die Daten an den Stub des Servers weiter. Dieser führt ein Unmarshalling durch und reicht die Daten an den Server weiter, der auf diesen Daten die gewünschte Berechnung ausführt. Auf dem Rückweg verhalten sich Stub und Proxy genau umgekehrt, d.h. der Stub verpackt die Daten und der Proxy entpackt sie wieder. Durch dieses Verfahren ist eine Plattformunabhängigkeit gewährleistet. Bild 10 Nun aber zu den beiden anderen Serverarten, dem Local Server und dem Remote Server. Beide liegen in Normalfall als Executeables vor. Der Local Server befindet sich in einem eigenen Prozess auf der lokalen Maschine. Der Austausch der Daten zwischen Client Prozess und Server Prozess findet mittels dem sogenannten Local Procedure Call (LPC) statt. Dieser orientiert sich wiederum an der DCE Spezifikation. Beim Remote Server kommt dagegen der Remote Procedure Call (RPC) zum Einsatz. Der Vorteil der von DCOM verwendeten Kommunikationsstruktur liegt in der einfachen Erzeugung von Proxy und Stub. Diese führen dann das Marshalling bzw. Unmarshalling automatisch durch, ohne dass sich der Client damit auseinander setzen muss. Er greift auf den Server zu, als ob er im gleichen Prozess liegen würde. Beim eigentlichen Verbindungsaufbau nimmt DCOM im Normalfall dem Client die meiste Arbeit ab. Der Client braucht nur die gewünschte CLSID an DCOM zu übergeben. Der lokale Service Control Manager (SCM) von DCOM sucht dann die CLSID in der lokalen Registry. Wird er dort fündig, führt er geeignete Maßnahmen zur Aktivierung des Servers durch. Liegt der Server lokal, wird er einfach aktiviert. Schwieriger wird dies bei einem Remote Server. Hier muss sich der lokale SCM erst mit dem SCM auf der Remote Maschine in Verbindung setzen, auf der der Server liegt. Dieser SCM aktiviert dann den gewünschten Server. Bei der Aktivierung wird über die Class Factory eine Instanz des Servers erzeugt. Ist der Server aktiviert, baut der SCM eine Verbindung zwischen Client und Server auf. Anschließend kann der Server eine Referenz auf das gewünschte Objekt zurückgeben. Dieses Verfahren ist für den Client transparent, weil es für ihn ohne Bedeutung ist, wo der Server sich befindet und wie die Verbindung aufgebaut werden muss. Da es in manchen Fällen notwendig sein kann, dass der Client einen bestimmten Server ansprechen muss, besteht in DCOM die Möglichkeit dieses zu tun.

21 Ablauf der Kommunikation(2)
Client Process Local Server Process In-Proc-Server In Proc Object Local Object Local Server Com Stub LPC Client Application COM Local Object Proxy Remote Server Process Remote Server Com Stub Remote Object IMoniker Ein Problem bei DCOM ist es, dass es keine Objektidentifikation gibt. Als Beispiel sei erwähnt, dass es keine Möglichkeit gibt eine Verbindung, die einmal unterbrochen war, wieder so herzustellen, dass das Objekt wieder im selben Zustand ist wie vor der Unterbrechung. Als Lösung existiert nur die Möglichkeit der sogenannten Monikers. Dieses Interface ermöglicht es, einem Objekt einen symbolischen Namen zuzuweisen. Ein Client kann über diesen Namen dann auf das Objekt zugreifen und es ist gewährleistet, dass es eine eindeutige Objektidentifikation gibt. Durch dieses Interface ist es somit auch möglich persistente Objekte zu erzeugen. Um diese Funktionalität zu erreichen, stellt das Interface Methoden zum Speichern und Laden eines Zustands eines Objekts zur Verfügung. Desweiteren muss es aber auch in der Lage sein, ein neues Objekt erzeugen zu können, da z.B. bei einer Unterbrechung einer Verbindung das Objekt unter Umständen auch gelöscht wird. Auch für dieses Zweck stellt das Interface Funktionen bereit. Dieser Vorgang der Erzeugung muss allerdings explizit durch den Client erfolgen. Remote Object Proxy RPC

22 Imoniker Es gibt keine Möglichkeit eine unterbrochene Verbindung wieder herzustellen Zuweisung eines symbolischen Name Eine eindeutige Objektidentifikation Speichern und Laden eines Zustands eines Objekts ein neues Objekt erzeugen Vorgang der Erzeugung muss explizit durch den Client erfolgen IMoniker Ein Problem bei DCOM ist es, dass es keine Objektidentifikation gibt. Als Beispiel sei erwähnt, dass es keine Möglichkeit gibt eine Verbindung, die einmal unterbrochen war, wieder so herzustellen, dass das Objekt wieder im selben Zustand ist wie vor der Unterbrechung. Als Lösung existiert nur die Möglichkeit der sogenannten Monikers. Dieses Interface ermöglicht es, einem Objekt einen symbolischen Namen zuzuweisen. Ein Client kann über diesen Namen dann auf das Objekt zugreifen und es ist gewährleistet, dass es eine eindeutige Objektidentifikation gibt. Durch dieses Interface ist es somit auch möglich persistente Objekte zu erzeugen. Um diese Funktionalität zu erreichen, stellt das Interface Methoden zum Speichern und Laden eines Zustands eines Objekts zur Verfügung. Desweiteren muss es aber auch in der Lage sein, ein neues Objekt erzeugen zu können, da z.B. bei einer Unterbrechung einer Verbindung das Objekt unter Umständen auch gelöscht wird. Auch für dieses Zweck stellt das Interface Funktionen bereit. Dieser Vorgang der Erzeugung muss allerdings explizit durch den Client erfolgen.

23 Sicherheitsmechanismen
activation security legt fest (und überwacht) wer beispielsweise COM Server starten darf call security dient der Regulierung des Zugriffs auf die Funktionen des Interfaces eines COM – Objektes Um überhaut Zugriff auf die benötigten Dienste zu bekommen muss sich der Benutzer erst authentifizieren 6 Authentifizierungsebenen z.B. RPC_C_AUTHN_LEVEL_NONE Keine Authentifizierung nötig Festlegung der Zugriffsrechte auf Schnittstellen Festlegung der Zugriffsrechte auf Ressourcen 3.5 Sicherheitsmechanismen Da DCOM den Zugriff auf „fremde“ Rechner sowie von „fremden“ Rechner zulässt mussten Sicherheitsmechanismen eingebaut werden , die die „unzweckmäßige“ Verwendung von Ressourcen verhindern. Zu diesem Zweck besitzt DCOM zwei Sicherheitsmechanismen: activation security und call security genannt. Mittels des activation security Mechanismus wird festgelegt (und überwacht) wer beispielsweise COM Server starten darf, der call security Mechanismus dient der Regulierung des Zugriffs auf die Funktionen des Interfaces eines COM – Objektes. Um überhaut Zugriff auf die benötigten Dienste zu bekommen muss sich der Benutzer erst authentifizieren. In folgender Tabelle befinden sich die durch DCOM unterstützten Authentication Levels : RPC_C_AUTHN_LEVEL_NONE Keine Authentifizierung nötig RPC_C_AUTHN_LEVEL_CONNECT Authentifizierung bei Verbindungsaufbau RPC_C_AUTHN_LEVEL_CALL Authentifizierung sobald der Server einen RPC Call empfängt RPC_C_AUTHN_LEVEL_PKT Überprüft, dass alle Daten auch vom erwarteten Client sind RPC_C_AUTHN_LEVEL_INTEGRITY Wie oben + Überprüfung, dass Daten nicht modifiziert wurden RPC_C_AUTHN_LEVEL_PRIVACY alle obigen + Verschlüsselung Nachdem die Authentifizierung des Clients abgeschlossen ist werden die zur Nutzung des COM - Objektes vorgesehenen Zugriffsrechte auf dessen Schnittstellen, sowie die Zugriffsrechte des Objektes auf die Ressourcen (für den jeweiligen Client) festgelegt. Die folgenden Tabelle RPC_C_IMP_LEVEL_ANONYMOUS Der Client bleibt gegenüber dem Server anonym. RPC_C_IMP_LEVEL_IDENTIFY Der Server legt die Zugriffsrechte jedes Clients auf das Objekt. RPC_C_IMP_LEVEL_IMPERSONATE Der Server legt für jeden Client fest, auf welche Ressourcen das COM - Objekt Zugriff hat. RPC_C_IMP_LEVEL_DELEGATE Der Server ermöglicht es dem Client außer den lokalen Ressourcen auch Anfragen an andere Server zu stellen.;

24 Kommunikationsaufbau
Informationen über einen "entfernten" COM - Server Struktur COSERVERINFO typedef struct _COSERVERINFO { DWORD dwReserved1; LPWSTR pwszName; COAUTHINFO *pAuthInfo;  Authentication - Einstellungen DWORD dwReserved2; } COSERVERINFO; pwszName    : zeigt auf den Namen des zu benutzenden Computers pAuthInfo    : Zeiger auf eine COAUTHINFO - Struktur, legt activation security fest 3.6 Kommunikationsaufbau In diesem Abschnitt werden die für die programmiertechnische Realisierung einer Client/Server Kommunikation notwendigen Strukturen und Funktionen erläutert. Um Informationen über einen "entfernten" COM - Server speichern zu können wird die Struktur COSERVERINFO verwendet. typedef struct _COSERVERINFO { DWORD dwReserved1; LPWSTR pwszName; COAUTHINFO *pAuthInfo; DWORD dwReserved2; } COSERVERINFO; dwReserved1     : reserviert für zukünftige Erweiterung pwszName    : zeigt auf den Namen des zu benutzenden Computers pAuthInfo    : Zeiger auf eine COAUTHINFO - Struktur, legt activation security fest dwReserved2         : reserviert für zukünftige Erweiterung Die COAUTHINFO - Struktur enthält die Authentication - Einstellungen die für einen Aufruf des Clients an den Server benötigt werden. typedef struct _COAUTHINFO { DWORD dwAuthnSvc; DWORD dwAuthzSvc; LPWSTR pwszServerPrincName; DWORD dwAuthnLevel; DWORD dwImpersonationLevel; COAUTHIDENTITY * pAuthIdentityData; DWORD dwCapabilities; } COAUTHINFO;   dwAuthnSvc : legt die Authentication - Service fest, enthält einen der oben aufgeführten RPC_C_AUTHN_LEVEL_XXX - Werte dwAuthzSvc : enthält einen der RPC_C_AUTHZ_xxx - Werte, legt die zu benutzenden authorization service fest pwszServerPrincName : NULL dwAuthnLevel : legt den zu benutzenden Authentication - Level fest : RPC_C_AUTHN_LEVEL_xxx dwImpersonationLevel : muß RPC_C_IMP_LEVEL_IMPERSONATE. sein pAuthIdentityData : enthält einen Zeiger auf eine COAUTHIDENTITY - Struktur dwCapabilities : muß EOAC_NONE sein Die COAUTHIDENTITY - Struktur repräsentiert einen Benutzernamen und ein Passwort. typedef struct _COAUTHIDENTITY { USHORT *User; ULONG UserLength; USHORT *Domain; ULONG DomainLength; USHORT *Password; ULONG PasswordLength; ULONG Flags; } COAUTHIDENTITY; User : Benutzername UserLength : Länge des Benutzernamens Domain : enthält den Domain oder Arbeitsgruppennamen DomainLength : Länge des Namens Password : ... PasswordLength : ... Flags : signalisiert, ob es sich bei den Strings um ANSI oder Unicode handelt, SEC_WINNT_AUTH_IDENTITY_ANSI oder SEC_WINNT_AUTH_IDENTITY_UNICODE.

25 Kommunikation Erzeugen der Objekte
CoGetClassObject – finden des Objektes CoCreateInstance - erzeugen des Objektes Aktivierung des Objektes durch Service Control Manager.  CoCreateInstanceEx mehrere Schnittstellenzeiger auf dasselbe Objekt Server, der Objekte nach außen zur Verfügung stellt, bezeichnet DCOM als Objektexporteur Client Server (Objekt) Proxy Stub Um COM - Objekte zu erzeugen werden die Funktionen CoGetClassObject und CreateInstance verwendet. Voraussetzung für die Erzeugung eines Objektes ist die Existenz einer dem Objekt entsprechenden CLSID in der System - Registry. STDAPI CoGetClassObject( REFCLSID rclsid, //CLSID des Objektes DWORD dwClsContext, //Context wie der Code des Objektes auszuführen ist // zur Aktivierung durch entfernten Server :CLSCTX_REMOTE_SERVER COSERVERINFO * pServerInfo, //zeigt auf den Rechner auf dem das Objekt instanziert werden soll REFIID riid, // Referenz auf den Identifizierer des Interfaces LPVOID * ppv //Address der Variable, die auf das zurückgesendete // Interface zeigt ); Die Funktion CreateInstance erzeugt ein uninitialisiertes Objekt. HRESULT CreateInstance( IUnknown * pUnkOuter, REFIID riid, void ** ppvObject ); Die Aktivierung des Zielobjekts erfolgt unter Kooperation der jeweiligen Service Control Manager. Hierbei handelt es sich um Systemprozesse, die bei API- Aufrufen wie zum Beispiel CoCreateInstance dazu dienen, um die Windows- Registry nach dem gewünschten Objekt zu durchsuchen, dieses gegebenfalls zu aktivieren und den entsprechenden Schnittstellenzeiger an den Aufrufer zurückzuliefern (siehe Bild 11). Bild 11:Auf jedem Rechner in einem COM- System gibt es einen Service Control Manager. Dieser Systemprozess ist dafür verantwortlich, bei der Instanziierung von Schnittstellen z.B. durch CoCreateInstance() die lokale Registry nach dem gewünschten Objekt zu durchforsten und dieses zu aktivieren. Befinden sich Client und Objekt auf separaten Maschinen, kooperieren die beteiligten SCMs. Aus Performanzgründen stellt DCOM zusätzliche API- Funktionen bereit. Beispielsweise CoCreateInstanceEx, um gleichzeitig mehrere Schnittstellenzeiger auf dasselbe Objekt zu erhalten. Dadurch ist der Programmierer nicht mehr gezwungen, mehrere QueryInterface- Aufrufe durchzuführen, sofern er mehrere Schnittstellen auf ein Objekt benötigt. Jeden Server, der Objekte nach außen zur Verfügung stellt, bezeichnet DCOM als Objektexporteur. Folgt der Programmierer dem sogenannten Apartment-Modell für Multithreading, so kann ein DCOM- Objekt dabei nur in einem Thread ablaufen. Bei Verwendung des "Free Threading"- Modells darf die Verarbeitung eines DCOM- Objekts sich auch über mehrere Threads erstrecken. Falls sich ein Server als Objektexporteur betätigt, ordnet ihm das Laufzeitsystem als eindeutigen Identifikator den sogenannten OXID (Object Exporter Identifier) zu. Um auf ein Server-Objekt zuzugreifen, muss ein Client den jeweiligen OXID des für das Objekt verantwortlichen Objektexporteurs spezifizieren. Auf jeder Maschine mit installiertem DCOM- Laufzeitsystem ist ein sogenannter OXID- Zuordungsprozess damit beauftragt, die entsprechenden Abbildungen von OXIDs auf die eigentliche Bindungsinformation durchzuführen (siehe Bild13). Service Control Manager Service Control Manager

26 Kommunikation (2) 1 CoCreateInstance() aufrufen
2 in Registry nachschauen (lokal) 3 in Registry nachschauen und Objekt aktivieren (entfernter Rechner) 4 Schnittstellenzeiger zurückliefern 5 Schnittstellenzeiger benutzen Bild12: Beim Aufruf von CoCreateInstance() überprüft das Laufzeitsystem anhand des Klassenidentifikators (CLSID) in der Registry, wo sich die Implementierung des Objekts befindet. Falls dieses auf einen entfernten Rechner liegt, wird es dort von COM aktiviert und der gewünschte Schnittstellenzeiger an den Aufrufer zurückgeliefert.

27 Wiederverwendung von Objekten
keine Implementationsvererbung sondern Interfacevererbung zwei Arten von Wiederverwendung in DCOM Containment/Delegation Aggregation Es gibt jeweils ein inneres und ein äußeres Objekt Gemeinsam ist beiden, Sprachunabhängigkeit, da die wiederverwendeten Objekte als Binärcode vorliegen können IUnknown Äußeres Objekt C B IUnknown A Aggregation Äußeres Objekt 3.1 Die DCOM-Architektur Ziel des von Microsoft entwickelten Standards ist es, dass Schreiben von wiederverwendbaren Komponenten und verteilten Anwendungen zu ermöglichen. Die Grundlage dieses Standards ist eine sogenannte Client-Server-Architektur. Diese Architektur wurde als ein objektbasierter Binärstandard definiert. Daraus ergibt sich der große Vorteil einer Sprachunabhängigkeit, was das Verwenden von Komponenten, die in einer beliebigen Sprache geschrieben sind, wesentlich vereinfacht. Die einzige Einschränkung dieser Sprachunabhängigkeit ergibt sich dadurch, dass ein verwendeter Compiler den Binärstandard unterstützen muss. Im Moment unterstützen hauptsächlich von Microsoft entwickelte Compiler den Standard (z.B. Visual Basic, Visual C++, Java, ...), aber auch Borland (z.B. Delphi, ...) ist auf eine Unterstützung bedacht. Insofern gibt es aber für alle wichtigen Programmiersprachen einen unterstützenden Compiler, mit weiter steigender Anzahl. Die Kommunikation zwischen Client und COM- Objekt findet über die sogenannten Interfaces statt. Der Client erhält dabei eine Referenz auf ein Interface des COM- Objekts. Solch ein Objekt kann, wie im nachfolgenden Bild zu sehen, mehrere Interfaces unterstützen. Für den Client ist es unbedeutend, wo das eigentlich Objekt liegt, d.h. ob es auf der „Local Machine" oder auf einer „Remote Machine" liegt. Das liegt hauptsächlich daran, dass DCOM von dem eigentlichen Zugriff abstrahiert und somit den Zugriffsmechanismus verbirgt. Bild 7 3.2 Interfaces Jedes Interface definiert einen sowohl für Client als auch Server bindenden Kontrakt zwischen diesen beiden, wobei es sich als Menge semantisch verwandter Funktionen darstellt. Interfaces sind von einander unabhängig. Das Verhalten der einzelnen Memberfunktionen eines Interfaces ist dabei nicht abhängig von der zu Grunde liegenden Implementierung, sondern nur abhängig von dem fest vorgegebenen Kontrakt. Das liegt daran, dass sich ein Client voll auf das jeweilige Interface, bzw. die jeweilige Funktion verlassen muss und Probleme bekommt, falls die gewünschte Funktionalität nicht den Erwartungen entspricht. Der Zugriff auf einen Server ist ausschließlich über Memberfunktionen möglich, und dieser geschieht nur indirekt über eine Referenz, die der Client von dem jeweiligen Server erhält. Dies führt dazu, dass der Client nicht direkt auf Zustandsinformationen des Objektes zugreifen, bzw. diese verändern kann. Zu erwähnen ist, dass es in DCOM keine Implementationsvererbung gibt, sondern nur eine Interfacevererbung. D.h. es müssen andere Methoden angewendet werden, um eine einmal geschriebene Implementierung wiederverwenden zukönnen. 3.8 Wiederverwendung von Objekten Um sinnvoll mit DCOM arbeiten zu können, ist es unerlässlich einmal implementierte Komponenten wiederverwenden zu können, da sonst der Aufwand zu hoch wäre. Da es in DCOM aber keine Implementationsvererbung gibt, muss dies anders organisiert werden. Es gibt zwei Arten von Wiederverwendung in DCOM, wie unten auf dem Bild zu sehen ist. Das ist einmal „Containment/Delegation" und einmal „Aggregation". Containment/Delegation Bei beiden Methoden gibt es jeweils ein inneres und ein äußeres Objekt. Beim Containment werden die Interfaces des inneren Objektes, die wiederverwendet werden sollen, vom äußeren Objekt nochmal neu implementiert. Innerhalb dieser Neuimplementierung werden dann die Interfaces des inneren Objektes aufgerufen. Somit greift der Client nicht direkt auf das wiederverwendete Interface zu. Außerdem besteht bei dieser Methode auch noch die Möglichkeit, neue Funktionalität dem Interface hinzuzufügen. Das Verhältnis zwischen innerem und äußerem Objekt entspricht bei diesem Verfahren einem Client-Server-Verhältnis. A B B C C Containment/Delegation

28 Containment / Delegation
die Interfaces des inneren Objektes werden vom äußeren Objekt neu implementiert Innerhalb dieser Neuimplementierung werden dann die Interfaces des inneren Objektes aufgerufen Somit greift der Client nicht direkt auf das wiederverwendete Interface zu die Möglichkeit neue Funktionalität dem Interface hinzuzufügen Das Verhältnis entspricht einem Client-Server-Verhältnis Containment/Delegation Bei beiden Methoden gibt es jeweils ein inneres und ein äußeres Objekt. Beim Containment werden die Interfaces des inneren Objektes, die wiederverwendet werden sollen, vom äußeren Objekt nochmal neu implementiert. Innerhalb dieser Neuimplementierung werden dann die Interfaces des inneren Objektes aufgerufen. Somit greift der Client nicht direkt auf das wiederverwendete Interface zu. Außerdem besteht bei dieser Methode auch noch die Möglichkeit, neue Funktionalität dem Interface hinzuzufügen. Das Verhältnis zwischen innerem und äußerem Objekt entspricht bei diesem Verfahren einem Client-Server-Verhältnis.

29 Aggregation Direkter Zugriff auf die Interfaces des inneren Objekts
Problem: Memberfunktion Queryinterface des inneren Objektes kennt die Interfaces des äußeren Objektes nicht Lösung Einführung Zweier IUnknown Interfaces Delegating Iunknown IUnkown- Interface des inneren Objektes eine Referenz auf das IUnknown- Interface des äußeren Objektes Nondelegating Iunknown Das Nondelegating IUnknown wird benötigt, wenn nicht über ein äußeres Objekt auf das innere Objekt zugegriffen wird. In diesem Fall werden Anfragen von dem inneren Objekt selbst bearbeitet. ein Objekt muss schon bei der Implementierung auf Aggregation ausgelegt werden (Implementierung von Delegating und Nondelegating IUnknown). Aggregation Im Gegensatz dazu erhält der Client bei der Aggregation direkten Zugriff auf die Interfaces des inneren Objekts und kommuniziert mit diesem direkt. Dies hört sich zwar einfach an, ist aber kompliziert zu implementieren. Aufgrund der Tatsache, dass mit der Referenz eines Interfaces alle anderen Interfaces eines Objektes erhalten werden müssen und dies mit dem Standardinterface IUnknown nicht möglich ist (Memberfunktion Queryinterface des inneren Objektes kennt die Interfaces des äußeren Objektes nicht und kann somit nicht nach diesen gefragt werden), ergibt sich, dass einige Änderungen durchgeführt werden müssen. Die Lösung dieses Problems ist die Einführung Zweier IUnknown Interfaces, einmal dem Delegating Iunknown und einmal dem Nondelegating IUnknown. Das Delegating IUnknown implementiert die drei Memberfunktionen des IUnkown- Interfaces des inneren Objektes. Dabei erhält es auch eine Referenz auf das IUnknown- Interface des äußeren Objektes, um Anfragen an das äußere Objekt delegieren zu können. Das Nondelegating IUnknown wird benötigt, wenn nicht über ein äußeres Objekt auf das innere Objekt zugegriffen wird. In diesem Fall werden Anfragen von dem inneren Objekt selbst bearbeitet. Wie zu sehen ist, muss im Gegensatz zu Containment einiger Aufwand betrieben werden, um Aggregation zu implementieren, außerdem muss ein Objekt schon bei der Implementierung auf Aggregation ausgelegt werden (Implementierung von Delegating und Nondelegating IUnknown). Gemeinsam ist beiden, dass sie unabhängig von der Implementierung zugrundeliegenden Programmiersprache sind, da die wiederverwendeten Objekte als Binärcode vorliegen können. Dies ist ein großer Vorteil dieser Art der Wiederverwendung gegenüber der Implementationsvererbung und damit auch gegenüber CORBA, wo es solch eine Unabhängigkeit nicht gibt.

30 Aggregation IUnknown Äußeres Objekt A IUnknown B C Aggregation
Im Gegensatz dazu erhält der Client bei der Aggregation direkten Zugriff auf die Interfaces des inneren Objekts und kommuniziert mit diesem direkt. Dies hört sich zwar einfach an, ist aber kompliziert zu implementieren. Aufgrund der Tatsache, dass mit der Referenz eines Interfaces alle anderen Interfaces eines Objektes erhalten werden müssen und dies mit dem Standardinterface IUnknown nicht möglich ist (Memberfunktion Queryinterface des inneren Objektes kennt die Interfaces des äußeren Objektes nicht und kann somit nicht nach diesen gefragt werden), ergibt sich, dass einige Änderungen durchgeführt werden müssen. Die Lösung dieses Problems ist die Einführung Zweier IUnknown Interfaces, einmal dem Delegating Iunknown und einmal dem Nondelegating IUnknown. Das Delegating IUnknown implementiert die drei Memberfunktionen des IUnkown- Interfaces des inneren Objektes. Dabei erhält es auch eine Referenz auf das IUnknown- Interface des äußeren Objektes, um Anfragen an das äußere Objekt delegieren zu können. Das Nondelegating IUnknown wird benötigt, wenn nicht über ein äußeres Objekt auf das innere Objekt zugegriffen wird. In diesem Fall werden Anfragen von dem inneren Objekt selbst bearbeitet. Wie zu sehen ist, muss im Gegensatz zu Containment einiger Aufwand betrieben werden, um Aggregation zu implementieren, außerdem muss ein Objekt schon bei der Implementierung auf Aggregation ausgelegt werden (Implementierung von Delegating und Nondelegating IUnknown). Gemeinsam ist beiden, dass sie unabhängig von der Implementierung zugrundeliegenden Programmiersprache sind, da die wiederverwendeten Objekte als Binärcode vorliegen können. Dies ist ein großer Vorteil dieser Art der Wiederverwendung gegenüber der Implementationsvererbung und damit auch gegenüber CORBA, wo es solch eine Unabhängigkeit nicht gibt.

31 Automation dynamische Methodenaufrufe Interface IDispatch
es wird erst zur Laufzeit bestimmt, welche Methode aufgerufen wird Interface IDispatch für Interpretative Umgebungen und Scriptsprachen Schnittstelle zu mehreren eigentlichen DCOM- Interfaces interface IDispatch : IUnknown { HRESULT getTypeInfoCount(/* ... */); HRESULT getTypeInfo(/* ... */); HRESULT getIDsOfNames(/* ... */); HRESULT invoke(/* ... */); }; getTypeInfo() textuelle Darstellung der Methoden Mit invoke() teilt der Client mit, welche Methode er mit welchen Parametern aufrufen möchte getIDsOfNames Abbildung von Strings auf Zahlenwerte Möglichkeit, Interfaces als ein Dual Interface zu implementieren 3.9 Automation Wie in CORBA gibt es auch in DCOM das Verfahren der „Automation". Automation erlaubt es, dynamische Methodenaufrufe auszuführen, d.h. es wird erst zur Laufzeit über Methodennamen bestimmt, welche Methode aufgerufen wird. Dieses Verfahren ist wichtig für interpretierende und Macro- Programmiersprachen, wie z.B. Visual Basic. Diese können durch dieses Verfahren relativ einfach auf DCOM- Komponenten zugreifen. Um nun Automation anbieten zu können, muss der sogenannte Automation Server das Interface IDispatch implementieren. Diese Interface dient dann als Schnittstelle zu mehreren eigentlichen DCOM- Interfaces, wie auch auf dem Bild verdeutlicht ist. Der Client, der auf ein solches Interface zugreift, wird als Automation Controller bezeichnet. Interpretative Umgebungen und Scriptsprachen wie Visual Basic können ebenfalls über Schnittstellen auf die Funktionalität von COM- Objekten zugreifen und dadurch Applikationen wie Microsoft Word oder Visio programmatisch steuern. Wären für diese Art von Automatisierung beliebige COM- Schnittstellen anzusteuern, gestaltete sich dadurch das Leben für die Entwicklerteams von Visual Basic und anderen interpretativen Umgebungen äußerst komplex. Zu deren Arbeitserleichterung hat Microsoft deshalb eine universelle COM- Schnittstelle namens IDispatch erschaffen: Diese Schnittstelle erlaubt Anwendungsprogrammen wie Excel einen universellen Zugriffspunkt auf ihre automatisierbare und nach außen angebotene Funktionalität. Information über die Funktionalität stellen die jeweiligen Applikationen in sogenannten Typbibliotheken zur Verfügung, die sich über die Methode getTypeInfo() abfragen lassen. Alle verfügbaren Methoden sind mittels textueller Darstellung beschrieben. Mit Hilfe eines Aufrufs von invoke() teilt der Client mit, welche Methode er mit welchen Parametern aufrufen möchte. Der Programmierer von invoke() ist selbst dafür verantwortlich, den Aufruf an die entsprechende interne Methode weiterzuleiten (dispatching). Da invoke() ganze Zahlen als Adressierungsschema verwendet, die Typbibliothek aber textuelle Information liefert, dient die Methode getIDsOfNames zur Abbildung von Strings auf die entsprechenden Zahlenwerte. Als Wermutstropfen zu Automation bleibt anzumerken, dass zum einen die Menge der für invoke()-Aufrufe verwendbaren Parametertypen durch die in Visual Basic verwendbaren Datentypen beschränkt ist. Zum anderen erfolgt das Weiterleiten von invoke()-Aufrufen dynamisch und entsprechend langsam, ist darüber hinaus für C++- Programmierer nur äußerst aufwendig zu programmieren. Daher sind die meisten Automatisierungsschnittstellen heutzutage als sogenannte Dual Interfaces konzipiert. Diese hybriden Schnittstellen definieren eine IDispatch- Schnittstelle, machen ihre Methoden aber gleichzeitig direkt über Methodenzeiger zugreifbar. Dadurch können Visual Basic Entwickler über IDispatch auf die Operationen zugreifen, während C++- Entwickler dieselbe Schnittstelle als konventionelle COM- Schnittstelle nutzen. Automatisierung ist auch im Zusammenhang mit ActiveX- Controls von Bedeutung, zumal dort IDispatch- Schnittstellen eine fundamentale Rolle spielen, etwa als Eingangschnittstellen zur Ereignismeldung. IDispatch Wie bereits gesagt, ermöglicht IDispatch das Ausführen einer Funktion über ihren Namen. Dazu stellt IDispatch zuerst den zum Funktionsnamen gehörigen Dispatch Identifier (DISPID) fest. Diese DISPID wird bei der jeweiligen Implementierung zur Entwicklungszeit vom Entwickler festgelegt. Die DISPID ist eine Long-Integerzahl, die nur in Bezug auf die jeweilige Implementierung des Interfaces eindeutig ist und nicht für alle Implementierungen. Deshalb ist die DISPID auch keine GUID. Nachdem die DISPID bestimmt wurde, wird die explizit vom Entwickler zu implementierende Funktion Invoke aufgerufen, die die gewünschte Funktion mit Hilfe der DISPID aufruft. Aus der Tatsache, dass IDispatch immer wieder neu implementiert werden muss, resultiert, dass jede Implementierung ihre eigene IID besitzt. Die Funktionen, die sich durch Invoke aufrufen lassen, bilden im Prinzip ein eigenes Interface, das sogenannte dispinterface. Es ist aber kein Interface im Sinne von DCOM, da es die Anforderungen an die Datenstruktur nicht erfüllt. Es gibt auch die Möglichkeit, das Interfaces als ein Dual Interface zu implementieren, d.h. Funktionen, die durch Invoke verfügbar gemacht werden, sind über die VTBL verfügbar. Dies ist sicherlich interessant, da hier abzuwägen ist, welche Variante im gegeben Zusammenhang besser ist. Z.B bei einer zeitkritischen Anwendung wäre der Zugriff über die VTBL wesentlich günstiger, da er schneller erfolgt als der Zugriff über Invoke. Dagegen können Makrosprachen wie z.B. Visual Basic wesentlich einfacher über Namen zugreifen. Automation in DCOM hat einen entscheidenden Nachteil gegen gegenüber Automation in CORBA. Während sie in CORBA automatisch zur Verfügung steht, muss in DCOM selbst Hand angelegt werden, um dieses Interface zu implementieren.

32 Threads in DCOM Apartment Thread Free Thread 3.10 Threads in DCOM
Apartment Threads sind single- threaded, d.h. ein Objekt gehört im Prinzip dem erzeugenden Thread und alle Zugriffe auf das Objekt müssen über den erzeugenden Thread erfolgen. Um dies zu realisieren wird ähnlich wie oben bereits erwähnt, mit Proxy und Stub gearbeitet. Ein beliebiger Thread sendet die Daten über den Proxy, der ein Marshalling durchführt, an den Stub des Objektes, wo wieder ein Unmarshalling durchgeführt wird. Durch dieses Verfahren wird erreicht, dass Anfragen an das Objekt synchronisiert werden. Diese Synchronisierung hat den Vorteil, dass bei der Anwendung von Apartment Threads die DCOM- Klassen nicht thread- safe implementiert werden müssen. Einzig die Class Factory und DLL- Eintrittspunkte müssen thread- safe sein. Free Thread Im Gegensatz zu den Apartment Threads sind Free Threads multi- threaded, d.h. die erzeugten Objekte gehören nicht mehr nur dem erzeugenden Prozess, sondern alle Prozesse können beliebig auf das Objekt zugreifen. Infolgedessen fällt die Kommunikation über Proxy und Stub, und somit auch die Synchronisation durch DCOM, weg. Dies bedeutet für den Entwickler wieder einigen Aufwand, da er nun seine Klassen thread- safe implementieren muss. Außerdem kommt noch hinzu, dass er unter Umständen auch explizit ein Marshalling und Unmarshalling durchführen muss, da Proxy und Stub dies ja auch übernommen hatten. Als eine Lösung dazu bietet DCOM den sogenannten FreeThreaded Marshaller (FTM) an.

33 Apartment Thread Apartment Thread
single- threaded ein Objekt gehört im Prinzip dem erzeugenden Thread alle Zugriffe auf das Objekt müssen über den erzeugenden Thread erfolgen DCOM- Klassen müssen nicht thread- safe implementiert werden Client Appl. Objekt Stub Proxy Ap. Thread bel. Thread 3.10 Threads in DCOM Apartment Thread Apartment Threads sind single- threaded, d.h. ein Objekt gehört im Prinzip dem erzeugenden Thread und alle Zugriffe auf das Objekt müssen über den erzeugenden Thread erfolgen. Um dies zu realisieren wird ähnlich wie oben bereits erwähnt, mit Proxy und Stub gearbeitet. Ein beliebiger Thread sendet die Daten über den Proxy, der ein Marshalling durchführt, an den Stub des Objektes, wo wieder ein Unmarshalling durchgeführt wird. Durch dieses Verfahren wird erreicht, dass Anfragen an das Objekt synchronisiert werden. Diese Synchronisierung hat den Vorteil, dass bei der Anwendung von Apartment Threads die DCOM- Klassen nicht thread- safe implementiert werden müssen. Einzig die Class Factory und DLL- Eintrittspunkte müssen thread- safe sein.

34 Free Threads Free Thread multi- threaded
erzeugten Objekte gehören nicht mehr nur dem erzeugenden Prozess alle Prozesse können beliebig auf das Objekt zugreifen Klassen müssen thread- safe implementiert weden Implementierung von Marshalling und Unmarshalling Client Appl. Objekt Free Thread Im Gegensatz zu den Apartment Threads sind Free Threads multi- threaded, d.h. die erzeugten Objekte gehören nicht mehr nur dem erzeugenden Prozess, sondern alle Prozesse können beliebig auf das Objekt zugreifen. Infolgedessen fällt die Kommunikation über Proxy und Stub, und somit auch die Synchronisation durch DCOM, weg. Dies bedeutet für den Entwickler wieder einigen Aufwand, da er nun seine Klassen thread- safe implementieren muss. Außerdem kommt noch hinzu, dass er unter Umständen auch explizit ein Marshalling und Unmarshalling durchführen muss, da Proxy und Stub dies ja auch übernommen hatten. Als eine Lösung dazu bietet DCOM den sogenannten FreeThreaded Marshaller (FTM) an.

35 Ausblick auf COM+ Weiterentwicklung von DCOM
Wegfallen des Programmier-Overheades (z.B. Referenzzähler, Implementierung von IUnknown usw.) GUIDs - interne Verwendung Konstruktoren und Destruktoren (Objekte initialisieren) Kontrolle des Lebensdauers von Objekten Implementationsvererbung jede maschinenspezifische Datenbank statt Registry 4. Ausblick auf COM+ COM+ soll eine Weiterentwicklung von DCOM sein und einige Nachteile von diesem beseitigen. Dazu gehört hauptsächlich der gewaltige Programmier- Overhead bei der Entwicklung von DCOM- Komponenten (z.B. Referenzzähler, Implementierung von Class Factory, IUnknown usw.). Die wichtigsten Punkte sind: ·                    Services und Runtime sollen leichter von beliebigen Programmiersprachen benutzt werden können ·                    Mit der Verwendung von Attributen soll erreicht werden, dass die Services leichter handbar sind und initialisiert werden können ·                    Die GUIDs sollen nach Möglichkeit nur noch intern verwendet werden müssen, da die direkte Verwendung dieser Zahlen in DCOM recht umständlich war ·                    Desweiteren soll im Gegensatz zu DCOM die Verwendung von Konstruktoren und Destruktoren möglich sein, um Objekte beim Start initialisieren zu können ·                    COM+ soll einen Service anbieten, der die Lebensdauer von Objekten kontrolliert. Damit fällt die umständliche Kontrolle von Hand bei DCOM weg. ·                    Interessanterweise soll bei COM+ jetzt doch eine Implementationsvererbung möglich sein. ·                    Ein wichtiger Punkt, der sich ändern soll, ist die Registrierung der Komponenten. War bei DCOM noch die nur auf Windows-Plattformen existierende Registry der zentrale Registrierpunkt, so soll bei COM+ jede maschinenspezifische Datenbank dazu dienen können. Dies begünstigt natürlich wieder die Verbreitung auf nicht Windows-Plattformen

36 Fragen?

37 Vielen Dank


Herunterladen ppt "COM (Component Object Model) / DCOM (Distributed COM)"

Ähnliche Präsentationen


Google-Anzeigen