Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

Systemy rozproszone W. Bartkiewicz Wykład 5. Komunikacja międzyprocesowa z wykorzystaniem usług warstwy pośredniej - RPC.

Podobne prezentacje


Prezentacja na temat: "Systemy rozproszone W. Bartkiewicz Wykład 5. Komunikacja międzyprocesowa z wykorzystaniem usług warstwy pośredniej - RPC."— Zapis prezentacji:

1 Systemy rozproszone W. Bartkiewicz Wykład 5. Komunikacja międzyprocesowa z wykorzystaniem usług warstwy pośredniej - RPC

2 Oprogramowanie warstwy pośredniej Oprogramowanie warstwy pośredniej to aplikacja, która logicznie przynależy do warstwy zastosowań, lecz zawiera wiele protokołów ogólnego przeznaczenia, niezależnych od innych, bardziej konkretnych aplikacji. Protokoły komunikacyjne oprogramowania warstwy pośredniej tworzą podstawy usług komunikacyjnych wysokiego poziomu. Do podstawowych usług komunikacyjnych oprogramowania warstwy pośredniej należą: –Zdalne wywołania procedur (RPC). –Zdalne wywołania obiektów. –Obsługa kolejek komunikatów. –Zaplecze strumieni komunikacji nośników ciągłych.

3 Zmodyfikowany model komunikacji sieciowej Zastosowanie Warstwa pośrednia Transport Sieć Łącze danych Poziom fizyczny Protokół aplikacji Protokół warstwy pośredniej Protokół transportu Protokół sieci Protokół łącza danych Protokół fizyczny Sieć

4 RPC – Wywołania procedur zdalnych RPC jest konstrukcją ukrywającą działania komunikacyjne pod znaną abstrakcją wywołania procedury. –Odwołanie do serwera ma po stronie klienta postać identyczną jak zwykłe wywołanie podprogramu. –Abstrakcja ta ukrywa w rzeczywistości wysłanie odpowiedniego komunikatu do procesu serwera (określającego procedurę jaka ma zostać wykonana przez serwer), wykonanie przez serwer odpowiadającego mu przetwarzania i odesłanie odpowiedzi. –Dane przesyłane przez klienta i niezbędne do wykonania przez serwer procedury, podawane są jako wartości parametrów. Odpowiedź serwera przekształcana jest na wartości parametrów wyjściowych oraz wartości powrotne z funkcji.

5 Semantyka wywołań RPC Definicja zdalnej procedury określa parametry wejściowe i wyjściowe. –Parametry wejściowe przekazywane są serwerowi jako wartości argumentów w komunikacie zamawiającym i kopiowane do zmiennych, które są przekazywane jako parametry do procedury w środowisku wykonawczym serwera. –Parametry wyjściowe zwracane są klientowi w komunikacie z odpowiedzią, gdzie używa się ich do zastąpienia wartości odpowiednich zmiennych w środowisku wywołania. –Jeśli parametr używany jest jako wejściowy i wyjściowy, to jego wartość musi zostać przesłana zarówno w zamówieniu jak i w odpowiedzi. Dostarczenie informacji o tym czy parametr używany jest na wejściu, wyjściu, czy w obu przypadkach powoduje konieczność zastosowania w każdym systemie RPC języka opisu interfejsu (IDL - Interface Definition Language).

6 Namiastki klienta i serwera Jeśli dana procedura ma być wykonana zdalnie, to system RPC w programie klienta umieszcza jej inną wersję, tzw. namiastkę procedury (stub procedure) nazywaną namiastką klienta (client stub). Jest to normalny, lokalny podprogram o sygnaturze zgodnej z procedurą zdalną. Zgodność sygnatury osiągana jest poprzez wspólną definicję interfejsu. Namiastka klienta umieszcza identyfikator procedury oraz parametry w komunikacie, który wysyła do serwera wykorzystując lokalny SO. Następnie blokuje się w oczekiwaniu na odpowiedź serwera. W programie serwera system RPC instaluje tzw. ekspedytora (dispatcher) oraz namiastki procedur serwera (server stubs). Ekspedytor na podstawie identyfikatora procedury w komunikacie z zamówieniem wybiera odpowiednią namiastkę procedury, przekazując jej argumenty.

