Architektura typu klient - serwer Oprogramowanie systemów równoległych i rozproszonych Wykład 6 Klient - Serwer to asymetryczna architektura, w której pewna funkcjonalność została rozdzielona i wyodbrębnione zostały dwa elementy: klient - potrzebujacy pewnej usługi, zlecajacy ja serwerowi, serwer - dostarczajacy usługi zlecanej przez klienta. Dr inż. Tomasz Olas olas@icis.pcz.pl Instytut Informatyki Teoretycznej i Stosowanej Politechnika Częstochowska 1/28 Cechy architektury klient - serwer Architektury klient - serwer Cechy charakterystyczne serwera: pasywny, czeka na żadania od klientów, w momencie otrzymania żadania, przetwarza je, a następnie wysyła odpowiedź. Cechy charakterystyczne klienta: aktywny, wysyła żadanie do serwera, oczekuje na odpowiedź od serwera. Podział ze względu na sposób obsługi żadań od klientów: serwer iteracyjny (sekwencyjne) (ang. iterative server), serwer współbieżny (ang. concurrent server). Podział ze względu na obsługę stanów serwera: serwer bezstanowy (ang. stateless server), serwer stanowy (ang. stateful server). Podział ze względu na rozdzielenie pracy : cienki klient (ang. thin client), gruby (bogaty) klient (ang. fat/rich client). Podział ze względu na liczbę warstw (modułów), Podział ze względu na sposób komunikacji (przy użyciu protokołu połaczeniowego lub bezpołaczeniowego). 3/28
Warstwy aplikacji - model MVC Architektura trójwarstwowa MVC (ang. Model-View-Controller) - Model-Widok-Kontroler składa się z trzech poziomów (warstw): 1. Poziom interfejsu użytkownika np. dokument w przegladarce 2. Poziom przetwarzania (logiki sterowania) np. przetworzenie zapytania w przegladarce internetowej 3. Poziom danych (modelu danych) np. informacje znajdujace się w bazie danych 5/28 Zdalne wywołanie procedur - koncepcja System Sun RPC (I) Zadaniem mechanizmu zdalnego wywołania procedur (ang. Remote Procedure Call) jest zachowanie w możliwie maksymalnym stopniu semantyki zwykłych wywołań procedur w środowisku sieciowym. Produkt Sun RPC został wprowadzony i wypromowany przez firmę Sun Microsystems jednocześnie z systemem NFS. RPC umożliwia konstruowanie aplikacji rozproszonych według modelu klient serwer. Aplikacje oparte na systemie RPC najczęściej sa tworzone przy wykorzystaniu kompilatora protokołów, takiego jak rpcgen firmy Sun Microsystems. 7/28
System Sun RPC (II) RPC - zasada działania W skład Sun RPC wchodza: biblioteka funkcji, narzędzie rpcgen służace do generowania dla aplikacji kodu obsługi sieci na podstawie opisu interfejsu procedur. Parametry wywołania funkcji i zwracane wyniki przesyłane sa w formacie XDR (external Data Representation - zewnętrzna reprezentacja danych). Z mechanizmu Sun RPC można korzystać przy użyciu protokołu transportu TCP lub UDP. Serwer może udostępniać dla wywołań RPC wiele podprogramów. Działanie RPC jest synchroniczne: aplikacja klient wysyła do serwera polecenie wykonania podprogramu wraz z argumentami wywołania. Następnie klient przechodzi w stan oczekiwania na zakończenie wykonania podprogramu, aby odebrać zwracane przez podprogram wyniki. Usługi RPC 9/28 Program rpcbind Usługa w RPC nazywa się zbiór funkcji przyjmujacych określone argumenty i zwracajacych określone wyniki. Deklaracje argumentów i wyników to interfejs usługi. Z punktu widzenia programisty usługa jest identyfikowana przez numer programu i numer wersji. rpcbind jest serwerem dokonujacym konwersji numerów programów RPC na numer portu tzw. portmapper (port 111) 1. serwer rejestruje się u demona portmap, 2. klient żada numeru portu serwera, 3. demon portmap odsyła klientowi numer portu serwera, 4. klient wysyła żadanie do serwera, 5. serwer wysyła odpowiedź do klienta. 11/28
Pieniek klienta i pieniek serwera Specyfikacja usług RPC W RPC stosowane sa pojęcia pieńka klienta (interfejsu klienta) i pieńka serwera (interfejsu serwera). Pieniek klienta symuluje w aplikacji klienta lokalne działanie procedury. Pieniek serwera czeka na żadanie nadchodzace od klienta. W RPC odległe usługi sa zorganizowane i identyfikowane według hierarchii jeden serwer zawiera jeden program jeden program ma jedna lub kilka wersji każda z wersji zawiera jedna lub kilka procedur Specyfikacje programów 13/28 Polecenie rpcinfo Numer programu - liczba 32-bitowa 0000 0000 1fff ffff - SunRPC 2000 0000 3fff ffff - definiowane przez użytkownika 4000 0000 5fff ffff - tymczasowe 6000 0000 ffff ffff - zarezerwowane Numer wersji - liczba 32-bitowa Numer procedury - liczba 32-bitowa Zwraca informacje dotyczace usług zarejestrowanych w rpcbind Wyświetlenie wszystkich usług na wskazanym serwerze: rpcinfo -p [ host ] Przykład: program wer. proto port 100000 2 tcp 111 portmapper 100000 2 udp 111 portmapper 391002 2 tcp 901 sgi_fam 100024 1 udp 757 status 100024 1 tcp 760 status 15/28
Plik /etc/rpc Program rpcgen Możliwe jest zdefiniowanie numerów programów w pliku /etc/rpc. W takim wypadku, aby otrzymać numer odpowiadajacy nazwie programu należy skorzystać z funkcji getrpcbyname(). Przykład: portmapper 100000 portmap sunrpc rstatd 100001 rstat rstat_svc rup perfmeter rusersd 100002 rusers nfs 100003 nfsprog ypserv 100004 ypprog mountd 100005 mount showmount ypbind 100007 walld 100008 rwall shutdown yppasswdd 100009 yppasswd etherstatd 100010 etherstat... Program rpcgen jako wejście pobiera plik specyfikacji usług w formacie języka RPC IDL ( C z dodatkiem typów program i version). Zostanie wygenerowany żadany kod języka C z implementacja zdefiniowanego wywołania zdalnej procedury. 17/28 Język RPC Przekazywanie argumentów Plik z definicja protokołu może zawierać następujace elementy: obowiazkowa deklaracja programu serwera i przynajmniej jednej dostarczonej przez niego funkcji, deklaracje złożonych typów danych wykorzystywanych w protokole, deklaracje stałych, komentarze. Standardowo RPC dopuszcza tylko jeden argument wywołania odległej procedury i jeden zwracany wynik, podawane w formie wskaźników. Jeśli występuje kilka argumentów należy je umieścić w strukturze. 19/28
XDR - External Data Representation Struktura CLIENT XDR jest zdefiniowanym na potrzeby RPC formatem danych, zapewniajacym ich pełna przenośność w środowisku heterogenicznym. Konwersja danych znajdujacych się w pamięci do formatu XDR (szeregowanie) i odwrotnie (deszeregowanie) odbywa się przy użyciu specjalnych procedur zwanych filtrami. Dla typów podstawowych zostały zdefiniowane odpowiednie filtry, natomiast dla typów złożonych programista musi je utworzyć samodzielnie. XDR może być używany również poza RPC, np. do tworzenia w pełni przenośnych plików binarnych. struct CLIENT AUTH *cl_auth; /* authenticator */ struct clnt_ops enum clnt_stat (*cl_call) (CLIENT *, u_long, xdrproc_t, caddr_t, xdrproc_t, caddr_t, struct timeval); /* wywołanie procedury zdalnej */ void (*cl_abort) (void); /* anulowanie wywołania */ void (*cl_geterr) (CLIENT *, struct rpc_err *); /* pobranie kodu błędu */ bool_t (*cl_freeres) (CLIENT *, xdrproc_t, caddr_t); /* zwolnienie wyników */ void (*cl_destroy) (CLIENT *); /* zniszczenie tej struktury */ bool_t (*cl_control) (CLIENT *, int, char *); /* ioctl() dla rpc */ *cl_ops; caddr_t cl_private; /* prywatne */ ; Ważniejsze funkcje (I) 21/28 Ważniejsze funkcje (II) Do tworzenia uchwytu klienta służy funkcja clnt_create: #include <rpc/rpc.h> CLIENT* clnt_create(char* host, u_long prog, u_long vers, char* protocol); host - nazwa hosta na którym działa proces serwer, prog - numer programu, vers - numer wersji, proto - określa klasę protokołu transportowego (może być między innymi udp lub tcp). jeżeli wywołanie zakończy się sukcesem zostanie zwrócony poprawny identyfikator (uchwyt) klienta, w przeciwnym wypadku funkcja zwróci NULL. Do usunięcia utworzonej struktury klienta służy funkcja clnt_destroy: void clnt_destroy(client* clnt); clnt - struktura klienta, która ma zostać usunięta Do obsługi błędów można wykorzystać funkcje void clnt_pcreateerror(char* s); void clnt_perrno(clnt_stat stat); void clnt_perror(client *clnt, char* s); 23/28
Przykład - plik ser.x Przykład - kod klienta (I) struct integers int x1; int x2; ; typedef struct integers intargs; program PROGSERVICE version VERSERVICE int SPSERVRPC(intargs) = 1; = 1; = 0x21000000; #include <iostream> #include <rpc/rpc.h> #include "ser.h" int dodaj(int a, int b) CLIENT *c1; integers arg; int *ret; char* host = "localhost"; c1 = clnt_create(host, PROGSERVICE, VERSERVICE, "tcp"); if (c1 == NULL) clnt_pcreateerror(host); return -1; 25/28 Przykład - kod klienta (II) Przykład - kod serwera arg.x1 = a; arg.x2 = b; ret = (int*)spservrpc_1(&arg, c1); if (ret == NULL) clnt_perror(c1, "blad wywolania odleglej procedury"); return -1; clnt_destroy(c1); return (*ret); int main() int a = 1, b = 1; std::cout << dodaj(a,b); #include <rpc/rpc.h> #include "ser.h" int spserv(int x1, int x2) return x1+x2; int *spservrpc_1_svc(intargs* arg, svc_req *) int* result = new int; *result = spserv(arg->x1, arg->x2); return result; 27/28