15. RPC - Remote Procedure Call
Transcrição
15. RPC - Remote Procedure Call
15. RPC - Remote Procedure Call • Historisch gesehen eine Vorstufe für RMI (Vorsicht bei Stub-Namen!). • Für die Implementierung von Klienten-Server Szenarien. • Berücksichtigt heterogene Umgebungen bezüglich: Klient Server - Betriebssystemplattformen, - Byteanordnungen, - Containergrößen. • Nachbildung eines lokalen Prozeduraufrufes: - Über Rechnergrenzen und Adressräume hinweg, - Synchrone Aufrufssemantik, - Übergabe von Parametern, - Rückgabe des Resultats, - Aber kein Kontext. Verteilte Betriebssysteme, 2003/2004, VS, Universität Ulm Client-Stub marshall unmarshall Server-Stub marshall unmarshall 1 15.1 RPC-Programmherstellung: • *.c, *.acf, *.idl-Dateien, • MIDL, Server.c Client.c Interf.acf Interf.idl • Stubs, MIDL Compiler • C, • Linker, Interf_C.C (stub) Interf.h Interf_S.C (stub) • Run time … C Compiler Client.obj. Server.obj C Compiler Interf_C.obj Interf_S.obj Client run time Linker Client.exe Verteilte Betriebssysteme, 2003/2004, VS, Universität Ulm Linker Server run time Server.exe 2 15.2 Attribute Configuration File interf.acf : [ implicit_handle(handle_t string_IfHandle) ] interface Interf { } • Mit implicit_handle benutzt das RPC Laufzeitsystem immer die spezifizierte globale Variable: RPC Library Implicit handle • explicit_handle erlaubt verschiedene Remote-Interfaces per RPC anzusprechen, eventuell unter Verwendung unterschiedlicher Stubs: void ExplicitRemoteProcX( handle_t whichServer, [string] char * printMsg); • auto_handle erledigt die Bindung automatisch und wählt zwischen explizit und impliziter RPC Handle, je nachdem, ob beim Prozeduraufruf ein Prozedurparameter erscheint Verteilte Betriebssysteme, 2003/2004, VS, Universität Ulm 3 15.3 Interface Definition File interf.idl : • Spezifiziert die Schnittstelle der Remote-Prozedur auf dem Server, • Universally Unique Identifier mit Programm uuidgen erzeugen, • Schnittstelle hat nur Routinen, ist also kein Objekt, • IDL als erweiterte Datendeklaration in C, • Kein strenges Typenkonzept. [ uuid(5AFEB070-D4D5-11d0-9451-002018304F6C), version (1.0), ] interface Interf { void Print( [in, string] unsigned char *pszString); } Klient Verteilte Betriebssysteme, 2003/2004, VS, Universität Ulm IDL Server 4 15.4 Parameterübergabe und IDL-Attribute • Marshalling: Konvertierung zwischen Hostformat & Netzwerkformat. • Verschiedene Datentypen als maschinenunabhängiges Format: - boolean, byte, char, double, float, hyper, long, short, small, wchar_t … Stringformat berücksichtigen, Containergrössen, Byte-Order: Verteilte Betriebssysteme, 2003/2004, VS, Universität Ulm 5 • Übergabe von Zeigern in den fremden Adressraum: - Übergabe dynamischer Strukturen nur mit sogenannter "Pointer Emulation", Parameter-Übergabe nötigenfalls nach dem Prinzip von Copy-Restore, Referenz-Zeiger sind konstant und enthalten nie den Wert NULL, Unique-Zeiger dürfen im Zeitpunkt des Aufrufs Null sein, lassen aber eine Allozierung des zurückgelieferten Parameterobjektes zu, - Full-Pointer zeigen auf ein Objekt, auf welches es auch Alias-Zeiger geben darf, - Kein automatische Hüllenbildung. • Übergabemodell für Werte und Zeiger: - "Hallo Server !" Als Kopie des Wertes, Als Adresse des Wertes, Als Adresse der Zeigervariablen, Als Menge aller Zeiger auf das Objekt. Verteilte Betriebssysteme, 2003/2004, VS, Universität Ulm 6 • Parametertransport mit speziellen Attributen: [in] - [string, …] mit Nullcharacter abgeschlossener String, - [out, …] nur auf dem Rückweg übertragen, [out] - [in, ...] nur auf dem Hinweg übertragen. Server • Weitere Attributfunktionen: - size_is(..), max_is, min_is, first_is, last_is, length_is … - zum Beispiel für einen Array variabler Größe: // weiteres IDL-Dateibeispiel size_is // Name des Attributes, muss separat deklariert werden interface RPC_Array // vgl. Hamilton & Williams "Windows NT4.0..." SAMS Verlag { extern short Size; // im Klientenprogramm angesiedelt void myArrayProc( [in, size_is(Size)] char Array[*] ) // Array variabler Größe …} • Attribute für RPC Binding-Handles: - [auto_handle] interface myServices, - [implicit_handle(handle_t InterfHdl] interface fixedService ), - [explicit_handle] verlangt beim RPC einen zusätzlichen Handle-Parameter. Verteilte Betriebssysteme, 2003/2004, VS, Universität Ulm 7 15.5 Quellprogramm client.c: • Argument auf der Befehlszeile enthält einen auszugebenden String. • Durch MIDL erzeugte Interface-Headerdatei mitcompilieren. • u.a. der Interface Handle ist in der Headerdatei versteckt. • Bind( )-Funktion für Windows-RPC: - Zeichenkette zusammenstellen mit den nötigen Binde-Parametern, Je nach gewähltem Protokoll Verbindung implizit aufbauen, Viele Protokollvarianten wählbar über eine Kennung; Z.B. "ncagn_np" für Microsoft Named Pipes #include <stdlib.h> #include <stdio.h> #include <windows.h> #include "..\interf.h" // File Client.c void main(int argc, char **argv){ RPC_STATUS status; unsigned char *pszStringBinding=NULL; unsigned char *pszString = &argv[1]; // Cmndline Argument implied ! // status of RPC // binding handle as string // string to print Verteilte Betriebssysteme, 2003/2004, VS, Universität Ulm 8 // make a concatenated string to feed the binding function - ignore errors here status = RpcStringBindingCompose(NULL, "ncacn_np", // proto.seq.=named-pipe NULL, // network-address (half open) "\\pipe\\hello", NULL, // end-point (pipe name) &pszStringBinding ); // the combined string status = RpcBindingFromStringBinding( pszStringBinding, &string_IfHandle); // now do the RPC RpcTryExcept { Print(pszString); } // try our remote print function, use RPC-Macro RpcExcept(1) // every exception is handled here { printf("Runtime reported exception 0x%lx\n", RpcExceptionCode() ); } RpcEndExcept // end the try block, use RPC-Macro //might need to free the strings allocated by the RPC run-time library status = RpcStringFree(&pszStringBinding); // should check for error status = RpcBindingFree(&string_IfHandle); // should check for error exit(0); } // allocate and free memory for an RPC client object (here string) void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len){ return (malloc(len)); } void __RPC_USER midl_user_free(void __RPC_FAR *ptr) { free(ptr); } Verteilte Betriebssysteme, 2003/2004, VS, Universität Ulm 9 15.6 Quellprogramm server.c: • Protokollsequenz auswählen. • Server-Interface registrieren. Handle wird durch Midl deklariert. • Server einschalten zur Entgegennahme von RPCs - concurrently. • Server stoppen, keine weiteren RPCs. • Registrierung wieder entfernen. • Allozierungsroutinen für die Laufzeitumgebung bereitstellen: - Objekte beim Aufruf allozieren, - Beim Rücksprung freigeben. #include <stdlib.h> #include <stdio.h> #include <windows.h> #include "..\string.h" // >>>>>>>> Datei Server.c (Teil 1) <<<<<<<<<<<<< // name of the remote interface void Print(unsigned char *pszString) { printf("RPC: %s\n", pszString); } Verteilte Betriebssysteme, 2003/2004, VS, Universität Ulm // rpc exported func 10 void main(int argc, char **argv) { RPC_STATUS status; // >>>>> Datei Server.c (Teil 2) <<<< // result status of RPC // tells the RPC library to use the specified protocol sequence combined // with the specified endpoint for receiving remote procedure calls. status = RpcServerUseProtseqEp("ncacn_np", 20, // named-pipe, # of concurrent calls "\\pipe\\hello", NULL ); // end-point name, security descr. // register interface with the RPC library status = RpcServerRegisterIf(string_ServerIfHandle, // interface to register (created by midl) NULL, NULL ); // nil UUID, default entry-point-vector // start the RPC server, ignore errors ! status = RpcServerListen( 1, 20, 1); // concurrent calls in [1..20], don't wait getchar(); status = RpcMgmtStopServerListening(NULL); // wait for any key to shutdown server // shutdown and stop listening status = RpcServerUnregisterIf( NULL,NULL,FALSE ); // unregister any interface // interface to unregister, unregister interface for all UUIDs, shutdown without wait // allocates and frees memory for an RPC client object (here string) void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len) { return malloc(len); } void __RPC_USER midl_user_free(void __RPC_FAR *ptr) { free( ptr ); } Verteilte Betriebssysteme, 2003/2004, VS, Universität Ulm 11