7 Namiastki klienta i serwera (c.d.) Namiastka serwera rozpakowuje parametry z komunikatu, tworząc w środowisku serwera odpowiednie bufory zarówno dla danych wejściowych jak i wyników działania. Następnie wywołuje (również poprzez zwykłe wywołanie lokalne) procedurę zdalną serwera. Wykonuje ona swoje zadanie, zwracając również w normalny sposób wynik namiastce serwera. Namiastka serwera umieszcza wynik działania procedury w komunikacie z odpowiedzią dla klienta, wysyła go a następnie przechodzi w stan oczekiwania na nadejście następnego komunikatu. Namiastka klienta odbiera komunikat, rozpakowuje z niego wyniki, kopiuje je do obszarów pamięci w których oczekuje ich podprogram klienta wywołujący procedurę zdalną i kończy działanie w zwykły sposób.

8 Działanie RPC Komputer klientaKomputer serwera Proces klienta Wywoła- nie lokalne Lokalny powrót Klient Przetaczanie parametrów Odwrotne przetaczanie wyników Namiastka procedury klienta Wysyłanie zamówienia Przyjęcie odpowiedzi Moduł komunikacyjny (SO) Wykona- nie procedury Powrót Procedura usługowa Odwrotne przetaczanie parametrów Przetaczanie wyników Namiastka procedury serwera Przyjęcie zamówienia Wysłanie odpowiedzi Moduł komunikacyjny (SO) Wybór procedury Ekspedytor

9 Specyfika wywołań RPC Procedura zdalna wykonywana jest w środowisku odmiennym od miejsca jej wywołania, toteż nie ma dostępu do zmiennych środowiska wywołania, np. do zmiennych globalnych zadeklarowanych w programie wywołującym. Proces przekazywania danych między różnymi środowiskami wykonawczymi nazywamy przetaczaniem (marshaling). W wieloplatformowych środowiskach RPC występuje konieczność uwzględnienia różnych reprezentacji binarnych danych, tzn. zdefiniowania protokołów ich przesyłania wspólnych dla serwera i klienta. Przekazywanie przez proces w komunikacie do innych procesów adresów komórek pamięci lub ich równoważników (np. odniesień, referencji, uchwytów) jest bezcelowe. Tak więc generalnie argumenty i wyniki procedur zdalnych nie powinny zawierać struktur danych ze wskaźnikami do komórek pamięci. Systemy RPC radzą sobie zwykle z przetaczaniem wskaźników (odniesień) do prostych tablic i struktur, kopiując (przesyłając) między namiastkami klienta i serwera całe wskazywane dane.

10 Język Opisu Interfejsu (IDL) Aby uprościć korzystanie z mechanizmów RPC, interfejsy definiujące zbiory podprogramów realizowanych przez serwer i możliwych do wywołania przez klienta, określane są zazwyczaj w specjalnym języku opisu interfejsu (IDL – Interface Definition Language). Zastosowanie wspólnej definicji interfejsu zarówno dla serwera, jak i klienta zapewnia, że typy argumentów i wartości powrotnych oraz protokoły przetaczania ich wartości, używane przez klienta będą zgodne ze zdefiniowanymi na serwerze. Definicje interfejsów zapisane w IDL kompilowane są przy użyciu kompilatora interfejsu, tworzącego składowe konsolidowane z programami serwera i klienta.

11 Zadania kompilatora interfejsu Generowanie namiastek procedur klienta, odpowiadających sygnaturom procedur w interfejsie. Namiastki te zostaną skompilowane i połączone z programem klienta. Generowanie namiastek procedur serwera odpowiadających sygnaturom procedur w interfejsie. Namiastki te zostaną skompilowane i połączone z programem serwera. Na podstawie sygnatur procedur z interfejsu, określających typy argumentów i wartości powrotnych, wygenerowanie operacji przetaczania oraz odwrotnego przetaczania w każdej namiastce procedury. Wygenerowanie dla każdej procedury z interfejsu szablonu bibliotecznego charakterystycznego dla danego języka programowania (na przykład w języku C/C++ pliku nagłówkowego z deklaracjami sygnatur poszczególnych procedur). Programista dostarcza następnie ich implementacji.

