Systemy Rozproszone - Ćwiczenie 5
1 Sockety
1.1 Serwer tekstowy
Poniżej znajduje się kod serwera, ktory odbiera od klienta tekst i w odpowiedzi odsyła ten sam tekst pisany wielkimi literami. Konstruktor klasy SocketServer tworzy gniazdo (klasa ServerSocket) nasłuchujące na określonym przez użyt-
kownika porcie. Następnie, serwer rozpoczyna obsługę żądań w metodzie SocketServer.listen().
Metoda ta obsługuje żądania od klientów w pętli while, w której to serwer blo- kuje się do czasu połączenia z klienem (metoda ServerSocket.accept()), a następnie po uzyskaniu połączenia obsługa żądania jest przekazywana do meto- dy serviceClient(). Zauważ, że wysyłanie i odbieranie komunikatów odbywa się poprzez operowanie na strumieniach.
import j a v a . i o . ∗ ; import j a v a . n e t . ∗ ;
public c l a s s S o c k e t S e r v e r { S e r v e r S o c k e t c l i e n t C o n n ; // O b j e c t O u t p u t S t r e a m o u t ; // O b j e c t I n p u t S t r e a m i n ;
public S o c k e t S e r v e r ( i n t p o r t ) {
System . ou t . p r i n t l n ( " S e r v e r ␣ c o n n e c t i n g ␣ t o ␣ p o r t ␣ "+p o r t )
; try {
c l i e n t C o n n = new S e r v e r S o c k e t ( p o r t ) ; }
catch ( E x c e p t i o n e ) {
System . o u t . p r i n t l n ( " E x c e p t i o n : " + e ) ; System . e x i t ( 1 ) ;
} }
public s t a t i c void main ( S t r i n g [ ] a r g s ) { i n t p o r t = 3 0 0 0 ;
i f ( a r g s . l e n g t h > 0 ) {
try {
p o r t = I n t e g e r . p a r s e I n t ( a r g s [ 0 ] ) ; }
catch ( E x c e p t i o n e ) { p o r t = 3 0 0 0 ;
} }
S o c k e t S e r v e r s e r v e r = new S o c k e t S e r v e r ( p o r t ) ;
System . ou t . p r i n t l n ( " S e r v e r ␣ r u n n i n g ␣ on ␣ p o r t ␣ "+p o r t ) ; s e r v e r . l i s t e n ( ) ;
}
public void l i s t e n ( ) { try {
System . o u t . p r i n t l n ( " Waiting ␣ f o r ␣ c l i e n t s . . . " ) ; while ( true ) {
S o c k e t c l i e n t R e q = c l i e n t C o n n . a c c e p t ( ) ; System . ou t . p r i n t l n ( " C o n n e c t i o n ␣ from ␣ "
+ c l i e n t R e q . g e t I n e t A d d r e s s ( ) . getHostName ( ) ) ; s e r v i c e C l i e n t ( c l i e n t R e q ) ;
} }
catch ( I O E x c e p t i o n e ) {
System . o u t . p r i n t l n ( " E x c e p t i o n : " + e ) ; }
}
public void s e r v i c e C l i e n t ( S o c k e t s ) { DataInputStream i n S t r e a m = n u l l ; DataOutputStream outStream = n u l l ; S t r i n g message ;
try {
i n S t r e a m = new DataInputStream ( s . g e t I n p u t S t r e a m ( ) ) ; outStream = new DataOutputStream ( s . getOutputStream
( ) ) ;
message = i n S t r e a m . readUTF ( ) ;
outStream . writeUTF ( message . toUpperCase ( ) ) ; }
catch ( I O E x c e p t i o n e ) {
System . o u t . p r i n t l n ( " I /O␣ E x c e p t i o n : " + e ) ; }
} }
1.2 Klient tekstowy
W celu połączenia klienta z serwerem, klient musi znać punkt końcowy ser- wera (adres i port). Parametry te możesz przekazać do wykonania progra- mu ustawiając we właściwościach projektu pole Run→Arguments na wartość
"localhost 3000" (w celu połączenia z uprzednio uruchomionym serwerem lo- kalnym). Klient w konstruktorze tworzy gniazdo do serwerwa (obiekt klasy Socket), a następnie rozpoczyna komunikację z serwerem wywołując metodę SocketClient.sendMessage().
import j a v a . i o . ∗ ; import j a v a . n e t . ∗ ;
public c l a s s S o c k e t C l i e n t { S o c k e t s e r v e r C o n n ;
public S o c k e t C l i e n t ( S t r i n g h o s t , i n t p o r t ) { try {
s e r v e r C o n n = new S o c k e t ( h o s t , p o r t ) ; }
catch ( E x c e p t i o n e ) {
System . o u t . p r i n t l n ( " E x c e p t i o n : " + e ) ; System . e x i t ( 1 ) ;
}
System . ou t . f o r m a t ( " Connected ␣ t o ␣%s :%d" , h o s t , p o r t ) ; }
public void sendMessage ( ) {
DataInputStream i n S t r e a m = n u l l ; DataOutputStream outStream = n u l l ; S t r i n g message = " h e l l o ␣ w o r l d " ; S t r i n g r e s p o n s e ;
try {
i n S t r e a m = new DataInputStream ( s e r v e r C o n n . g e t I n p u t S t r e a m ( ) ) ;
outStream = new DataOutputStream ( s e r v e r C o n n . getOutputStream ( ) ) ;
outStream . writeUTF ( message ) ; r e s p o n s e = i n S t r e a m . readUTF ( ) ;
System . o u t . p r i n t l n ( " S e r v e r ␣ r e t u r n e d ␣ " + r e s p o n s e ) ; }
catch ( I O E x c e p t i o n e ) {
System . o u t . p r i n t l n ( " I /O␣ E x c e p t i o n : " + e ) ;
} }
public s t a t i c void main ( S t r i n g [ ] a r g s ) { i f ( a r g s . l e n g t h < 2 ) {
System . o u t . p r i n t l n ( " Usage : ␣ j a v a ␣ S o c k e t C l i e n t ␣ h o s t ␣ p o r t " ) ;
System . e x i t ( 1 ) ; }
S t r i n g h o s t = a r g s [ 0 ] ; i n t p o r t ;
try {
p o r t = I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ; }
catch ( NumberFormatException e ) { p o r t = 3 0 0 0 ;
}
S o c k e t C l i e n t c l i e n t = new S o c k e t C l i e n t ( h o s t , p o r t ) ; c l i e n t . sendMessage ( ) ;
} }
1.3 Serwer obiektowy
Ten serwer różni si od poprzedniego sposobem wymiany komunikatów. W tym przypadku klient przekazuje serwerowi obiekt (tablica typu int) i odsyła klien- towi liczbę całkowitą (równą sumie elementów w tablicy). Uwaga: kolejność w jakiej tworzone są strumienie ObjectInputStream i ObjectOutputStream jest istotna. Najpierw należy utworzyć obiekt ObjectOutputStream, a następ- nie obiekt ObjectInputStream.
import j a v a . i o . ∗ ; import j a v a . n e t . ∗ ;
public c l a s s O b j e c t S e r v e r { S e r v e r S o c k e t c l i e n t C o n n ; // O b j e c t O u t p u t S t r e a m o u t ; // O b j e c t I n p u t S t r e a m i n ;
public O b j e c t S e r v e r ( i n t p o r t ) {
System . ou t . p r i n t l n ( " S e r v e r ␣ c o n n e c t i n g ␣ t o ␣ p o r t ␣ "+p o r t )
; try {
c l i e n t C o n n = new S e r v e r S o c k e t ( p o r t ) ; }
catch ( E x c e p t i o n e ) {
System . o u t . p r i n t l n ( " E x c e p t i o n : " + e ) ; System . e x i t ( 1 ) ;
} }
public s t a t i c void main ( S t r i n g [ ] a r g s ) { i n t p o r t = 3 0 0 0 ;
i f ( a r g s . l e n g t h > 0 ) { try {
p o r t = I n t e g e r . p a r s e I n t ( a r g s [ 0 ] ) ; }
catch ( E x c e p t i o n e ) { p o r t = 3 0 0 0 ;
} }
O b j e c t S e r v e r s e r v e r = new O b j e c t S e r v e r ( p o r t ) ;
System . ou t . p r i n t l n ( " S e r v e r ␣ r u n n i n g ␣ on ␣ p o r t ␣ "+p o r t ) ; s e r v e r . l i s t e n ( ) ;
}
public void l i s t e n ( ) { try {
System . o u t . p r i n t l n ( " Waiting ␣ f o r ␣ c l i e n t s . . . " ) ; while ( true ) {
S o c k e t c l i e n t R e q = c l i e n t C o n n . a c c e p t ( ) ; System . ou t . p r i n t l n ( " C o n n e c t i o n ␣ from ␣ "
+ c l i e n t R e q . g e t I n e t A d d r e s s ( ) . getHostName ( ) ) ; s e r v i c e C l i e n t ( c l i e n t R e q ) ;
} }
catch ( I O E x c e p t i o n e ) {
System . o u t . p r i n t l n ( " E x c e p t i o n : " + e ) ; }
}
public void s e r v i c e C l i e n t ( S o c k e t s ) { O b j e c t I n p u t S t r e a m i n S t r e a m = n u l l ; ObjectOutputStream outStream = n u l l ;
i n t [ ] d a t a = n u l l ; i n t sum = 0 ;
try {
// z j a k i e g o s powodu u t w o r z e n i e inStream , // a n a s t e p n i e o u t S t r e a m powoduje
// z a b l o k o w a n i e programu // w i e c e j c i e k a w o s t e k na :
// h t t p : / /www . s e a s i t e . n i u . edu / c s 5 8 0 j a v a / O b j e c t _ S e r i a l i z a t i o n . h t m l
outStream = new ObjectOutputStream ( s . getOutputStream ( ) ) ;
i n S t r e a m = new O b j e c t I n p u t S t r e a m ( s . g e t I n p u t S t r e a m ( ) ) ;
try {
d a t a = ( i n t [ ] ) i n S t r e a m . r e a d O b j e c t ( ) ; f o r ( i n t i =0; i <d a t a . l e n g t h ; i ++) {
sum += d a t a [ i ] ; }
outStream . w r i t e I n t ( sum ) ;
// wymuszamy z a p i s do s t r u m i e n i a outStream . f l u s h ( ) ;
}
catch ( E x c e p t i o n e ) { e . p r i n t S t a c k T r a c e ( ) ; }
}
catch ( I O E x c e p t i o n e ) {
System . o u t . p r i n t l n ( " I /O␣ E x c e p t i o n : " + e ) ; }
} }
1.4 Klient obiektowy
Klient obiektowy działa w podobny sposób do klienta kekstowego. Tablica wysy- łana jest na serwer w dwóch krokach: poprzez umieszczenie obiektu w strumieniu (ObjectOutputStream.writeObject()), oraz faktycznie wysłanie danych (me- toda ObjectOutputStream.flush()).
import j a v a . i o . ∗ ; import j a v a . n e t . ∗ ;
public c l a s s O b j e c t C l i e n t { S o c k e t s e r v e r C o n n ;
public O b j e c t C l i e n t ( S t r i n g h o s t , i n t p o r t ) { try {
s e r v e r C o n n = new S o c k e t ( h o s t , p o r t ) ; }
catch ( E x c e p t i o n e ) {
System . o u t . p r i n t l n ( " E x c e p t i o n : " + e ) ; System . e x i t ( 1 ) ;
}
System . ou t . f o r m a t ( " Connected ␣ t o ␣%s :%d" , h o s t , p o r t ) ; }
public void sendMessage ( ) {
O b j e c t I n p u t S t r e a m i n S t r e a m = n u l l ; ObjectOutputStream outStream = n u l l ; i n t [ ] d a t a = new i n t [ 1 0 ] ;
f o r ( i n t i =0; i <10; i ++) { d a t a [ i ] = i +1;
}
i n t sum ; try {
outStream = new ObjectOutputStream ( s e r v e r C o n n . getOutputStream ( ) ) ;
i n S t r e a m = new O b j e c t I n p u t S t r e a m ( s e r v e r C o n n . g e t I n p u t S t r e a m ( ) ) ;
outStream . w r i t e O b j e c t ( d a t a ) ; outStream . f l u s h ( ) ;
sum = i n S t r e a m . r e a d I n t ( ) ;
System . o u t . p r i n t l n ( " S e r v e r ␣ r e t u r n e d ␣sum=" + sum ) ; }
catch ( I O E x c e p t i o n e ) {
System . o u t . p r i n t l n ( " I /O␣ E x c e p t i o n : " + e ) ; }
}
public s t a t i c void main ( S t r i n g [ ] a r g s ) { i f ( a r g s . l e n g t h < 2 ) {
System . o u t . p r i n t l n ( " Usage : ␣ j a v a ␣ S o c k e t C l i e n t ␣ h o s t ␣ p o r t " ) ;
System . e x i t ( 1 ) ;
}
S t r i n g h o s t = a r g s [ 0 ] ; i n t p o r t ;
try {
p o r t = I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ; }
catch ( NumberFormatException e ) { p o r t = 3 0 0 0 ;
}
O b j e c t C l i e n t c l i e n t = new O b j e c t C l i e n t ( h o s t , p o r t ) ; c l i e n t . sendMessage ( ) ;
} }
2 Przykad 1
... w którym klient otwiera połączenie z serwerem tylko na czas wykonania po- lecenia wybranego z menu przez użytkownika. Połączenie z serwerem zostaje utworzone po wybraniu polecenia, a po odebrania odpowiedzi od serwera połą- czenie jest zamykane.
2.1 Serwer
/∗
∗ To change t h i s t e m p l a t e , c h o o s e T o o l s | Templates
∗ and open t h e t e m p l a t e i n t h e e d i t o r .
∗/
package j a v a a p p l i c a t i o n 1 ; import j a v a . i o . ∗ ;
import j a v a . n e t . ∗ ; import j a v a . u t i l . ∗ ;
public c l a s s O b j e c t S e r v e r { S e r v e r S o c k e t c l i e n t C o n n ; // O b j e c t O u t p u t S t r e a m o u t ; // O b j e c t I n p u t S t r e a m i n ;
public O b j e c t S e r v e r ( i n t p o r t ) {
System . ou t . p r i n t l n ( " S e r v e r ␣ c o n n e c t i n g ␣ t o ␣ p o r t ␣ "+p o r t )
;
try {
c l i e n t C o n n = new S e r v e r S o c k e t ( p o r t ) ; }
catch ( E x c e p t i o n e ) {
System . o u t . p r i n t l n ( " E x c e p t i o n : " + e ) ; System . e x i t ( 1 ) ;
} }
public s t a t i c void main ( S t r i n g [ ] a r g s ) { i n t p o r t = 3 0 0 0 ;
i f ( a r g s . l e n g t h > 0 ) { try {
p o r t = I n t e g e r . p a r s e I n t ( a r g s [ 0 ] ) ; }
catch ( E x c e p t i o n e ) { p o r t = 3 0 0 0 ;
} }
O b j e c t S e r v e r s e r v e r = new O b j e c t S e r v e r ( p o r t ) ;
System . ou t . p r i n t l n ( " S e r v e r ␣ r u n n i n g ␣ on ␣ p o r t ␣ "+p o r t ) ; s e r v e r . l i s t e n ( ) ;
}
public void l i s t e n ( ) { try {
System . o u t . p r i n t l n ( " Waiting ␣ f o r ␣ c l i e n t s . . . " ) ; while ( true ) {
S o c k e t c l i e n t R e q = c l i e n t C o n n . a c c e p t ( ) ; System . ou t . p r i n t l n ( " C o n n e c t i o n ␣ from ␣ "
+ c l i e n t R e q . g e t I n e t A d d r e s s ( ) . getHostName ( ) ) ; s e r v i c e C l i e n t ( c l i e n t R e q ) ;
} }
catch ( I O E x c e p t i o n e ) {
System . o u t . p r i n t l n ( " E x c e p t i o n : " + e ) ; }
}
public void s e r v i c e C l i e n t ( S o c k e t s ) {
System . ou t . p r i n t l n ( "New␣ r e q u e s t ␣ from ␣ " + s . g e t I n e t A d d r e s s ( ) ) ;
O b j e c t I n p u t S t r e a m i n S t r e a m = n u l l ; ObjectOutputStream outStream = n u l l ;
i n t message_id ;
O b j e c t message = n u l l ; try {
outStream = new ObjectOutputStream ( s . getOutputStream ( ) ) ;
i n S t r e a m = new O b j e c t I n p u t S t r e a m ( s . g e t I n p u t S t r e a m ( ) ) ;
message_id = i n S t r e a m . r e a d I n t ( ) ;
System . o u t . p r i n t l n ( "Got␣ message ␣ "+message_id ) ; message = i n S t r e a m . r e a d O b j e c t ( ) ;
switch ( message_id ) { case 1 :
Date d = new Date ( ) ; outStream . w r i t e O b j e c t ( d ) ; break ;
case 2 :
i n t [ ] d a t a = ( i n t [ ] ) message ; i n t sum = 0 ;
f o r ( i n t i =0; i <d a t a . l e n g t h ; i ++) { sum += d a t a [ i ] ;
}
outStream . w r i t e O b j e c t (new I n t e g e r ( sum ) ) ; break ;
case 3 :
S t r i n g s t r = ( S t r i n g ) message ;
outStream . w r i t e O b j e c t ( s t r . toUpperCase ( ) ) ; break ;
}
outStream . f l u s h ( ) ; }
catch ( E x c e p t i o n e ) {
System . o u t . p r i n t l n ( " E x c e p t i o n : " + e ) ; }
System . ou t . p r i n t l n ( "Done . " ) ; }
}
2.2 Klient
/∗
∗ To change t h i s t e m p l a t e , c h o o s e T o o l s | Templates
∗ and open t h e t e m p l a t e i n t h e e d i t o r .
∗/
package j a v a a p p l i c a t i o n 1 ;
import j a v a . i o . ∗ ; import j a v a . n e t . ∗ ; import j a v a . u t i l . ∗ ;
public c l a s s O b j e c t C l i e n t { S t r i n g h o s t ;
i n t p o r t ;
public O b j e c t C l i e n t ( S t r i n g h o s t , i n t p o r t ) { t h i s . h o s t = h o s t ;
t h i s . p o r t = p o r t ; }
public O b j e c t sendMessage ( i n t message_id , O b j e c t message ) throws E x c e p t i o n {
S o c k e t s e r v e r C o n n ;
O b j e c t I n p u t S t r e a m i n S t r e a m = n u l l ; ObjectOutputStream outStream = n u l l ; O b j e c t r e s p o n s e = n u l l ;
s e r v e r C o n n = new S o c k e t ( h o s t , p o r t ) ;
outStream = new ObjectOutputStream ( s e r v e r C o n n . getOutputStream ( ) ) ;
i n S t r e a m = new O b j e c t I n p u t S t r e a m ( s e r v e r C o n n . g e t I n p u t S t r e a m ( ) ) ;
outStream . w r i t e I n t ( message_id ) ; outStream . w r i t e O b j e c t ( message ) ; outStream . f l u s h ( ) ;
r e s p o n s e = i n S t r e a m . r e a d O b j e c t ( ) ; s e r v e r C o n n . c l o s e ( ) ;
return r e s p o n s e ; }
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
O b j e c t C l i e n t c l i e n t = new O b j e c t C l i e n t ( " l o c a l h o s t " , 3 0 0 0 ) ;
S c a n n e r s c a n = new S c a n n e r ( System . i n ) ; boolean end_loop = f a l s e ;
try {
while ( ! end_loop ) {
System . o u t . p r i n t l n ( " \n\ n1 . ␣ Ktora ␣ g o d z i n a ? " ) ; System . o u t . p r i n t l n ( " 2 . ␣Suma␣ l i c z b ␣w␣ t a b l i c y " ) ; System . o u t . p r i n t l n ( " 3 . ␣ M o d y f i k a c j a ␣ t e k s t u " ) ; System . o u t . p r i n t l n ( " 0 . ␣ Koniec " ) ;
char c = s c a n . n e x t L i n e ( ) . charAt ( 0 ) ; switch ( c ) {
case ’ 1 ’ :
Date d = ( Date ) c l i e n t . sendMessage ( 1 , n u l l ) ;
System . ou t . p r i n t l n ( " S e r v e r : ␣ "+d ) ; break ;
case ’ 2 ’ :
i n t [ ] d a t a = new i n t [ 1 0 ] ; f o r ( i n t i =0; i <10; i ++) {
d a t a [ i ] = i +1;
}
I n t e g e r r e s p o n s e = ( I n t e g e r ) c l i e n t . sendMessage ( 2 , d a t a ) ;
System . ou t . p r i n t l n ( " S e r v e r : ␣ "+r e s p o n s e ) ; break ;
case ’ 3 ’ :
System . ou t . p r i n t ( " Wpisz ␣ t e k s t : ␣ " ) ; S t r i n g s t r = s c a n . n e x t L i n e ( ) ;
S t r i n g r = ( S t r i n g ) c l i e n t . sendMessage ( 3 , s t r ) ;
System . ou t . p r i n t l n ( " S e r v e r : ␣ "+r ) ; break ;
case ’ 0 ’ :
end_loop = true ; break ;
} } }
catch ( E x c e p t i o n e ) {
System . o u t . p r i n t l n ( " E x c e p t i o n : " + e ) ; }
} }
3 Przykad 2
... w którym klient otwiera połączenie z serwerem i utrzymuje je podczas wy- konywania poleceń, do momentu jawnego zakończenia pracy przez klienta. Cała komunikacja przebiega w ramach 1 połączenia, które rozpoczynane jest przy uruchomieniu klienta.
3.1 Serwer
/∗
∗ To change t h i s t e m p l a t e , c h o o s e T o o l s | Templates
∗ and open t h e t e m p l a t e i n t h e e d i t o r .
∗/
package j a v a a p p l i c a t i o n 2 ; import j a v a . i o . ∗ ;
import j a v a . n e t . ∗ ; import j a v a . u t i l . ∗ ;
public c l a s s O b j e c t S e r v e r { S e r v e r S o c k e t c l i e n t C o n n ; // O b j e c t O u t p u t S t r e a m o u t ; // O b j e c t I n p u t S t r e a m i n ;
public O b j e c t S e r v e r ( i n t p o r t ) {
System . ou t . p r i n t l n ( " S e r v e r ␣ c o n n e c t i n g ␣ t o ␣ p o r t ␣ " + p o r t ) ;
try {
c l i e n t C o n n = new S e r v e r S o c k e t ( p o r t ) ; } catch ( E x c e p t i o n e ) {
System . o u t . p r i n t l n ( " E x c e p t i o n : " + e ) ; System . e x i t ( 1 ) ;
} }
public s t a t i c void main ( S t r i n g [ ] a r g s ) { i n t p o r t = 3 0 0 0 ;
i f ( a r g s . l e n g t h > 0 ) { try {
p o r t = I n t e g e r . p a r s e I n t ( a r g s [ 0 ] ) ; } catch ( E x c e p t i o n e ) {
p o r t = 3 0 0 0 ; }
}
O b j e c t S e r v e r s e r v e r = new O b j e c t S e r v e r ( p o r t ) ; System . ou t . p r i n t l n ( " S e r v e r ␣ r u n n i n g ␣ on ␣ p o r t ␣ " +
p o r t ) ;
s e r v e r . l i s t e n ( ) ; }
public void l i s t e n ( ) { try {
System . o u t . p r i n t l n ( " Waiting ␣ f o r ␣ c l i e n t s . . . " ) ; while ( true ) {
S o c k e t c l i e n t R e q = c l i e n t C o n n . a c c e p t ( ) ; System . ou t . p r i n t l n ( " C o n n e c t i o n ␣ from ␣ "
+ c l i e n t R e q . g e t I n e t A d d r e s s ( ) . getHostName ( ) ) ;
s e r v i c e C l i e n t ( c l i e n t R e q ) ; }
} catch ( I O E x c e p t i o n e ) {
System . o u t . p r i n t l n ( " E x c e p t i o n : " + e ) ; }
}
public void s e r v i c e C l i e n t ( S o c k e t s ) { ObjectOutputStream outStream ; O b j e c t I n p u t S t r e a m i n S t r e a m ; try {
outStream = new ObjectOutputStream ( s . getOutputStream ( ) ) ;
i n S t r e a m = new O b j e c t I n p u t S t r e a m ( s . g e t I n p u t S t r e a m ( ) ) ;
i n t message_id ;
O b j e c t message = n u l l ; boolean f i n i s h e d = f a l s e ; while ( ! f i n i s h e d ) {
message_id = i n S t r e a m . r e a d I n t ( ) ; System . ou t . p r i n t l n ( "Got␣ message ␣ " +
message_id ) ;
message = i n S t r e a m . r e a d O b j e c t ( ) ; switch ( message_id ) {
case 1 :
Date d = new Date ( ) ; outStream . w r i t e O b j e c t ( d ) ; outStream . f l u s h ( ) ;
break ; case 2 :
i n t [ ] d a t a = ( i n t [ ] ) message ; i n t sum = 0 ;
f o r ( i n t i = 0 ; i < d a t a . l e n g t h ; i ++) {
sum += d a t a [ i ] ; }
outStream . w r i t e O b j e c t (new I n t e g e r ( sum ) ) ;
outStream . f l u s h ( ) ; break ;
case 3 :
S t r i n g s t r = ( S t r i n g ) message ; outStream . w r i t e O b j e c t ( s t r .
toUpperCase ( ) ) ; outStream . f l u s h ( ) ; break ;
case 0 :
outStream . w r i t e O b j e c t ( " bye " ) ; f i n i s h e d = true ;
break ; }
}
} catch ( E x c e p t i o n e ) { e . p r i n t S t a c k T r a c e ( ) ; }
System . ou t . p r i n t l n ( "Done . " ) ; }
}
3.2 Klient
/∗
∗ To change t h i s t e m p l a t e , c h o o s e T o o l s | Templates
∗ and open t h e t e m p l a t e i n t h e e d i t o r .
∗/
package j a v a a p p l i c a t i o n 2 ; import j a v a . i o . ∗ ;
import j a v a . n e t . ∗ ; import j a v a . u t i l . ∗ ;
public c l a s s O b j e c t C l i e n t { S o c k e t s e r v e r C o n n ;
O b j e c t I n p u t S t r e a m i n S t r e a m = n u l l ; ObjectOutputStream outStream = n u l l ;
public O b j e c t C l i e n t ( S t r i n g h o s t , i n t p o r t ) throws UnknownHostException , I O E x c e p t i o n {
s e r v e r C o n n = new S o c k e t ( h o s t , p o r t ) ;
outStream = new ObjectOutputStream ( s e r v e r C o n n . getOutputStream ( ) ) ;
i n S t r e a m = new O b j e c t I n p u t S t r e a m ( s e r v e r C o n n . g e t I n p u t S t r e a m ( ) ) ;
}
public O b j e c t sendMessage ( i n t message_id , O b j e c t message ) throws E x c e p t i o n {
outStream . w r i t e I n t ( message_id ) ; outStream . w r i t e O b j e c t ( message ) ; outStream . f l u s h ( ) ;
O b j e c t r e s p o n s e = i n S t r e a m . r e a d O b j e c t ( ) ; return r e s p o n s e ;
}
public s t a t i c void main ( S t r i n g [ ] a r g s ) { S c a n n e r s c a n = new S c a n n e r ( System . i n ) ; boolean f i n i s h e d = f a l s e ;
try {
O b j e c t C l i e n t c l i e n t = new O b j e c t C l i e n t ( "
l o c a l h o s t " , 3 0 0 0 ) ; while ( ! f i n i s h e d ) {
System . ou t . p r i n t l n ( " \n\ n1 . ␣ Ktora ␣ g o d z i n a ?
" ) ;
System . ou t . p r i n t l n ( " 2 . ␣Suma␣ l i c z b ␣w␣
t a b l i c y " ) ;
System . ou t . p r i n t l n ( " 3 . ␣ M o d y f i k a c j a ␣ t e k s t u
" ) ;
System . ou t . p r i n t l n ( " 0 . ␣ Koniec " ) ; char c = s c a n . n e x t L i n e ( ) . charAt ( 0 ) ; switch ( c ) {
case ’ 1 ’ :
Date d = ( Date ) c l i e n t . sendMessage ( 1 , n u l l ) ;
System . o u t . p r i n t l n ( " S e r v e r : ␣ " + d ) ;
break ; case ’ 2 ’ :
i n t [ ] d a t a = new i n t [ 1 0 ] ; f o r ( i n t i = 0 ; i < 1 0 ; i ++) {
d a t a [ i ] = i + 1 ; }
I n t e g e r r e s p o n s e = ( I n t e g e r ) c l i e n t . sendMessage ( 2 , d a t a ) ; System . o u t . p r i n t l n ( " S e r v e r : ␣ " +
r e s p o n s e ) ; break ;
case ’ 3 ’ :
System . o u t . p r i n t ( " Wpisz ␣ t e k s t : ␣ " )
;
S t r i n g s t r = s c a n . n e x t L i n e ( ) ;
S t r i n g r = ( S t r i n g ) c l i e n t . sendMessage ( 3 , s t r ) ;
System . o u t . p r i n t l n ( " S e r v e r : ␣ " + r ) ;
break ; case ’ 0 ’ :
System . o u t . p r i n t l n ( " S e r v e r ␣ s a y s : ␣
" + ( S t r i n g ) c l i e n t . sendMessage ( 0 , n u l l ) ) ;
c l i e n t . s e r v e r C o n n . c l o s e ( ) ; f i n i s h e d = true ;
break ; }
}
} catch ( E x c e p t i o n e ) {
System . o u t . p r i n t l n ( " E x c e p t i o n : " + e ) ; e . p r i n t S t a c k T r a c e ( ) ;
} } }
4 Zadanie
Stwórz aplikację klient-serwer, która pozwoli na zachowanie kopii zapasowej pli- ków klienta (z wybranego katalogu, który może być podany bezpośrednio w kodzie) po stronie serwera, oraz na przywrócenie kopii z serwera do klienta.
Serwer powinien móc obsłużyć następujące żądania klienta:
• czy plik x znajduje się na serwerze?
• czy plik x znajdujący się serwerze jest taki sam jak u klienta (to można stwierdzić porównując sumy kontrolne plików)?
• odebranie pliku od klienta i zapisanie go w określonym miejscu na dysku
• przesłanie pliku klientowi (klient powinien zapisać ten plik w określonej lokalizacji)
Po napisaniu serwera, rozszerz go tak, żeby mogło z niego korzystać wielu klien- tów. Dodatkowo, dopisz do klienta funkcjonalność umożliwiającą wyświetlenie raportu wskazującego które pliki mają swoją kopię na serwerze wraz z informa- cją czy jest ona identyczna z tą u klienta. Zastanów się jak możnaby obsłużyć usuwanie plików.