PZR420 - ćw - temat A
Zaliczenie z ćwiczeń
W czasie trwania zajęć piszemy sprawozdanie z wykonania Zadań danego
tematu ...
W sprawozdaniu powinny się znaleźć:
- kod programu
- wydruki pokazujace działanie programu
- komentarze i odpowiedzi na pytania
Sprawozdanie to wysyłamy na adres mhanckow@main.amu.edu.pl subject: PZR420 - tematX.
Termin nadsyłania sprawozdań:
tydzien od ćwiczeń, na których zakończono dany temat.
RPC = Remote Procedure Call
--> literatura:
Gabassi, Dupouy "Przetwarzanie rozproszone w UNIX-ie"
krótkie
omówienie ONC RPC
--> cel RPC:
zastapienie wywołania "lokalnej
procedury"
wywołaniem "zdalnej procedury"
(w możliwie przezroczysty
sposób)
* robi sie to prawie automatycznie :
przygotowuje się plik "plik.x" zawierajacy
m. in. prototypy funkcji ktore maja być zdalnymi procedurami,
a nastepnie program "rpcgen" z parametrem "plik.x" tworzy
(prawie) wszystkie potrzebne pliki zrodlowe w jezyku C
pliki te trzeba później zmodyfikować ręcznie ...
* wywołanie odleglej procedury oznacza, że:
nasz proces ("klient") nawiazuje lacznosc z "serwerem"
w ktorym znajduje sie kod zdalnej procedury;
a> argument procedury jest przekazywany do serwera
(uzywany jest format XDR)
b> procedura jest uruchomiana w procesie serwera
c> wynik procedury jest zwracany do klienta
(uzywany jest format XDR)
klient czeka az procedura zwroci wynik
(tak, RPC jest synchroniczne; oczekiwanie na zakończenie
zdalnej proc. blokuje klienta)
* argument i wynik odleglej procedury moga byc skomplikowanymi
strukturami danych - na dobitke INACZEJ reprezentowanymi
w pamieci na maszynie klienta i serwera;
ten problem jest rozwiazany przy pomocy biblioteki XDR
--> usluga RPC
<=> nr programu & nr wersji programu
"zdalne procedury" sa podzielone na programy i wersje
procedury z tym samym nr programu i nr wersji
beda oczekiwac na jednym porcie
(na gniazdku strumieniowym i datagramowym rownoczesnie !)
w ponizszym przykladzie mamy:
jedna "zdalną procedurę" o nazwie "suma",
ktorej nr programu = 0x21000000,
nr wersji = 1,
rr procedury=1
argumentem procedury jest struktura "ParaLi"
wynikiem jest zmienna "int"
--------------------sum.x--------------------
struct ParaLiczb {
int x1;
int x2;
} ;
typedef struct ParaLiczb ParaLi;
program PROGSERVICE {
version VERSERVICE {
int suma(ParaLi) =1;
} = 1;
} = 0x21000000;
---------------------------------------------
--> portmap-er
jest to demon ktory zamienia nr programu i nr wersji
na nr portu, na ktorym czeka serwer zawierajacy
odlegle procedury nalezace do tego programu i wersji
(serwer musi sie zarejestrowac u portmap-era
na samym poczatku swojego dzialania)
demon ten oczekuje na zadania klientow na porcie 111
musi być włączony przez root-a
UWAGA: w ten sposob zostal rozwiazany klopotliwy problem
przydzielania nr portu...
--> pieniek klienta, pieniek serwera
* sa to procedury generowane przez "rpcgen plik.x"
* "pieniek klienta" symuluje wywolanie lokalnej procedury
innymi slowy czyni wywolenie odleglej procedury
nieodroznialnym od wywolania lokalnej procedury
jest w pliku "plik_clnt.c"
* "pieniek serwera" ulatwia budowe serwera;
powoduje ze majac kod procedury bardzo latwo
stworzyc caly serwer ...
jest w pliku "plik_svc.c"
--> XDR
* jest to biblioteka pozwalajaca wymieniac dane miedzy
maszynami o roznych architekturach i systemach operacyjnych;
miedzy aplikacjami pisanymi w roznych jezykach ...
(struktury danych moga byc roznie implementowane w pamieci
zaleznie od kompilatora czy architektury systemu)
* dzialanie polega na tym ze przed wyslaniem
dane sa kodowane do formatu XDR;
w takiej postaci sa przesylane (przez siec);
nastepnie sa dekodowane do formatu uzywanego
na odleglej maszynie
* filtry XDR - sluza do kodowania/dekodowania na/z format XDR
np: funkcja "xdr_long()" sluzy do kodowania zmiennych typu "long"
xdr_array() służy do kodowania tablic zmiennej długości
* program "rpcgen" tworzy odpowiednie "filtry XDR"
ktore beda uzywane do przesylania argumentu i wyniku
odleglej procedury
* mozna tworzyc filtry dla dowolnie zlozonych
struktur danych - ale na szeczescie nie musimy tego
robic ręcznie ! - robi to za nas program "rpcgen"
na podstawie struktur zdefiniowanych w "plik.x" !!!
--> jezyk RPC (uzywany w pliku ".x")
* jest bardzo podobny od jezyka C
* nalezy "nadużywać" typedef
jako argrument i wynik odleglej procedury
(MUSISZ uzyc ident. typu zdefiniowanego przez "typedef")
* proc. zdalne muszą mieć JEDEN argument
* konstrukcje jezyka RPC - nalezace do jezyka C
const, enum, struct, union
typedef
"tablice o stalej ilosci elementow"
* konstrukcje jezyka RPC - NIE nalezace do jezyka C
tablice o zmiennej ilosci elementow:
float x <>;
tablice o zmiennej ilosci elementow z ustalonym max:
float x <1000>;
"nowe" typy danych:
string s <>;
bool b;
program PROGSERVICE { } = 0x21000000;
version VERSERVICE { } = 1;
--> opis funkcji bibliotecznych (libnsl?)
opis fun. RPC i XDR -uzywanych w pienkach i
pozostalym kodzie- mozna znalezc w manualu:
man 3 rpc
man 3 xdr
..................................................
Zadanie 1.
Zbadaj i opisz jak rpcgen tlumaczy bardziej złożone struktury danych,
ktorych def jest podana poniżej;
aby wykonać to zadanie skompiluj plik "rpcgen -aC plik.x"
a potem zajrzyj do plikow ...
------------------------------------------
struct Macierz {
float Elem <>;
int IleW; int IleK;
};
typedef struct Macierz Mac;
struct TrzyMacierze { Mac M1; Mac M2; Mac M3; };
typedef struct TrzyMacierze TrzyMac;
program ProgMacierze {
version VerMacierze {
void PokazMacierz(Mac) = 1;
void OperacjaNaMacierzach(TrzyMac) = 2;
} = 1;
} = 0x21001234;
------------------------------------------
--> jak jest zbudowany tradycyjny klient RPC
a) otrzymuje "id klienta"
b) wywoluje odlegla procedure
c) likwiduje "id klienta"
--> jak jest zbudowany tradycyjny serwer RPC
a) otrzymuje "id transportu"
b) rejestruje "usluge RPC" u demona "portmap"
c) czeka na klientow;
wywoluje odpowiednie procedury dla klientow
i zwraca wyniki
--> jak używać plików wygenerowanych przez "rpcgen -aC sum.x"
a) należy JEDNOKROTNIE uruchomić rpcgen
b) zmodyfikowac pliki sum_client.c i sum_server.c,
c) skompilować wszystko przez "make -f Makefile.sum"
d) mozna uruchomic server (wczesniej upewnić się ze działa portmap)
oraz uruchamiac klienta
------------------- sum.x -------------------
struct ParaLiczb {
int x1;
int x2;
} ;
typedef struct ParaLiczb ParaLi;
program PROGSERVICE {
version VERSERVICE {
int suma(ParaLi) =1;
} = 1;
} = 0x21000000;
---------------------------------------------
Zadanie 2 "suma dwóch liczb".
Zaprogramuj aplikacje "sum.x" i wyprobuj jej dzialanie;
w aplikacji tej klient uruchamia proc RPC, która sumuje dwie liczby;
te dwie liczby powinny być parametrami wywołania klienta;
klient powinien wypisywać także wynik dodawania;
zmiany jakie trzeba wprowadzić do sum_client.c i sum_server.c łatwo
zauważyć
gdy się do tych plików zajrzy...
klienta i serwer uruchamiaj na lokalnej maszynie;
zobacz jakie proc RPC są dostępne przy pomocy "rpcinfo -p";
do sprawozdania wstaw odpowiednie wydruki!
Zadanie 3.
Zdefiniuj proc RPC pozwalającą przesłać macierz o dowolnych wymiarach
do serwera
oraz wyświetlić ją na terminalu po stronie serwera;
koniecznie pamiętaj o możliwych wyciekach pamięci!!
Zadanie 4 "operacje na macierzach".
Zdefiniuj proc RPC pozwalające wykonywać operacje na macierzach
(mnożenie i dodawanie);
zwróć uwagę, że teraz macierze będą przekazywane w obie strony:
kli->ser i ser->kli;
zadbaj o prawidłowe zwalnianie pamięci (patrz też uwagi poniżej na ten
temat!);
do sprawozdania wstaw wydruki i kluczowe fragmenty kodu (zwlaszcza
plik.x)
Zadanie 5 "timeout".
Zbadaj znaczenie parametrów TIMEOUT i TIMEOUT_RETRY po stronie klienta;
Aby eksperymentować z tymi parametrami upewnij się że w pliku
sum_client.c,
w funkcji clnt_create(), jest ustawiony transport "udp" (tylko wtedy te
parametry maja znaczenie);
następnie modyfikuj te parametry przy pomocy funkcji clnt_control() -
jej opis znajdziesz w manualu!
w procedurze sum_server dodaj do proc obliczającej sume sleep(5);
jak sie teraz będzie teraz zachowywać klient??
jaka musi być wartość TIMEOUT i TIMEOUT_RETRY aby klient doczekał się
wyniku?
ile razy jest wywoływana zdalna procedura?
--> opisy wazniejszych fukcji biblioteki RPC:
CLIENT *clnt_create(host, prog, vers, proto)
char *host;
u_int prog, vers;
char *proto;
Generic client creation routine. The host parameter identifies the
name of the remote host where the server is located. The proto parame-
ter indicates which kind of transport protocol to use. The currently
supported values for this field are "udp" and "tcp". Default timeouts
are set, but can be modified using clnt_control().
Warning: Since UDP-based RPC messages can only hold up to 8 Kbytes of
encoded data, this transport cannot be used for procedures that take
large arguments or return huge results.
enum clnt_stat clnt_call(clnt, procnum, inproc, in, outproc, out, tout)
CLIENT *clnt;
u_int procnum;
xdrproc_t inproc, outproc;
char *in, *out;
struct timeval tout;
A macro that calls the remote procedure procnum associated with the
client handle, clnt, which is obtained with an RPC client creation
routine such as clnt_create(). The in parameter is the address of the
procedure's argument(s), and out is the address of where to place the
result(s); inproc is used to encode the procedure's parameters, and
outproc is used to decode the procedure's results; tout is the time
allowed for results to come back.
--> zwalnianie pamieci
* pamiec alokowana przez XDR (podczas dekodowania
stringow lub tablic o zmiennej dlugosci itp)
powinna byc zwalniana przez "xdr_free()";
(to dotyczy "rezultatu" odleglej procedury po stronie klienta)
* pamiec alokowana przez nas powinna byc przez nas
zwalniana (to dotyczy "rezultatu" odleglej procedury
po stronie serwera oraz "argumentu" po stronie klienta)
void xdr_free(proc, objp)
xdrproc_t proc;
char *objp;
Generic freeing routine. The first argument is the XDR routine for the
object being freed. The second argument is a pointer to the object
itself. Note: the pointer passed to this routine is not freed, but
what it points to is freed (recursively).
......................................................................
Zadanie 6 "naiwne RPC" przy pomocy ssh
Usługa ssh może być używana jako "naiwne RPC" :
echo "dane wejsciowe" | ssh atos 'program'
# zdalna procedure realizuje 'program'
# dane wyjsciowe pojawiają sie na terminalu
Jak widać dane we/wy przekazuje się przez std we/wy (deskrptory 0 i 1),
lecz dotyczy to jedynie danych TEKSTOWYCH.
Aby powyższe dzialalo trzeba skonfigurowac ssh aby nie wymagalo hasla:
1. na maszynie lokalnej wygeneruj klucze prywatny i
publiczny:
ssh-keygen
2. wpisz zawartosc .ssh/id_dsa.pub (jedna linia tekstu)
do pliku authorized_keys na zdalnej maszynie
3. od teraz ssh nie wymaga hasla ...
Zdalna procedurę instalujemy sftp-ujac kolejny program na zdalna
maszyne!!!
Do sprawozdania prosze wstawic wydruki z eksperymentow.
Przyklad jak uruchamiac zdalna proc ssh:
echo "1 2 3 4" | ssh atos -qC "./program"
Czesc 2 zadania 6:
Porównaj wydajność zdalnych procedur
monożących wektor liczb double przez 2
1. prawdziwe RPC
2. naiwne RPC/ ssh
Uruchamiaj te procedury dla tablic o
długosci 600 6000 60000.
Te eksperymenty wygodnie wykonać w języku Tcl !!!
(Materiały
o Tcl; wish konsola2c.tcl & lub ./tclkit konsola2c.tcl & - uruchamianie b. wygodnej konsoli)
exec ./test_client << {1 2 3 4}
# wynik powinien sie pojawic na konsoli
# << {1 2 3 4} oznacza ze na stdin tego
programu zostana przekazane liczby calkowite 1 2 3 4
# w trybie TEKSTOWYM! (to NIE moga być dane
binarne)
W celu obliczenia czasu działania prog używaj polecenia time tcl-a:
time {exec ./test_client << {1 2 3 4}}
#% 3006590 microseconds per iteration
Procedura tcl tworzaca liste zadanej dlugosci:
proc lista n { set x {}; for {set i 0} {$i<$n} {incr i}
{lappend x $i}; set x }
lista 3
#% 0 1 2
Zadanie 7
Spróbuj wywoływać procedury SUN/ONC RPC z poziomu języka Java;
użyj oprogramowania "remotetea" http://remotetea.sourceforge.net/
(Uwaga: w tym zadaniu klient
ma być javowy, serwer pozostaje napisany w j. C !!!).
Połączenie języka Java i Tcl + konsola do interaktywnych eksperymentów:
TclBlend, konsola2c.tcl.
Zadanie 7a (**)
Spróbuj zaprogramować klienta RPC w j. Tcl lub innym tego typu,
bez odwoływania się do
bibliotek (j. C) xdr i rpc...
Wymaga to dokładnej znajomości protokolu rpc i xdr (patrz dokumenty
RFC1014 i RFC1057).
Wskazówka dla programujących w Tcl: jest b. wygodna komenda binary do tworzenia danych
binarnych.
(Uwaga: to zadanie jest
bezterminowe)