12 Wiązanie Definicja interfejsu określa tekstową nazwę usługi za pomocą której odwołują się do niej klienty. Dla celów komunikacyjnych niezbędne jest jednak dostarczenie klientom informacji o punkcie końcowym serwera. Przez wiązanie (binding) rozumiemy odwzorowanie nazwy usługi na konkretny identyfikator komunikacyjny, określający punkt końcowy serwera (identyfikator portu, grupy portów lub dowolna inna forma miejsca przeznaczenia) do którego wysyłane będą komunikaty. Program klienta zawierać może sieciowy adres serwera. Oznacza to jednak, że przy każdym przemieszczeniu serwera niezbędne jest poinformowanie o tym wszystkich klientów. Łącznik (binder) jest odrębną usługą utrzymującą tablicę odwzorowań nazw usług na punkty końcowe serwerów. Łącznik jest przykładem usług nazewniczych, w których rejestruje się serwery aby umożliwić ich lokalizację przez klientów.

13 Uszkodzenia dostaw Komunikaty od czasu do czasu są gubione przez nadawców, odbiorców oraz bramy sieci. Sieci mogą ulegać podziałowi. Oznacza to, że jeden lub więcej węzłów sieci może zostać oddzielony od reszty sieci. Procesy ulegają niekiedy awariom. Ogólnie biorąc nadawca nie jest w stanie odróżnić awarii procesu od awarii komunikacyjnej. Jeśli proces nie odpowiada pomimo wykonania ustalonej liczby N prób skomunikowania się z nim, to zakłada się, że jest nieosiągalny. Wybór N jest trudny: jeśli będzie za małe, to można omyłkowo uznać proces za uszkodzony, natomiast gdy N będzie za duże to czas potrzebny na wykrycie uszkodzenia może stać się zbyt długi. Nie ma uszkodzeń danych. Komunikaty są odbierane poprawnie – zapewniają to mechanizmy wykrywania błędów na poziomie sieci.

14 Protokoły wymiany RPC Protokół zamówienia (request – R). Może być używany w sytuacji, gdy procedura zdalna nie musi zwracać żadnej wartości, a klient nie wymaga potwierdzenia, że ją wykonano. Klient może kontynuować działanie natychmiast po wysłaniu komunikatu z zamówieniem, gdyż nie musi czekać na komunikat z odpowiedzią. Protokół zamówienie – odpowiedź (request-reply – RR). Polega na wymianie pary komunikatów zamówienie – odpowiedź. Nie są wymagane komunikaty potwierdzające, gdyż za potwierdzenie zamówienia klienta służy odpowiedź serwera. Protokół zamówienie – odpowiedź – potwierdzenie (request-reply- acknowledge reply – RRA).Zakłada wymianę trzech komunikatów, z dodatkowym potwierdzeniem od klienta do serwera. Komunikat potwierdzający odpowiedź zawiera identyfikator zamówienia, wzięty z odpowiedzi. Jego nadejście powoduje potraktowanie przez serwer wszystkich odpowiedzi o mniejszych identyfikatorach zamówień jako potwierdzonych. Tak więc zgubienie jakiegoś potwierdzenia jest nieszkodliwe.

15 Problemy gwarancji dostaw Na wypadek awarii serwera, lub zagubień komunikatów z zamówieniami lub odpowiedziami, namiastka klienta powinna stosować odliczanie czasu przy czekaniu na odpowiedź od serwera. Po wyczerpaniu czasu oczekiwania namiastka klienta może przerwać swoje działanie i wrócić do klienta, przekazując informację, że operacja się nie powiodła. Zazwyczaj jednak powtarza ona (retransmituje) wysyłanie komunikatu zamawiającego do czasu aż skończy się to powodzeniem lub stanie się prawie pewne, że opóźnienie wynika z braku odpowiedzi od serwera, a nie z zaginięcia komunikatu. W przypadku retransmitowania komunikatu z zamówieniem, serwer może go otrzymać więcej niż jeden raz, a więc może wykonać operację kilkukrotnie. Jest to dopuszczalne jeśli operacja realizowana przez serwer jest idempotentna, tzn. wykonanie wielokrotne ma taki sam skutek jak jednokrotne.

