Você está na página 1de 49

SCE5777

Sistemas Distribudos
Comunicao em Sistemas Distribudos
Sockets
4 aula
26/08/08
Profa. Sarita Mazzini Bruschi
sarita@icmc.usp.br
Slides baseados no material de:
Prof. Edmilson Marmo Moreira (UNIFEI / IESTI)
1

Sockets
Introduo


Uma rede de computadores composta por


mquinas interconectadas e canais de
comunicao que permitem a transmisso de
bytes de uma mquina para outra
No TCP/IP, para um programa comunicar
com outro, ele utiliza duas informaes:



Endereo Internet: usado pelo protocolo IP


Nmero de porta: utilizado pelo protocolo de
transporte (UDP ou TCP)
2

Sockets
Definio


Um socket uma abstrao atravs da qual


uma aplicao pode enviar e receber dados,
de uma maneira semelhante utilizada para
ler e escrever em arquivos
Uma abstrao
socket pode ser
referenciada por
diversos
programas
usurios


Sockets
usando Java

Sockets
Conceitos Bsicos


Um cliente deve utilizar o endereo IP do servidor


para iniciar uma comunicao
Em Java, o endereo pode ser especificado usando
uma string que contm o endereo IP ou o nome
correspondente
O endereo IP encapsulado na classe
InetAddress que prov 3 mtodos estticos:




getByName
getAllByName
getHostAddress

