Systemy Rozproszone
Transkrypt
Systemy Rozproszone
Systemy Rozproszone - Ćwiczenie 6 1 Obiekty zdalne Celem ćwiczenia jest stworzenie obiektu zdalnego świadczącego prostą usługę nazewniczą. Nazwy i odpowiadające im punkty końcowe będą przechowywane przez obiekt w tablicy. Metoda insert dodaje punkt końcowy (hostName, portNumber) o nazwie s. Metoda search zwraca indeks w tablicy dla nazwy s. Metody getHostName i getPort zwracają nazwę hosta i port dla zadanego indeksu w tablicy. 1.1 Interfejs obiektu zdalnego Pierwszym krokiem przy tworzeniu obiektu zdalnego jest określenie jego interfejsu, który dziedziczy po klasie java.rmi.Remote. Każda metoda interfejsu musi być zadeklarowana jako zgłaszająca wyjątek java.rmi.RemoteException. /∗ p l i k RMINameService . j a v a ∗/ import j a v a . rmi . ∗ ; public i n t e r f a c e RMINameService extends Remote { public int s e a r c h ( S t r i n g s ) throws RemoteException ; public int i n s e r t ( S t r i n g s , S t r i n g hostName , int portNumber ) throws RemoteException ; public int g e t P o r t ( int i n d e x ) throws RemoteException ; public S t r i n g getHostName ( int i n d e x ) throws RemoteException ; } 1.2 Implementacja obiektu zdalnego Klasa dla obiektu zdalnego musi dziedziczyć po java.rmi.server.UnicastRemoteObject i implementować interfejs, który został zadeklarowany w rozdziale 1.1. W metodzie main tworzony jest obiekt zdalny klasy RMINameServer. Nastepnie, ten obiekt jest eksportowany przy pomocy metody UnicastRemoteObject.exportObject(). W wyniku eksportu otrzymujemy namiastkę obiektu zdalnego (typu RMINameService), 1 którą należy skojarzyć z określoną nazwą w rejestrze RMI przy poprzez wywołanie Registry.rebind() import j a v a . rmi . ∗ ; import j a v a . rmi . r e g i s t r y . ∗ ; import j a v a . rmi . s e r v e r . UnicastRemoteObject ; public c l a s s RMINameServer extends UnicastRemoteObject implements RMINameService { f i n a l int maxSize = 1 0 0 ; private S t r i n g [ ] names = new S t r i n g [ maxSize ] ; private S t r i n g [ ] h o s t s = new S t r i n g [ maxSize ] ; private int [ ] p o r t s = new int [ maxSize ] ; private int d i r S i z e = 0 ; public RMINameServer ( ) throws RemoteException { } public int s e a r c h ( S t r i n g s ) throws RemoteException { f o r ( int i = 0 ; i < d i r S i z e ; i ++) { i f ( names [ i ] . e q u a l s ( s ) ) { return i ; } } return −1; } public int i n s e r t ( S t r i n g s , S t r i n g hostName , int portNumber ) throws RemoteException { int o l d I n d e x = s e a r c h ( s ) ; i f ( ( o l d I n d e x == −1) && ( d i r S i z e < maxSize ) ) { names [ d i r S i z e ] = s ; h o s t s [ d i r S i z e ] = hostName ; p o r t s [ d i r S i z e ] = portNumber ; d i r S i z e ++; return 1 ; } return 0 ; } public int g e t P o r t ( int i n d e x ) throws RemoteException { return p o r t s [ i n d e x ] ; } 2 public S t r i n g getHostName ( int i n d e x ) throws RemoteException { return h o s t s [ i n d e x ] ; } public s t a t i c void main ( S t r i n g [ ] a r g s ) { try { RMINameServer o b j = new RMINameServer ( ) ; UnicastRemoteObject . u n e x p o r t O b j e c t ( obj , true ) ; System . out . p r i n t l n ( " E x p o r t i n g . . . " ) ; RMINameService s t u b = ( RMINameService ) UnicastRemoteObject . e x p o r t O b j e c t ( obj , 0 ) ; Registry r e g i s t r y ; i f ( true ) { // s t w o r z e n i e nowego r e j e s t r u na l o c a l h o s c i e r e g i s t r y = LocateRegistry . createRegistry (1099) ; System . out . p r i n t l n ( "New␣ r e g i s t r y ␣ c r e a t e d ␣on␣ localhost ") ; } else { System . out . p r i n t l n ( " L o c a t i n g ␣ r e g i s t r y . . . " ) ; // p o d l a c z e n i e do i s t n i e j a c e g o r e j e s t r u na localhoscie r e g i s t r y = LocateRegistry . getRegistry (" localhost " ); System . out . p r i n t l n ( " R e g i s t r y ␣ l o c a t e d " ) ; } r e g i s t r y . r e b i n d ( "MyNameServer" , s t u b ) ; System . out . p r i n t l n ( " RMINameService ␣bound , ␣ ready " ) ; } catch ( E x c e p t i o n e ) { System . e r r . p r i n t l n ( " RMINameService ␣ e x c e p t i o n : " ) ; e . printStackTrace () ; } } } 1.3 Klient import j a v a . rmi . ∗ ; import j a v a . rmi . r e g i s t r y . ∗ ; 3 public c l a s s RMIClient { public s t a t i c void main ( S t r i n g [ ] a r g s ) { try { System . out . p r i n t l n ( " L i s t ␣ o f ␣ r e g i s t e r e d ␣REMOTE␣ objects : ") ; f o r ( S t r i n g s : Naming . l i s t ( " // l o c a l h o s t " ) ) { System . out . p r i n t l n ( s ) ; } System . out . p r i n t l n ( " G e t t i n g ␣ r e g i s t r y " ) ; Registry reg = LocateRegistry . getRegistry ( " localhost ") ; System . out . p r i n t l n ( " G e t t i n g ␣ i n t e r f a c e " ) ; RMINameService s = ( RMINameService ) r e g . lookup ( " MyNameServer" ) ; System . out . p r i n t l n ( "Got␣ i n t e r f a c e " ) ; s . i n s e r t ( " foo " , " 1 9 2 . 1 6 8 . 1 . 1 " , 10000) ; s . i n s e r t ( " bar " , " 1 9 2 . 1 6 8 . 1 . 2 " , 1 0 0 0 0 ) ; s . i n s e r t ( " baz " , " 1 9 2 . 1 6 8 . 1 . 3 " , 1 0 0 0 0 ) ; String search_string = " foo " ; int i = s . s e a r c h ( s e a r c h _ s t r i n g ) ; i f ( i != −1) { System . out . p r i n t l n ( s . getHostName ( i ) + " : " + s . getPort ( i ) ) ; } else { System . out . p r i n t l n ( s e a r c h _ s t r i n g + " ␣ not ␣ found " ) ; } } catch ( E x c e p t i o n e ) { e . printStackTrace () ; } } } 2 Zadanie 1 - Kalkulator Zaimplementuj kalkulator jako obiekt zdalny. 4 3 Zadanie 2 - Bank Stwórz prosty system bankowy, która umożliwa klientowi banku zalogowanie się do systemu i przeprowadzenie podstawowych operacji na swoim koncie. Metody zdalne do zaimplementowania po stronie serwera: /∗ A u t o r y z a c j a k l i e n t a na p o d s t a w i e pary ( numer konta , kod pin ) i r o z p o c z e c i e s e s j i ( zalogowanie ) Parametry : a c c o u n t : numer k o n t a p i n : p i n p r z y p i s a n y do k o n t a Uwagi : Metoda zwraca t o k e n a u t o r y z a c y j n y , k t o r y j e s t generowany i zapamietywany p r z e z s e r w e r ( l o s o w y c i a g znakow ) . Token p o t r z e b n y j e s t do a u t o r y z a c j i k o l e j n y c h o p e r a c j i wykonywanych na tym k o n c i e ∗/ S t r i n g a u t h o r i z e ( int account , int p i n ) /∗ Zapytanie o stan konta Parametry : t o k e n : t o k e n a u t o r y z a c y j n y otrzymany po z a l o g o w a n i u Zwraca s t a n k o n t a ( i l o s c p i e n i e d z y na k o n c i e ) ∗/ double g e t B a l a n c e ( S t r i n g token ) /∗ Wplata p i e n i e d z y na k o n t o Parametry : t o k e n : t o k e n a u t o r y z a c y j n y otrzymany po z a l o g o w a n i u v a l u e : kwota do w p l a t y ∗/ void d e p o s i t ( S t r i n g token , double v a l u e ) /∗ Wyplata p i e n i e d z y z k o n t a Parametry : t o k e n : t o k e n a u t o r y z a c y j n y otrzymany po z a l o g o w a n i u v a l u e : kwota do w y p l a t y Zwraca f a l s z , gdy b r a k srodkow na k o n c i e do przeprowadzenia operacji 5 ∗/ boolean withdraw ( S t r i n g token , double v a l u e ) /∗ P r z e l e w p i e n i e d z y na i n n e k o n t o Parametry : t o k e n : t o k e n a u t o r y z a c y j n y otrzymany po z a l o g o w a n i u a c c o u n t : nr k o n t a na k t o r e z o s t a n a p r z e l a n e p i e n i a d z e v a l u e : kwota do w y p l a t y Zwraca f a l s z , gdy b r a k srodkow na k o n c i e do przeprowadzenia operacji ∗/ boolean withdraw ( S t r i n g token , int account , double v a l u e ) /∗ Konczy s e s j e ( w y l o g o w a n i e ) Uwagi : Serwer p o w i n i e n usunac t o k e n ( o i l e j e s t on p r a w i d l o w y ) ∗/ void bye ( S t r i n g token ) Przykład użycia kodu po stronie klienta: B a n k i n g S e r v i c e atm = . . . . . . // o b i e k t z d a l n y o d p o w i e d z i a l n y za o b s l u g e k o n t bankowych S t r i n g token = atm . a u t h o r i z e ( 1 2 3 4 5 6 , 1 1 1 1 ) ; i f ( token != null ) { // wplacam 100 z l na k o n t o atm . d e p o s i t ( token , 1 0 0 ) ; // sprawdzam s t a n k o n t a double b a l a n c e = atm . g e t B a l a n c e ( token ) ; System . out . p r i n t l n ( " Stan ␣ konta : ␣ "+b a l a n c e ) ; // wyplacam p i e n i a d z e z k o n t a atm . withdraw ( token , 5 0 ) ; // wplacam p i e n i a d z e na k o n t o nr 112233 atm . t r a n s f e r ( token , 1 1 2 2 3 3 , 2 5 ) ; // ponownie sprawdzam s t a n k o n t a System . out . p r i n t l n ( " Stan ␣ konta : ␣ "+atm . g e t B a l a n c e ( token ) ); } 6