16 Problemy gwarancji dostaw Jeśli powtórki komunikatów dochodzą do serwera podczas realizacji zadania (ponieważ jego wykonanie jest bardziej czasochłonne niż limit czasu przewidziany przez klienta), to aby uniknąć powtórzenia operacji, serwer może implementować protokół rejestracji i rozpoznawania zamówień tego samego klienta, w celu odfiltrowania duplikatów o takim samym identyfikatorze zamówienia. Duplikaty będą ignorowane, odpowiedź przesłana po zakończeniu zadania. Jeśli powtórne zamówienie dochodzi po wysłaniu odpowiedzi, serwer może korzystać z rejestru (historii) odpowiedzi. Wyszukując odpowiedź na zamówienie o danym identyfikatorze od danego klienta, serwer retransmituje ponownie komunikat z odpowiedzią, bez konieczności powtórnej realizacji zadania. Strategia ta może być kosztowna pod względem alokacji zasobów. Zazwyczaj serwer przechowuje tylko ostatnią odpowiedź dla danego klienta – przyjście od klienta nowego zamówienia traktowane jest jako potwierdzenie otrzymania odpowiedzi na poprzednie. Jeśli klient nie zgłasza nowych zadań, komunikaty z rejestru odpowiedzi usuwane są ponadto po upływie określonego czasu.

17 Semantyki niezawodności wywołań RPC Semantyka wywołania ewentualnego. Nie zakłada tolerowania uszkodzeń. Jeśli komunikat z odpowiedzią nie nadejdzie po wyznaczonym czasie i nie ponawia się prób, to nie ma pewności czy procedura została wykonana. Nie wiadomo bowiem, czy zaginął komunikat z zamówieniem lub awarii uległ serwer, czy też wykonanie doszło do skutku, a zaginął komunikat z odpowiedzią. Na ogół trudno taką semantykę zaakceptować. Semantyka wywołania co najmniej jednokrotnego. Retransmitowanie komunikatów odbywa się bez odfiltrowania powtórzeń, tak więc serwer może go otrzymać i wykonać więcej niż raz. Klient w końcu otrzyma odpowiedź, albo zostanie poinformowany, że serwer uległ awarii. Po zakończeniu wywołania RPC serwer nie będzie wiedział ile razy je wykonano. Semantyka ta jest do przyjęcia, jeśli wszystkie procedury serwera mogą być zaprojektowane za pomocą działań idempotentnych.

18 Semantyki niezawodności wywołań RPC Semantyka wywołania co najwyżej jednokrotnego. Zachodzi odfiltrowywanie powtórzeń oraz retransmitowanie odpowiedzi bez ponownego wykonywania działań. Jeśli serwer nie ulegnie awarii i klient otrzyma wynik wywołania, to procedura została wykonana dokładnie jeden raz. W przeciwnym przypadku następuje sygnalizacja sytuacji wyjątkowej. Tę semantykę wybiera się zazwyczaj w implementacjach RPC, zwłaszcza do realizacji operacji nieidempotentnych.

19 Sun RPC Jednym z najbardziej znanych uniksowych systemów zdalnych wywołań procedur jest system Sun RPC. Początkowo zaprojektowany został do komunikacji klient/serwer w sieciowym systemie plików Sun NFS. Sun RPC jest załączane jako część rozmaitych systemów operacyjnych firmy Sun i również jest dostępne w innych instalacjach systemu NFS. Programiści maja do wyboru użytkowanie RPC ponad protokołami UDP/IP lub TCP/IP. System Sun RPC zawiera język opisu interfejsu nazywany XDR oraz kompilator interfejsu o nazwie rpcgen.