Sockets
Exemplo
import java.net.*; // for InetAddress
class InetAddressExample {
public static void main (String[] args) {
// Get name and IP address of the local host
try {
InetAddress address = InetAddress.getLocalHost();
System.out.println("Local Host:");
System.out.println("\t" + address.getHostName());
System.out.println("\t" + address.getHostAddress());
} catch (UnknownHostException e) {System.out.println("Unable to determine
this host's address");}
for (int i=0; i < args.length; i++) {
// Get name(s)/address(es) of hosts given on command line
try {
InetAddress[] addressList =
InetAddress.getAllByName(args[i]);
System.out.println(args[i] + ":");
System.out.println("\t" + addressList[0].getHostName());
for (int j=0; j < addressList.length; j++)
System.out.println ("\t" +
addressList[j].getHostAddress());
} catch (UnknownHostException e) {System.out.println("Unable to
find address for" + args[i]);}
}
}
}
6

Sockets
TCP


Java fornece duas classes para trabalhar


com o TCP:



Socket
ServerSocket

Uma instncia de Socket representa uma


conexo de TCP fim-a-fim


Um canal cujas pontas so indentificadas por um


endereo IP e um nmero de porta

Sockets
TCP


Perodo de Setup


Perodo que se inicia com o cliente enviando uma


requisio de conexo para o servidor

Uma instncia de ServerSocket aguarda


conexes TCP e cria uma nova instncia de
Socket para manipular os pedidos de
conexo

Sockets
TCP
Cliente TCP




Os clientes iniciam a comunicao com um servidor que


est passivamente aguardando por uma conexo
Um cliente tpico segue os seguintes passos:
1.

2.

3.

Constri uma instncia de Socket: o construtor estabelece


uma conexo TCP para um host e uma porta especificada;
Comunica-se utilizando o sockets I/O stream: uma instncia
de Socket contm objetos InputStream e OutputStream
que pode ser utilizado como qualquer outro Java I/O stream
Encerra a conexo utilizando o mtodo close() da classe
Socket

Sockets
TCP Exemplo - Cliente
import java.net.*; // for Socket
import java.io.*; // for IOException and Input/OutputStream
public class TCPEchoClient {
public static void main (String[] args) throws IOException {
if ((args.length < 2) || (args.length > 3))
throw new IllegalArgumentException ("Parameter(s): <Server> <Word> [<Port>]");
String server = args[0];
// Convert input String to bytes using the default character
// encoding
byte[] byteBuffer = args[1].getBytes();
int servPort=(args.length == 3) ? Integer.parseInt(args[2]) :7;
// Create socket that is connected to server on specified port
Socket socket = new Socket(server, servPort);
System.out.println("Connected to server... sending echo string");
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
out.write(byteBuffer); // Send the encoded string to the server
// Receive the same string back from the server
int totalBytesRcvd = 0;
int bytesRcvd;
while (totalBytesRcvd < byteBuffer.length) {
if ((bytesRcvd = in.read(byteBuffer, totalBytesRcvd, byteBuffer.length - totalBytesRcvd)) == -1)
throw new SocketException("Connection closed prematurely");
totalBytesRcvd += bytesRcvd;
}
System.out.println("Received: " + new String(byteBuffer));
socket.close();
}
}

10

Sockets
TCP
Servidor TCP
A tarefa do servidor preparar o canal de chegada dos pedidos
e aguardar por conexes dos clientes
Um servidor tpico segue os seguintes passos:


1.

2.

Cria uma instncia local da classe ServerSocket, especificando


uma porta local. Esse objeto fica ouvindo a porta, aguardando por
pedidos de conexo
Repetidamente





Chama o mtodo accetp() do ServerSocket para obter a prxima


conexo dos clientes. Quanto um novo cliente se conecta, uma nova
instncia da classe Socket criada e retornada pelo mtodo accept()
Comunica-se com o cliente usando os objetos InputStream e
OutputStream do objeto Socket
Encerra a conexo com o cliente usando o mtodo close() da classe
Socket

11

Sockets
TCP Exemplo - Servidor
import java.net.*; // for Socket, ServerSocket
import java.io.*; // for IOException and Input/OutputStream
public class TCPEchoServer {
private static final int BUFSIZE = 32; // Size of receive buffer
public static void main (String[] args) throws IOException {
if (args.length != 1)
throw new IllegalArgumentException("Parameter(s): <Port>");
int servPort = Integer.parseInt(args[0]);
// Create a server socket to accept client connection requests
ServerSocket servSock = new ServerSocket(servPort);
int recvMsgSize; // Size of receive message
byte[] byteBuffer = new byte[BUFSIZE]; // Receive buffer
for (;;) { // Run forever, accpeting and servicing connections
Socket clntSock = servSock.accept(); // Get client connection
System.out.println("Handling client at " +
clntSock.getInetAddress().getHostAddress() + " on port " + clntSock.getPort());
InputStream in = clntSock.getInputStream();
OutputStream out = clntSock.getOutputStream();
// Receive until client closes connection,
// indicated by -1 return
while ((recvMsgSize = in.read(byteBuffer)) != -1)
out.write(byteBuffer, 0, recvMsgSize);
clntSock.close(); // Close de socket.
// We are done with this client
}
/* NOT REACHED */
}
}

12

Sockets
UDP


O socket UDP prov um servio diferente de


comunicao em relao ao protocolo TCP
O UDP executa somente duas funes:


Adiciona outra camada de endereamento


(portas) para o IP;
Detecta dados corrompidos que podem ocorrer
na transmisso das mensagens

13

Sockets
UDP


Caractersticas



No precisam ser conectados antes de serem utilizados


Cada mensagem carrega as prprias informaes de
endereamento, sendo independente das outras
mensagens
Durante o recebimento, funciona como uma caixa de
correio onde cartas e pacotes de diferentes lugares podem
ser colocados
Assim que criado, um socket UDP pode ser usado para
enviar e receber mensagens para qualquer endereo
No h garantias de quem uma mensagem enviada por
um socket UPD chegar ao seu destino
As mensagens podem ser entregues fora de ordem
14

Sockets
UDP


Java fornece duas classes para trabalhar


com UDP:



DatagramPacket
DatagramSocket

Clientes e servidores utilizam


DatagramSockets para enviar e receber
DatagramPackets

15

Sockets
UDP


DatagramPacket


Ao invs de enviar streams, como o TCP, o UDP


envia mensagens autocontidas, denominadas
datagramas, que so representadas em Java
como instncias DatagramPacket
Para enviar uma mensagem, um programa Java
constri uma instncia de DatagramPacket e
passa como argumento para o mtodo Send()
da classe DatagramSocket

16

Sockets
UDP


DatagramPacket


Para receber uma mensagem, um programa Java


cria uma instncia de DatagramPacket com
espao pr-alocado de memria (objeto byte[]),
onde o contedo da mensagem recebida pode
ser copiado e passa a respectiva instncia para o
mtodo receive() da classe DatagramPacket

17

Sockets
UDP


DatagramPacket
 Cada instncia de DatagramPacket tambm
contm informaes de endereos e portas
 Quando um DatagramPacket enviado, o
endereo e a porta identificam o destinatrio
 Quanto um DatagramPacket recebido, o
endereo identifica o remetente
 Quando um DatagramPacket recebido no
servidor, este pode modificar seu contedo e
enviar o mesmo DatagramPacket
18

Sockets
UDP
Cliente UDP




Os clientes iniciam a comunicao enviando um


datagrama para um servidor que est passivamente
Um cliente UDP tpico segue os seguintes passos:
1.

2.

3.

Constri uma instncia de DatagramPacket, opcionalmente


indicando o endereo e a porta
Comunica-se atravs do envio e do recebimento de
instncias de DatagramPacket usando os mtodos send()
e receive() da classe DatagramPacket
Quanto finaliza, desaloca o socket usando o mtodo close()
da classe DatagramPacket

19

Sockets
UDP Exemplo Cliente
import java.net.*; // for DatagramSocket,DatagramPacket,InetAddress
import java.io.*; // for IOException
public class UDPEchoClientTimeout {
private static final int TIMEOUT = 3000; // Resend timeout
private static final int MAXTRIES = 5; // Maximum retransmissions
public static void main (String[] args) throws IOException {
if ((args.length < 2) || (args.length > 3))
throw new IllegalArgumentException("Parameter(s): <Server> <Word> [<Port>]");
InetAddress serverAddress = InetAddress.getByName(args[0]);
// Convert the argument String to bytes using the
// default encoding
byte[] bytesToSend = args[1].getBytes();
int servPort = (args.length == 3) ? Integer.parseInt(args[2]):7;
DatagramSocket socket = new DatagramSocket();
socket.setSoTimeout(TIMEOUT); // Maximum receive blocking time
DatagramPacket sendPacket = new DatagramPacket(bytesToSend, bytesToSend.length, serverAddress,
servPort);
DatagramPacket receivePacket = new DatagramPacket (new byte[bytesToSend.length],
bytesToSend.length);
int tries = 0;
boolean receivedResponse = false;

20

Sockets
UDP Exemplo Cliente (continuo)
do {
socket.send(sendPacket); // Send the echo string
try {
socket.receive(receivePacket); // Attempt echo reply
// reception
// Check source
if (!receivePacket.getAddress().equals(serverAddress))
throw new IOException("Received packet from an unknown source");
receivedResponse = true;
} catch (InterruptedIOException e) { // We didn't get anything
tries += 1;
System.out.println("Timed out, " + (MAXTRIES - tries) + " more tries ...");
}
} while ((!receivedResponse) && (tries < MAXTRIES));
if (receivedResponse)
{
System.out.println("Received: " + new String(receivePacket.getData()));
System.out.println("Porta: " + (int)socket.getPort());
}
else
System.out.println("No response -- giving up.");
socket.close();
}
}

21

Sockets
UDP


Servidor UDP


Como um servidor TCP, um servidor UDP


inicializado e aguarda passivamente por um
cliente
Como no h a necessidade de se estabelecer
conexo, a comunicao UDP iniciada assim
que chega um datagrama

22

Sockets
UDP
Servidor UDP

Um servidor UDP tpico segue os seguintes passos:


1.

2.

3.

4.

Cria uma instncia da classe DatagramPacket, especificando uma


porta local e, opcionalmente, um endereo local. O servidor est
pronto para receber datagramas de qualquer cliente
Recebe uma instncia de DatagramPacket usando o mtodo
receive() da classe DatagramPacket. Quando receive()
retorna, o datagrama contm o endereo do cliente. Desta forma, o
servidor reconhece o destinatrio da resposta
Comunica-se com os clientes pelo envio e recebimento de
DatagramPackets usando os mtodos send() e receive() da
classe DatagramPacket
Quando finalizado, deloca-se o socket usando o mtodo close()
da classe DatagramPacket

23

Sockets
UDP Exemplo Servidor
import java.net.*; // for DatagramSocket and DatagramPacket
import java.io.*; // for IOException
public class UDPEchoServer {
private static final int ECHOMAX = 255; // Maximum size of echo
// datagram
public static void main (String[] args) throws IOException {
if (args.length != 1)
throw new IllegalArgumentException("Parameter(s): <Port>");
int servPort = Integer.parseInt(args[0]);
DatagramSocket socket = new DatagramSocket(servPort);
DatagramPacket packet = new DatagramPacket(new byte[ECHOMAX],ECHOMAX);
for (;;) { // Run forever, accpeting and echoing datagrams
socket.receive(packet); // Receive packet from client
System.out.println ("Handling client at " + packet.getAddress().getHostAddress() + "
on port " + packet.getPort());
System.out.println ("Message received " + new String(packet.getData()));
socket.send(packet); // Send de same packet back to client
packet.setLength(ECHOMAX);
// Reset length to avoid
//
shrinking buffer
}
/* NOT REACHED */
}
}
24

Sockets
Envio e recebimento de mensagens com Sockets UDP


Uma diferena entre TCP e UDP que o UDP


preserva as ltimas mensagens


A cada chamada do mtodo receive() so retornados


dados de pelo menos uma chamada send()
Alm disso, diferentes chamadas a receive() nunca iro
retornar dados de uma mesma chamada send()
Quando uma chamada ao mtodo write() em um stream
de sada TCP retorna, todos os chamadores sabem que os
dados foram copiados para um buffer para transmisso,
independente dos dados terem sido transmitidos
Entretando, o UDP no prov recuperao de erros na
rede e, dessa forma, no existem buffers de dados para
possveis retransmisses
25

Sockets
Envio e recebimento de mensagens com Sockets UDP


Entre o tempo de uma mensagem chegar


pela rede e o tempo de seus dados serem
retornados pelos mtodos read() e
receive(), os dados so armazenados em
uma fila FIFO
Com uma conexo TCP, todos os bytes
recebidos, mas ainda no entregues, so
tratados como uma seqncia contnua de
bytes
26

Sockets
Envio e recebimento de mensagens com Sockets UDP


No protocolo UDP, os dados podem ter sido originados de


diferentes emissores. Um dado recebido de um socket UDP
mantido em uma fila de mensagens, cada uma com a
informao associada que identifica sua origem
Uma chamada a receive() nunca ir retornar mais do que
uma mensagem
Entretando, se receive() chamada com um
DatagramPacket contendo um buffer de tamanho n e o
tamanho da primeira mensagem da fila de mensagens recebidas
for maior do que n, somente os primeiros n bytes da mensagem
so retornados. Os bytes restantes so descartados sem
nenhuma indicao ao programa receptor de que a informao
foi perdida
27

Sockets
Envio e recebimento de mensagens com Sockets UDP


Por essa razo, um receptor deve sempre


prover um DatagramPacket com um buffer
grande o suficiente para manter a maior
mensagem permitida pelo protocolo da
aplicao durante uma chamada ao mtodo
receive()
Essa tcnica ir garantir que nenhum dado
se perder, entretanto, o tamanho mximo
de um datagrama UDP 65.507 bytes
28

Sockets
Envio e recebimento de mensagens com Sockets UDP


importante lembrar que cada instncia da classe


DatagramPacket no possui, internamente, noo
do tamanho das mensagens, o qual pode ser
alterado toda vez que uma mensagem recebida.
Aplicaes que chamam o mtodo receive()
mais de uma vez, com a mesma instncia de
DatagramPacket,devem explicitamente reiniciar o
tamanho interno do buffer atual antes de cada
chamada ao mtodo.

29

Sockets
usando C

30

Tipos de Sockets


Stream Sockets






Entrega confivel
Garantia de ordenao
das mensagens
Orientado conexo
Bidirecional

Datagram Sockets






Entrega no confivel
Sem garantias de
ordenao das msgs
No orientado conexo
Pode enviar ou receber

31

Estruturas e manipulao de dados




Estrutura sockaddr
struct sockaddr {
u_short
char
}

sa_family;
sa_data[14];

// endereo da famlia AX_xxx


// endereo especfico do protocolo

Para a domnio Internet (TCP/IP), utiliza-se a


estrutura sockadd_in
struct sockadd_in {
short
u_short
struct in_addr
char

sin_family
sin_port
sin_addr
sin_zero[8]

// AF_INET
// nmero da porta
// endereo do host
// no usado

}
32

Estruturas e manipulao de dados




Apesar de existirem vrias estruturas


(sockaddr_in, sockaddr_ns, sockaddr_un),
algumas funes, tais como connect e bind
precisam do endereo da estrutura gentica
(sockaddr) e do tamanho da estrutura
necessrio fazer casting:
struct sockaddr_in serv_addr;
connect(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr));
33

Estruturas e manipulao de dados




Existem dois tipos de ordenao do


endereo:


Bits mais significantes primeiro




Network Byte Ordering

Bits menos significantes primeiro

Quanto uma funo precisa que o endereo


esteja no formato Network Byte Ordering,
precisa-se usar uma funo de converso

34

Estruturas e manipulao de dados




Funes para converso do formato host


para o formato network:





htonl (h-to-n-l): host to network; long integer


htons (h-to-n-s): host to network; short integer
ntohl (n-to-h-l): network to host; long integer
ntohs (n-to-h-s): network to host; shot integer

35

Estruturas e manipulao de dados




Funes para converso de endereos:




unsigned long inet_addr (char *ptr)




Converte uma string em formato de endereo Internet


(decimal com ponto)

char *inet_ntoa (struct in_addr inaddr)




Funo inversa

36

Principais funes


int socket (int family, int type, int protocol):





Cria um descritor
family: AF_UNIX
AF_INET
AF_NS
AF_IMPLINK

type:

SOCK_STREAM
SOCK_DGRAM
SOCK_RAW
SOCK_SEQPACKET
SOCK_RDM

protocol: normalmente 0
37

Principais funes


int bind (int sockfd, struct sockaddr *my_addr,


int addrlen)






Associao de um socket a uma porta local


Necessrio quando for utilizar a funo listen()
depois
sockfd: descritor do socket
my_addr: ponteiro para uma struct sockaddr que
contm informao sobre seu endereo, nome,
porta e endereo IP
addrlen: tamanho da estrutura sockaddr
38

Principais funes


bind()


O processo de pegar o prprio endereo IP e/ou


porta pode ser feito automaticamente:


Fazendo my_addr.sin_port = 0


Fazendo my_addr.sin_addr.s_addr = INADDR_ANY








Escolha da porta
Preenche automaticamente o endereo IP da mquina que
o processo est sendo executado

bind() retorna -1 se ocorreu um erro


Portas abaixo de 1024 so reservadas
Pode-se utilizar qualquer porta at 65535
39

Principais funes


connect(int sockfd, struct sockaddr


*serv_addr, int addrlen)




Conecta com um servidor


sockfd: descritor do socket
serv_addr: ponteiro para uma struct sockaddr que
contm informao sobre endereo, nome, porta
e endereo IP do destino
addrlen: tamanho da estrutura sockaddr

40

Sockets em C
Principais funes


listen(int sockfd, int backlog)





Espera por conexes


Processo que:






Primeiro escuta
Depois aceita

sockfd: descritor do socket


backlog: nmero de conexes que so aceitas na
fila de entrada

41

Principais funes


accept(int sockfd, void *addr, int *addrlen)







Algum processo ir tentar se conectar a uma porta que o


servidor est ouvindo
A conexo ser colocada na fila de entrada esperando que
seja aceita
Quando se faz um accept() est aceitando uma conexo
pendente
sockfd: descritor do socket
addr: ponteiro para uma struct sockaddr_in que contm
informao sobre a conexo que est chegando
addrlen: tamanho da estrutura sockaddr

42

Principais funes



send(int sockfd, const void *msg, int len, int flags)


receive(int sockfd, void *buf, int len, unsigned int
flags)







Para envio e recebimento


sockfd: descritor do socket
msg: ponteiro para a mensagem que se quer enviar
buf: buffer onde a mensagem ser colocada
len: tamanho da mensagem em bytes
flags = 0

43

Principais funes


sento(int sockfd, const void *msg, int len,


unsigned int flags, const struct sockaddr *to,
int tolen)
int recvfrom(int sockfd, void *buf, int len,
unsigned int flags, structlen, unsigned int
flags, struct sockaddr *from, int *fromlen);

44

Principais funes


close(sockfd)


Fecha uma conexo

45

Principais funes


int gethostname(char *hostname, size_t size);




Retorna o nome do computador que o processo est sendo


executado

struct hostent *gethostbyname(const char *name);




Retorna um ponteiro para uma estrutura hostent

struct hostent {
char *h_name;
char **h_aliases;
int h_addrtype;
int h_length;
char **h_addr_list;
};
#define h_addr h_addr_list[0]


46

Principais funes







h_name nome do host


h_aliases lista alternativa de nomes.
h_addrtype tipo do endereo utilizado;
normalmente AF_INET.
h_length tamanho do endereo em bytes.
h_addr_list Array de endereos de rede para o
host. Os hosts so endereados em Network Byte
Order.
h_addr Primeiro endereo de h_addr_list.

47

Cliente/Servidor TCP

48

Cliente/Servidor UDP

49

Você também pode gostar