Cliente-Servidor e Multicast - Inf

Propaganda
INF01018
– Aula Prática 1 –
Cliente-Servidor e Multicast
Lucas Mello Schnorr, Alexandre Silva Carı́ssimi
{lmschnorr,asc}@inf.ufrgs.br
http://www.inf.ufrgs.br/∼lmschnorr/ad/
INF01018 – Sistemas Operacionais
Distribuı́dos e de Redes
Sala 102 – Prédio 67 – 05 Setembro 2006
1 / 30
Roteiro
1
Introdução
2
Cliente-Servidor
3
Multicast
4
Referências
2 / 30
Introdução
Dar suporte às aulas teóricas 04 e 05
Utilização de exemplos com código fonte
Duas linguagens de programação: Java e C
Programas Cliente/Servidor e Multicast
Download de Exemplos
http://www.inf.ufrgs.br/∼lmschnorr/ad/aula1.tar.gz
3 / 30
Introdução – Parte do Cliente/Servidor
Do lado do servidor
Recebe comandos dos clientes
Se comando for igual a hora, enviar hora local ao
cliente
Se comando não for conhecido, envia mensagem ao
cliente avisando
Do lado do cliente
Cria uma datagrama com o comando
Envia ao servidor
Aguarda uma resposta
4 / 30
Introdução – Parte do Multicast
Dois programas
Programa Receptor
Cria um socket multicast
Faz bind desse socket a um endereço multicast
Aguarda mensagens do socket e imprime na tela
Programa Enviador
Cria um socket multicast
Entra no grupo multicast
Envia uma mensagem ao grupo
5 / 30
Cliente-Servidor
UDP
Serviço orientado a Datagramas
Sem confirmação de recebimento ou retentativas
Do lado do servidor
Recebe comandos dos clientes
Se comando for igual a hora, enviar hora local ao
cliente
Se comando não for conhecido, envia mensagem ao
cliente avisando
Do lado do cliente
Cria uma datagrama com o comando
Envia ao servidor
Aguarda uma resposta
6 / 30
UDP usando a linguagem C
Principais funções
socket (int domain, int type, int protocol)
bind (int sockfd, struct sockaddr *addr, socklen t len)
recvfrom (int s, void *buf, size t len, int flags,
struct sockaddr *from, socklen t *fromlen)
sendto (int s, const void *buf, size t len, int flags,
const struct sockaddr *to, socklen t tolen)
7 / 30
Cliente-Servidor UDP em C – 1/3
Códigos retirados do arquivo ServidorUDP.c
30
31
32
33
/ ∗ c r i a r s o c k e t UDP para r e c e b e r ou e n v i a r datagramas ∗ /
i f ( ( sock = socket ( PF INET , SOCK DGRAM, IPPROTO UDP ) ) < 0 ) {
p e r r o r ( ” sock ( ) f a l h o u ” ) ;
}
35
36
37
38
39
/ ∗ c o n s t r u i r a e s t r u t u r a de endereco l o c a l ∗ /
memset (& echoServAddr , 0 , s iz e o f ( echoServAddr ) ) ;
echoServAddr . s i n f a m i l y = AF INET ;
echoServAddr . s i n a d d r . s a d d r = h t o n l ( INADDR ANY ) ;
echoServAddr . s i n p o r t = htons ( numeroPorta ) ;
41
42
43
44
45
/ ∗ Bind ao endereco l o c a l ∗ /
i f ( bind ( sock , ( s t r u c t sockaddr ∗ ) & echoServAddr ,
s iz e o f ( echoServAddr ) ) < 0 ) {
perror ( ” bind ( ) falhou ” ) ;
}
8 / 30
Cliente-Servidor UDP em C – 2/3
Códigos retirados do arquivo ServidorUDP.c
47
48
49
50
51
52
53
54
55
56
68
69
70
71
72
73
while ( 1 ) {
/ ∗ e s p e r a r mensagem de alguem ∗ /
c l i A d d r L e n = s iz e o f ( echoClntAddr ) ;
i f ( ( recvMsgSize = recvfrom ( sock , echoBuffer , ECHOMAX, 0 ,
( s t r u c t sockaddr ∗ ) & echoClntAddr , & c l i A d d r L e n ) ) < 0 ) {
p e r r o r ( ” r e c v fr o m ( ) f a l h o u ” ) ;
}
p r i n t f ( ” Recebeu c l i e n t e %s\n ” ,
i n e t n t o a ( echoClntAddr . s i n a d d r ) ) ;
p r i n t f ( ” ==> [%s ] %d\n ” , echoBuffer , c l i A d d r L e n ) ;
/ ∗ e n v i a r a HORA para o c l i e n t e ∗ /
i n t bytesEnviados = sendto ( sock , t i m e s t r i n g ,
s iz e o f ( t i m e s t r i n g ) , 0 ,
( s t r u c t sockaddr ∗ ) & echoClntAddr ,
s iz e o f ( echoClntAddr ) ) ;
p r i n t f ( ” enviando %d\n ” , bytesEnviados ) ;
9 / 30
Cliente-Servidor UDP em C – 3/3
Códigos retirados do arquivo ClienteUDP.c
36
37
38
39
/ ∗ c r i a r um s o c k e t UDP ∗ /
i f ( ( sock = socket ( PF INET , SOCK DGRAM, IPPROTO UDP ) ) < 0 ) {
p e r r o r ( ” socket ( ) falhou ” ) ;
}
41
42
43
44
45
/ ∗ c o n s t r u i r a e s t r u t u r a de endereco do s e r v i d o r ∗ /
memset (& echoServAddr , 0 , s iz e o f ( echoServAddr ) ) ;
echoServAddr . s i n f a m i l y = AF INET ;
echoServAddr . s i n a d d r . s a d d r = i n e t a d d r ( nomeServidor ) ;
echoServAddr . s i n p o r t
= htons ( numeroPorta ) ;
47
48
49
50
/ ∗ e n v i a r o comando para o s e r v i d o r ∗ /
sendto ( sock , mensagem , tamanhoMensagem+ 1 , 0 ,
( s t r u c t sockaddr ∗ ) & echoServAddr ,
s iz e o f ( echoServAddr ) ) ;
52
53
54
55
/ ∗ r e c e b e r uma r e s p o s ta ∗ /
fromSize = s iz e o f ( fromAddr ) ;
r e s p S tr i n g L e n = recvfrom ( sock , echoBuffer , ECHOMAX, 0 ,
( s t r u c t sockaddr ∗ ) & fromAddr , & fromSize ) ;
10 / 30
UDP usando a linguagem Java
Classes utilizadas
DatagramSocket
new DatagramSocket (int porta)
DatagramPacket
new DatagramPacket (byte[] b, int length)
new DatagramPacket (byte[] buf, int length,
InetAddress address, int port)
11 / 30
Cliente-Servidor UDP em Java – 1/3
Códigos retirados do arquivo ServidorUDP.java
18
19
20
/ ∗ I n i c i a l i z a c a o do s o c k e t UDP ∗ /
s o c k e t = new DatagramSocket (
new I n t e g e r ( numeroPorta ) . i n t V a l u e ( ) ) ;
22
23
24
25
26
27
28
29
/ ∗ Laco de recebimento de datagramas ∗ /
while ( t r u e ) {
request = n u l l ;
reply = nu ll ;
b u f = new b y te [ 1 0 2 4 ] ;
31
32
33
34
35
36
/ ∗ Recepcao bloqueante dos dados ∗ /
socket . receive ( request ) ;
/ ∗ Preparacao do Datagrama de Recepcao ∗ /
r e q u e s t = new DatagramPacket ( buf , b u f . l e n g t h ) ;
/ ∗ Recuperacao do comando ∗ /
comando = new S t r i n g ( r e q u e s t . getData ( ) , 0 ,
r e q u e s t . getLength ( ) ) ;
12 / 30
Cliente-Servidor UDP em Java – 2/3
Códigos retirados do arquivo ServidorUDP.java
43
44
45
46
47
56
57
/ ∗ C r i a datagrama com a r e s p o s ta ∗ /
r e p l y = new DatagramPacket ( hora . g e tB y te s ( ) ,
hora . g e tB y te s ( ) . l e n g th ,
r e q u e s t . getAddress ( ) ,
request . getPort ( ) ) ;
/ ∗ Envia r e s p o s ta p e l o s o c k e t UDP ∗ /
s o c k e t . send ( r e p l y ) ;
13 / 30
Cliente-Servidor UDP em Java – 3/3
Códigos retirados do arquivo ClienteUDP.java
20
21
/ ∗ I n i c i a l i z a c a o de s o c k e ts UDP com Datagrama ∗ /
s o c k e t = new DatagramSocket ( ) ;
23
24
25
26
27
28
29
/ ∗ Configuracao a p a r t i r dos parametros ∗ /
In e tA d d r e s s h o s t = In e tA d d r e s s . getByName ( nomeServidor ) ;
s e r v e r P o r t = new I n t e g e r ( numeroPorta ) . i n t V a l u e ( ) ;
b y te [ ] m = mensagemEnviar . g e tB y te s ( ) ;
31
32
/ ∗ Envio p r o p r i a m e n te d i t o ∗ /
s o c k e t . send ( r e q u e s t ) ;
34
35
36
37
38
/ ∗ Preparacao do Pacote Datagrama para Recepcao ∗ /
r e p l y = new DatagramPacket ( buf , b u f . l e n g t h ) ;
/ ∗ Criacao do Pacote Datagrama para Envio ∗ /
r e q u e s t = new DatagramPacket (m, m. l e n g th , host , s e r v e r P o r t ) ;
/ ∗ Recepcao do r e t o r n o ∗ /
socket . receive ( r e p l y ) ;
14 / 30
Cliente-Servidor em TCP
TCP
Orientado a conexão (stream)
Confiabilidade e Integridade
Menos desempenho na comunicação
15 / 30
TCP usando a linguagem C
Principais funções
socket (int domain, int type, int protocol)
bind (int sockfd, struct sockaddr *addr, socklen t len)
listen (int sockfd, int backlog)
accept (int sockfd, struct sockaddr *addr, socklen t
*addrlen);
send (int s, const void *buf, size t len, int flags);
recv (int s, void *buf, size t len, int flags);
connect (int sockfd, const struct sockaddr *serv addr,
socklen t addrlen);
16 / 30
Cliente-Servidor TCP em C – 1/4
Códigos retirados do arquivo ServidorTCP.c
36
37
38
39
40
/ ∗ Criacao do s o c k e t TCP para r e c e b e r conexoes ∗ /
i f ( ( servSock = socket ( PF INET , SOCK STREAM , IPPROTO TCP)) <0){
p e r r o r ( ” socket ( ) falhou ” ) ;
exit (1);
}
43
44
45
46
47
/ ∗ c o n s tr u c a o do endereco de conexao ∗ /
memset (& echoServAddr , 0 , s iz e o f ( echoServAddr ) ) ;
echoServAddr . s i n f a m i l y = AF INET ;
echoServAddr . s i n a d d r . s a d d r = h t o n l ( INADDR ANY ) ;
echoServAddr . s i n p o r t = htons ( numeroPorta ) ;
49
50
51
52
53
54
/ ∗ Bind ao endereco l o c a l ∗ /
i f ( bind ( servSock , ( s t r u c t sockaddr ∗ ) & echoServAddr ,
s iz e o f ( echoServAddr ) ) < 0 ) {
perror ( ” bind ( ) falhou ” ) ;
exit (1);
}
17 / 30
Cliente-Servidor TCP em C – 2/4
Códigos retirados do arquivo ServidorTCP.c
57
58
59
60
61
/∗ l i s t e n ∗/
i f ( l i s t e n ( servSock , MAXPENDING) < 0 ) {
perror ( ” l i s t e n ( ) falhou ” ) ;
exit (1);
}
64
65
66
67
68
69
70
71
72
while ( 1 ) {
/ ∗ esperando conexoes com accept ∗ /
c l n t L e n = s iz e o f ( echoClntAddr ) ;
i f ( ( c l n t S o c k = accept ( servSock ,
( s t r u c t sockaddr ∗ ) & echoClntAddr ,
&clntLen ) ) < 0 ) {
p e r r o r ( ” accept ( ) f a l h o u ” ) ;
exit (1);
}
18 / 30
Cliente-Servidor TCP em C – 3/4
Códigos retirados do arquivo ServidorTCP.c
74
75
76
77
78
79
80
81
82
/ ∗ c l n t S o c k e s ta conectado a um c l i e n t e ∗ /
p r i n t f ( ” Tratando c l i e n t e %s\n ” ,
i n e t n t o a ( echoClntAddr . s i n a d d r ) ) ;
while ( 1 ) {
i f ( ( tamanhoRecebido = recv ( c l n tS o c k , comando ,
RCVBUFSIZE , 0 ) ) < 0 ) {
p e r r o r ( ” r e c v ( ) f a l h o u \n ” ) ;
exit (1);
}
94
95
/ ∗ enviando dados ao c l i e n t e ∗ /
i n t k = send ( c l n tS o c k , t i m e s t r i n g , s iz e o f ( t i m e s t r i n g ) , 0 ) ;
19 / 30
Cliente-Servidor TCP em C – 4/4
Códigos retirados do arquivo ClienteTCP.c
34
35
/ ∗ Criacao do Socket TCP ∗ /
sock = socket ( PF INET , SOCK STREAM , IPPROTO TCP ) ;
37
38
39
40
41
/ ∗ c o n s tr u c a o do endereco de conexao ∗ /
memset (& echoServAddr , 0 , s iz e o f ( echoServAddr ) ) ;
echoServAddr . s i n f a m i l y = AF INET ;
echoServAddr . s i n a d d r . s a d d r = i n e t a d d r ( e n d e r e c o IP S e r v i d o r ) ;
echoServAddr . s i n p o r t = htons ( numeroPorta ) ;
43
44
45
46
47
48
/ ∗ Conectando ao s e r v i d o r ∗ /
i f ( connect ( sock , ( s t r u c t sockaddr ∗ ) & echoServAddr ,
s iz e o f ( echoServAddr ) ) < 0 ) {
p e r r o r ( ” connect ( ) f a l h o u : ” ) ;
exit (1);
}
20 / 30
TCP usando a linguagem Java
Principais Classes
ServerSocket (int port)
PrintWriter (OutputStream out, boolean autoFlush)
BufferedReader (Reader in)
21 / 30
Cliente-Servidor TCP em Java – 1/2
Códigos retirados do arquivo ServidorTCP.java
20
21
22
/ ∗ I n i c i a l i z a c a o do s e r v e r s o c k e t TCP ∗ /
s e r v e r S o c k e t = new ServerSocket (
new I n t e g e r ( numeroPorta ) . i n t V a l u e ( ) ) ;
24
25
26
while ( t r u e ) {
/ ∗ Espera por um c l i e n t e ∗ /
c l i e n t S o c k e t = s e r v e r S o c k e t . accept ( ) ;
29
30
31
32
33
/ ∗ Preparacao dos f l u x o s de e n tr a d a e s a i d a ∗ /
o u t = new P r i n t W r i t e r ( c l i e n t S o c k e t . getOutputStream ( ) ,
true ) ;
i n = new BufferedReader ( new InputStreamReader (
c l i e n t S o c k e t . g e tIn p u tS tr e a m ( ) ) ) ;
35
36
/ ∗ Recuperacao dos comandos ∗ /
while ( ( comando = i n . r e a d L i n e ( ) ) ! = n u l l ) {
42
43
/ ∗ Escreve na s a i d a a ’ hora ’ ∗ /
o u t . p r i n t l n ( hora ) ;
22 / 30
Cliente-Servidor TCP em Java – 2/2
Códigos retirados do arquivo ClienteTCP.java
17
18
19
/ ∗ I n i c i a l i z a c a o de s o c k e t TCP ∗ /
socket = new Socket ( nomeServidor ,
new I n t e g e r ( numeroPorta ) . i n t V a l u e ( ) ) ;
21
22
23
24
/ ∗ I n i c i a l i z a c a o dos f l u x o s de e n tr a d a e s a i d a ∗ /
i n = new BufferedReader ( new InputStreamReader (
socket . g e tIn p u tS tr e a m ( ) ) ) ;
o u t = new P r i n t W r i t e r ( socket . getOutputStream ( ) , t r u e ) ;
30
31
32
33
34
35
36
while ( ( mensagemEnviar = inReader . r e a d L i n e ( ) ) ! = n u l l ) {
45
46
47
out . close ( ) ;
i n . close ( ) ;
socket . c l o s e ( ) ;
/ ∗ Envio da mensagem ∗ /
o u t . p r i n t l n ( mensagemEnviar ) ;
/ ∗ Recebimento da r e s p o s ta do s e r v i d o r ∗ /
S t r i n g r e s p o s ta = i n . r e a d L i n e ( ) ;
23 / 30
Multicast
Utilizado com suporte da camada Ethernet
Quando sem esse suporte, utiliza vários Unicast
Conceito de grupo
24 / 30
Multicast usando a linguagem C
Principais funções
setsockopt (int s, int level, int optname,
const void *optval, socklen t optlen);
25 / 30
Multicast em C – 1/3
Códigos retirados do arquivo MulticastReceiver.c
28
29
30
i f ( ( sock = socket ( PF INET , SOCK DGRAM, IPPROTO UDP ) ) < 0 ) {
p r i n t f ( ” s o c k e t ( ) f a l h o u \n ” ) ;
}
32
33
34
35
36
/ ∗ c o n s t r u i r a e s t r u t u r a de endereco para o b i n d ∗ /
memset (& m u l t i c a s t A d d r , 0 , s iz e o f ( m u l t i c a s t A d d r ) ) ;
m u l t i c a s t A d d r . s i n f a m i l y = AF INET ;
m u l t i c a s t A d d r . s i n a d d r . s a d d r = h t o n l ( INADDR ANY ) ;
m u l t i c a s t A d d r . s i n p o r t = htons ( m u l t i c a s t P o r t ) ;
38
39
40
41
42
/∗ bind ∗/
i f ( bind ( sock , ( s t r u c t sockaddr ∗ ) & m u l t i c a s t A d d r ,
s iz e o f ( m u l t i c a s t A d d r ) ) < 0 ) {
p r i n t f ( ” b i n d ( ) f a l h o u \n ” ) ;
}
26 / 30
Multicast em C – 2/3
Códigos retirados do arquivo MulticastReceiver.c
44
45
46
47
48
49
50
51
52
/ ∗ a c e r t a r opcoes do m u l t i c a s t ∗ /
multicastRequest . i mr mul ti addr . s addr =
inet addr ( multicastIP ) ;
m u l t i c a s t R e q u e s t . i m r i n t e r f a c e . s a d d r = h t o n l ( INADDR ANY ) ;
i f ( setsockopt ( sock , IPPROTO IP , IP ADD MEMBERSHIP ,
( void ∗ ) & m u l ti c a s tR e q u e s t ,
s iz e o f ( m u l t i c a s t R e q u e s t ) ) < 0 ) {
p r i n t f ( ” s e ts o c k o p t ( ) f a l h o u \n ” ) ;
}
54
55
56
57
58
59
/ ∗ Receive a s i n g l e datagram from th e s e r v e r ∗ /
while ( 1 ) {
i f ( ( r e c v S t r i n g L e n = r e c v fr o m ( sock , r e c v S t r i n g ,
MAXRECVSTRING, 0 , NULL , 0 ) ) < 0 ) {
p r i n t f ( ” r e c v fr o m ( ) f a l h o u \n ” ) ;
}
27 / 30
Multicast em C – 3/3
Códigos retirados do arquivo MulticastSender.c
30
31
32
i f ( ( sock = socket ( PF INET , SOCK DGRAM, IPPROTO UDP ) ) < 0 ) {
p r i n t f ( ” s o c k e t ( ) f a l h o u \n ” ) ;
}
39
40
41
42
memset ( & m u l t i c a s t A d d r , 0 , s iz e o f ( m u l t i c a s t A d d r ) ) ;
m u l t i c a s t A d d r . s i n f a m i l y = AF INET ;
multicastAddr . si n addr . s addr = i net addr ( mul ti castIP ) ;
m u l t i c a s t A d d r . s i n p o r t = htons ( m u l t i c a s t P o r t ) ;
50
51
52
i n t k = sendto ( sock , s e n d S tr i n g , sendStringLen , 0 ,
( s t r u c t sockaddr ∗ ) & m u l t i c a s t A d d r ,
s iz e o f ( m u l t i c a s t A d d r ) ) ;
28 / 30
Multicast usando a linguagem Java
Principais classes
MulticastSocket (int port)
DatagramPacket (byte[] buf, int length)
29 / 30
Multicast em Java – 1/3
Códigos retirados do arquivo ServidorMulticast.java
11
MulticastSocket socket = new MulticastSocket ( p o r t a ) ;
12
13
In e tA d d r e s s endereco = In e tA d d r e s s . getByName ( args [ 1 ] ) ;
socket . j o i n G r o u p ( endereco ) ;
15
16
17
18
19
20
while ( t r u e ) {
b y te [ ] recvData = new b y te [ 1 0 2 4 ] ;
DatagramPacket recvPacket ;
recvPacket = new DatagramPacket ( recvData ,
recvData . l e n g t h ) ;
socket . r e c e i v e ( recvPacket ) ;
23
24
25
26
sentence = new S t r i n g ( recvPacket . getData ( ) ) ;
System . o u t . p r i n t
( recvPacket . getAddress ( ) . t o S t r i n g ( ) + ” : ” ) ;
System . o u t . p r i n t l n ( sentence ) ;
30 / 30
Multicast em Java – 1/3
Códigos retirados do arquivo ClienteMulticast.java
13
MulticastSocket c l i e n t S o c k e t = new MulticastSocket ( ) ;
14
15
In e tA d d r e s s endereco = In e tA d d r e s s . getByName ( args [ 1 ] ) ;
c l i e n t S o c k e t . j o i n G r o u p ( endereco ) ;
26
27
28
29
34
35
sendPacket = new DatagramPacket ( sendData ,
sendData . l e n g th , endereco , p o r t a ) ;
c l i e n t S o c k e t . setTimeToLive ( t t l ) ;
c l i e n t S o c k e t . send ( sendPacket ) ;
c l i e n t S o c k e t . leaveGroup ( endereco ) ;
cl i e n tSo cke t . close ( ) ;
31 / 30
Referências
Man pages no Linux para funções C
Especificação das classes Java na Internet
32 / 30
Download