20 Język Sun XDR Interfejs identyfikowany jest poprzez tzw. numer programu i numer wersji. Opis interfejsu składa się z definicji procedur, stałych oraz typów. Obok typów prostych, dopuszczalne jest definiowanie struktur, wyliczeń oraz unii. Składnia definicji typów jest taka sama jak w języku C. Definicja procedury określa jej sygnaturę oraz numer (począwszy od 1). Numer zero zarezerwowany jest dla automatycznie generowanej procedury pustej, służącej do testowania dostępności serwera. Dozwolony jest tylko jeden parametr wejściowy. Zarówno typ parametru wejściowego jak i wartości powrotnej mogą mieć charakter prosty lub zmiennej strukturalnej. Procedury wieloparametrowe muszą więc przekazywać parametry jako elementy jednej struktury.

21 Język Sun XDR const MAX = 100; typedef int plik_id; typedef int plik_wsk; typedef int dlugosc; struct Dane { int len; char bufor[MAX]; }; struct pisz_arg { plik_id p; plik_wsk pozycja; Dane dane; }; struct czyt_arg { plik_id p; plik_wsk pozycja; dlugosc len; }; Program CZYTAJPISZPLIK { version WERSJA { Dane CZYTAJ(czyt_arg) = 1; void PISZ(pisz_arg) = 2; } = 2; } = 9999;

22 Kompilator rpcgen Kompilator interfejsu rpcgen generuje: Namiastki procedur klienta. Namiastki procedur serwera, ekspedytora oraz procedurę główną (main) serwera. Procedury XDR przetaczania i odwrotnego przetaczania danych na użytek ekspedytora oraz namiastek klienta oraz serwera. Plik nagłówkowy o nazwie takiej samej jak nazwa interfejsu (programu), np. CzytajPiszPlik.h, z deklaracjami wspólnych zmiennych i typów do użytku w programach klienta i serwera. Sygnatury procedur usługowych podane są w postaci prototypów funkcji języka C. Nazwy procedur są takie same jak w interfejsie, z tym że zamienia się je na małe litery, dodaje znak podkreślenia oraz numer wersji. Argumentem każdej procedury użytkowej jest wskaźnik do jednego argumentu lub struktury zawierającej wszystkie argumenty. Podobnie jest w przypadku wartości powrotnej – zwracany jest wskaźnik do wyniku lub struktury z wynikami.

23 Program serwera Program serwera implementuje funkcje usługowe, zgodnie z prototypami wygenerowanymi w pliku nagłówkowym przez rpcgen. Wartość powrotna jest wskaźnikiem, musi więc być to adres zmiennej statycznej. Moduł zawierający procedury użytkowe musi zostać skonsolidowany z wygenerowanymi przez rpcgen modułami bibliotecznymi zawierającymi funkcję main, procedurę ekspedytora, i namiastki serwera i procedury przetaczające. Sun RPC działa bez ogólnosieciowych usług wiązania. Zamiast tego udostępnia na komputerze serwera lokalne usługi wiązania, nazywane programami odwzorowania portów (port mapper). Funkcja main tworzy gniazdo do przyjmowania komunikatów z zamówieniami klientów, a następnie eksportuje interfejs usługi, podając lokalnemu programowi odwzorowania portów numer programu (interfejsu), numer wersji oraz identyfikator portu serwera.

24 Serwer Sun RPC #include #include CzytajPiszPlik.h void* pisz_2(pisz_arg* a) { /* kod procedury zapisu*/ } Dane* czytaj_2(czyt_arg* a) { static Dane wynik; /*kod procedury zapisu*/ return &wynik; }

25 Program klienta Moduł zawierający procedury użytkowe musi zostać skonsolidowany z wygenerowanymi przez rpcgen modułami bibliotecznymi zawierającymi namiastki procedur klienta i procedury przetaczające. Do pobrania interfejsu punktu końcowego serwera służy funkcja clnt_create, zwracająca uchwyt klienta zawierający informacje niezbędne do komunikacji z portem serwera. W parametrach podajemy nazwę serwera, numer programu i wersji. Funkcja ta kontaktuje się z usługami odwzorowania portu w celu pobrania pełnej informacji komunikacyjnej. Porty serwerów nie muszą więc być ogólnie znane. Program klienta wywołuje funkcje usługowe, zgodnie z prototypami wygenerowanymi w pliku nagłówkowym przez rpcgen, rozszerzonymi o dodatkowy parametr uchwytu klienta. Semantyka wywołania procedury serwera jest co najmniej jednokrotna. Odstęp czasu miedzy kolejnymi próbami ma wartość domyślną, którą można określić podczas uzyskiwani uchwytu.

