PZR420 - ćw - temat A

Zaliczenie z ćwiczeń

W czasie trwania zajęć piszemy sprawozdanie z wykonania Zadań danego tematu ...
W sprawozdaniu powinny się znaleźć:
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)