26 Klient Sun RPC #include #include CzytajPiszPlik.h main() { CLIENT* client_handle; char* nazwa_serw = kkkk; czyt_arg a; Dane* ptr; client_handle = clnt_create(nazwa_serw, CZYTAJPISZPLIK, WERSJA, udp); if ( client_handle == NULL ) { clnt_pcreateerror(nazwa_serw); exit(1); } a.p = 10; a.pozycja = 100; a.len = 1000; ptr = czytaj_2(&a, client_handle); clnt_destroy(client_handle); }

27 DCE RPC DCE (Distributed Computing Environment) jest rozproszonym środowiskiem obliczeniowym, opracowanym przez konsorcjum OSF (Open Software Foundation – obecnie Open Software Group). DCE opracowane początkowo dla systemu UNIX zostało przeniesione do wszystkich głównych systemów operacyjnych, łącznie z systemami VMS, Windows, a także systemami operacyjnymi komputerów osobistych. Specyfikacje DCE RPC zostały zaadaptowane przez Microsoft jako podstawowy system obliczeń rozproszonych. Wiele modeli obiektów rozproszonych stanowi bezpośrednie rozwinięcie koncepcji zawartych w DCE RPC.

28 DCE RPC Interfejs specyfikowany jest z wykorzystaniem specjalnego języka o nazwie IDL. Pliki IDL zawierają deklaracje prototypów funkcji specyfikowane w formie zbliżonej do składni języka C. Zawierać mogą również deklaracje typów, stałych oraz informacje inne potrzebne do przetaczania parametrów i wyników. Interfejs DCE RPC identyfikowany jest przez jednoznaczny identyfikator UID, składający się ze 128 bitowej liczby dwójkowej. Identyfikatory UID generowane są przez generator uuidgen, na podstawie informacji o lokalizacji komputera oraz czasu. Wiązanie w DCE RPC ma charakter lokalny, tzn. środowisko utrzymuje na maszynie serwera proces zwany demonem DCE (DCE daemon), wykonujący usługę odwzorowania portów. Środowisko DCE dostarcza jednak również globalnych usług wiązania. Serwer RPC może zostać zarejestrowany w globalnej usłudze katalogowej.

29 DCE RPC Usługi DCE RPC realizowane mogą być na bazie różnych protokołów. Domyślna semantyka wywołania procedury zdalnej ma charakter co najwyżej jednokrotny. Procedura może zostać jednak oznaczona w pliku IDL jako idempotentna. Wówczas wywołana będzie co najmniej jednokrotnie.

30 Przykład: Korzystanie z DCE RPC w systemie Windows Generujemy pusty plik interfejsu przy użyciu programu uuidgen z opcją /I. W naszym przykładzie będzie to plik motd.idl. Modyfikujemy otrzymany plik IDL, definiując interfejs usługi. uuid(9ebec1c7-bb8a-4063-ac06-d6441c6badea), version(1.0) ] interface MOTD { void GetMOTD([out, string, max_is(ct)] char* msg, [in] unsigned int ct); } Zmieniamy nazwę interfejsu na MOTD, deklarujemy procedurę zdalną GetMOTD. Opis funkcji jest w zasadzie taki sam jak w C. W nawiasach kwadratowych informujemy kompilator interfejsu jak mają być traktowane parametry. Opisy te nazywamy atrybutami.

31 Przykład: Korzystanie z DCE RPC w systemie Windows Istnieje wiele innych atrybutów, które można użyć do opisu innych typów parametrów (np. takich jak tablice). Można również definiować własne typy. Parametry mogą być również jednocześnie wejściowe i wyjściowe. Należy jednak robić tak jedynie w przypadku gdy rzeczywiście potrzebny nam jest przepływ danych w obie strony. Pozwoli to uniknąć przetaczania przez sieć śmieci. uuid(9ebec1c7-bb8a-4063-ac06-d6441c6badea), version(1.0) ] interface MOTD { void GetMOTD([out, string, max_is(ct)] char* msg, [in] unsigned int ct); }

32 Przykład: Korzystanie z DCE RPC w systemie Windows Tworzymy nowy, pusty plik o takiej samej nazwie jak plik IDL i rozszerzeniu ACF. Będzie on zawierał linię tworzącą niejawny uchwyt używany przez mechanizm RPC dla naszego interfejsu. [implicit_handle (handle_t MOTDHandle)] interface MOTD {}

33 Przykład: Korzystanie z DCE RPC w systemie Windows Kompilujemy stworzony interfejs z wykorzystaniem programu MIDL. Tworzy on plik nagłówkowy motd.h, który włączany będzie zarówno do kodu klienta jak i serwera, oraz dwa pliki motd_c.c (plik funkcji pośrednich po stronie klienta) i motd_s.c (funkcje pośrednie po stronie serwera). Piszemy kod serwera. Do projektu włączamy również plik motd_s.c oraz rpcrt4.lib – bibliotekę zawierającą funkcje środowiska RPC. Piszemy kod klienta. Konsolidujemy go z plikiem modt_c.c oraz również z biblioteką rpcrt4.lib.

34 Serwer RPC dla Windows – przydatne funkcje RPC_STATUS RPC_ENTRY RpcServerUseProtseqEp( //definiuje punkt końcowy unsigned char *Protseq, // Identyfikator protokołu unsigned int MaxCalls, // Długość kolejki wywołań unsigned char *Endpoint, // Id. punktu końcowego (numer gniazda, id potoku) void *SecurityDescriptor //Deskryptor zabezpieczeń (tylko potoki) ); Protseq Identyfikator (tekstowy) protokołu, np. ncacn_np dla nazwanych potoków, ncacn_ip_tcp dla tcp. Endpoint Identyfikator (tekstowy) punktu końcowego, np. dla ncacn_np identyfikator potoku, dla ncacn_ip_tcp numer gniazda.

35 Serwer RPC dla Windows – przydatne funkcje RPC_STATUS RPC_ENTRY RpcServerRegisterIf( //rejestracja interfejsu RPC_IF_HANDLE IfSpec, // uchwyt interfejsu (wygenerowany przez MIDL) UUID *MgrTypeUuid, // UUID menedżera interfejsu (zazwyczaj NULL) RPC_MGR_EPV *MgrEpv // Menedżer interfejsu (NULL to defaultowy // wygenerowany przez MIDL) ); RPC_STATUS RPC_ENTRY RpcServerListen( //start nasłuchiwania unsigned int MinimumCallThreads,// Min. liczba wątków serwera (zazw. 1) unsigned int MaxCalls,// Max liczba jednoczesnych k;ientów unsigned int DontWait// Zazwyczaj 0 );

36 Serwer RPC dla Windows (1) #include #include "motd.h" void main() { RPC_STATUS status; unsigned int cMaxCalls = 20; //dla gniazd //status = RpcServerUseProtseqEp((unsigned char*)"ncacn_ip_tcp", //cMaxCalls, (unsigned char*)"201", NULL); status = RpcServerUseProtseqEp((unsigned char*)"ncacn_np", cMaxCalls, (unsigned char*)"\\pipe\\MOTD", NULL); if ( status ) { exit(status); } status = RpcServerRegisterIf(MOTD_v1_0_s_ifspec, NULL, NULL); if ( status ) { exit(status); } status = RpcServerListen(1, cMaxCalls, 0); if ( status ) { exit(status); } }

37 Serwer RPC dla Windows (2) 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); }

38 Serwer RPC dla Windows (3) static char *motd[]= { "Yawn a more Roman way", "Rats live on no evil star.", "If I had a hi-fi", "Rise to vote sir", "Evil Olive", "Never odd or even", "No lemons, no melon" }; /* Funkcja(e)*/ void GetMOTD(unsigned char __RPC_FAR *msg, unsigned int ct) { static int n=0; char tmp[1024]; sprintf(tmp,"%d: %s",++n,motd[n%(sizeof(motd)/sizeof(char *))]); strncpy((char*)msg,tmp,ct); }

39 Klient RPC dla Windows – przydatne funkcje RPC_STATUS RPC_ENTRY RpcStringBindingCompose( unsigned char *ObjUuid, // Ident. interfejsu unsigned char *ProtSeq, // Ident. protokołu unsigned char *NetworkAddr, // Adres sieciowy komputera unsigned char *EndPoint, // Id. punktu końcowego unsigned char *Options, // Opcje unsigned char **StringBinding// Łańcuch połączenia (parametr wyjściowy) ); Protseq Identyfikator (tekstowy) protokołu, np. ncacn_np dla nazwanych potoków, ncacn_ip_tcp dla tcp. Endpoint Identyfikator (tekstowy) punktu końcowego, np. dla ncacn_np identyfikator potoku, dla ncacn_ip_tcp numer gniazda. NetworkAddr Adres sieciowy komputera serwera, np. dla ncacn_np nazwa Windows, dla ncacn_ip_tcp adres IP lub nazwa domenowa.

40 Klient RPC dla Windows – przydatne funkcje RPC_STATUS RPC_ENTRY RpcBindingFromStringBinding( unsigned char *StringBinding, // Łańcuch połączenia RPC_BINDING_HANDLE *Binding // Adres uchwytu klienta ); RPC_STATUS RPC_ENTRY RpcStringFree( unsigned char **String ); RPC_STATUS RPC_ENTRY RpcBindingFree( RPC_BINDING_HANDLE *Binding );

41 Klient RPC dla Windows (1) #include #include "motd.h" unsigned char* pszStringBinding = NULL; RPC_STATUS RPC_init(int argc, char* argv[]) { RPC_STATUS status; unsigned char* pszNetworkAddres = NULL; if ( argc ==2 ) pszNetworkAddres = (unsigned char*)argv[1]; // Dla gniazd //status = RpcStringBindingCompose(NULL, (unsigned char*)"ncacn_ip_tcp", //pszNetworkAddres, (unsigned char*)"201", //NULL, &pszStringBinding); status = RpcStringBindingCompose(NULL, (unsigned char*)"ncacn_np", pszNetworkAddres, (unsigned char*)"\\pipe\\MOTD", NULL, &pszStringBinding); if ( status ) {return status;} status = RpcBindingFromStringBinding(pszStringBinding, &MOTDHandle); return status; }

42 Klient RPC dla Windows (2) RPC_STATUS RPC_close() { RPC_STATUS status; status = RpcStringFree(&pszStringBinding); if ( status ) {return status;} status = RpcBindingFree(&MOTDHandle); return status; } 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); }

43 Klient RPC dla Windows (3) void main(int argc, char* argv[]) { unsigned long ulCode; char msg[100]; RPC_STATUS status = RPC_init(argc, argv); if ( status ) { printf("Blad laczenia z RPC\n"); exit(status); } GetMOTD((unsigned char*)msg, sizeof(msg)); printf("Z serwera: %s\n", msg); status = RPC_close(); if ( status ) {exit(status);} }

44 Klient RPC dla Windows (4) – Przechwytywanie wyjątków RPC void main(int argc, char* argv[]) { unsigned long ulCode; char msg[100]; RPC_STATUS status = RPC_init(argc, argv); if ( status ) { printf("Blad laczenia z RPC\n"); exit(status); } RpcTryExcept { GetMOTD((unsigned char*)msg, sizeof(msg)); printf("Z serwera: %s\n", msg); } RpcExcept(1) { ulCode = RpcExceptionCode(); printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode); } RpcEndExcept status = RPC_close(); if ( status ) {exit(status);} }


Pobierz ppt "Systemy rozproszone W. Bartkiewicz Wykład 5. Komunikacja międzyprocesowa z wykorzystaniem usług warstwy pośredniej - RPC."

Podobne prezentacje


Reklamy Google