You are on page 1of 39

A Camada de Transporte

Sockets

Dnio Mariz denio@cefetpb.edu.br


SET/2004

Descritores de arquivos no Unix


Unix trata um arquivo como uma sequncia de bytes Funes da API para lidar com arquivos so:
 open(), creat(), read(), write(), lseek(), close() Todos operam sobre um descritor de arquivo  Um descritor de arquivo (DA) um nmero inteiro  Mas o DA representa uma estrutura de dados mais

complexa, interna ao sistema operacional

Processo

Descritores de Arquivo

2 14 34

Memria (Estruturas do S.O.) z z z z z

Byte Ordering
Como um valor armazenado na memria? Exemplo: 16909060 = 0x01020304

Big-Endian
Endereo n n+1 n+2 n+3 Memria 01 02 03 04 Endereo n n+1 n+2 n+3

Little-Endian
Memria 04 03 02 01

Dados so armazenados e transferidos na rede no formato Big-Endian


 evita conflitos entre hosts de arquiteturas diferentes
3

Programao na Internet
Sockets
 Estilo: envia/recebe (send/receive)  Caracterstica: eficiente

RPC
 Chamada remota de procedimento  Transparncia e facilidade de programao

Objetos distribudos
 Transparncia, facilidade e todos os benefcios da programao

orientada a objetos
 Execuo mais lenta  Exemplos: DCOM, CORBA, Java RMI, outros

Unix BSD Sockets


Interface padro para comunicao entre processos em redes TCP/IP Nasceu com o Unix de Berkeley Os projetistas tentaram usar ao mximo as chamadas de sistema do Unix Implementada hoje em vrios sistemas operacionais Programar com sockets pode ser visto como desenvolver um protocolo de aplicao

Tipos de sockets
Servio com conexo
 Implementa um stream de dados (SOCK_STREAM)  Protocolo TCP (tipicamente)

Servio sem conexo


 Implementa um servio de datagramas (SOCK_DGRAM)  Protocolo UDP (tipicamente)

Servio de baixo nvel


 Acessa diretamente a camada de rede (SOCK_RAW)  Protocolo IP (tipicamente)

API Sockets
API = Application Program Interface  API o elemento de ligao entre a aplicao e um sistema de mais baixo nvel
 Consiste de algumas funes bem definidas que podem ser

usadas pelo usurio na sua aplicao


Aplicao Final Aplicao

Sockets Transporte Sistema Operacional (Kernel) Rotinas do S.O. Rede Rotinas do Driver Enlace de Dados Drivers e Hardware Fsica
7

Comandos no Hardware

Sockets: como funciona


Usurio

Aplicao
Sockets Comunicao lgica

Aplicao
Sockets

SO (Kernel)

TCP UDP

...

TCP UDP

...

Transporte Rede Enlace de Dados


Drivers, Hardware

Transporte Rede Enlace de Dados Fsica

Fsica

Internet
Comunicao Fsica 8

Bind (Associao)
Um processo servidor precisa associar um socket a um endereo IP e porta para avisar ao sistema operacional que deseja receber dados que chegam ao host.
Sockets

Processos

Endereo Associado (IP:porta) 146.164.41.10 : 80 146.164.41.10 : 21

0561 0613 1342 0613

10 13 20 28 33

146.164.41.10 : 6020 146.164.41.10 : 6021 9

Servio com Conexo (TCP)


Servidor
socket () bind () listen () accept () (Bloqueado)
Estabelecimento da conexo

Cliente
socket () connect () Processa

read () Processa write () close ()

Dados (Solicitao)

write ()

Dados (Resposta)

read () close ()
10

Servio sem Conexo (UDP)


Servidor
socket () bind () recfrom() (Bloqueado)
Dados (Solicitao)

Cliente

socket () bind () Processa sendto ()

Processa
Dados (Resposta)

sendto () close ()

recfrom() close()
11

Primitivas BSD Socket para TCP


Primitiva SOCKET BIND LISTEN ACCEPT CONNECT SEND RECEIVE CLOSE Significado Cria um novo ponto de comunicao Associa um endereo IP e uma porta local a um socket Anuncia que est pronto para aceitar conexes (passivo) Bloqueia a aplicao at uma que chegue uma conexo Tenta estabelecer uma conexo Envia dados pela conexo estabelecida (=WRITE) Recebe dados pela conexo estabelecida (=READ) Libera a conexo

12

#include ... #include <sys/socket.h> int main(int argc, char **argv){ int s; struct sockaddr_in dest; char msg_write[100], msg_read[100]; socket(AF_INET, SOCK_STREAM, 0)); s = socket

CLIENTE
socket () connect () Processa write ()

bzero(&dest, sizeof(dest)); read () dest.sin_family = AF_INET; Com conexo close () dest.sin_port = htons(9999); inet_aton(127.0.0.1, &dest.sin_addr.s_addr); connect(s, (struct sockaddr*)&dest, sizeof(dest)); connect do { scanf("%s",msg_write); /* processamento */ write (s, msg_write, strlen(msg_write)+1); read (s, msg_read, MAXBUF); } while (strcmp(msg_read,"bye")); close close(s); }
13

#include ... #include <sys/socket.h>

SERVIDOR
socket () bind () listen () accept () (Bloqueado)

int main(int argc, char **argv){


int s, client_s; struct sockaddr_in self, client; int addrlen = sizeof(client); char msg_write[100], msg_read[100];

s = socket socket(AF_INET, SOCK_STREAM, 0); bzero(&self, sizeof(self)); self.sin_family = AF_INET; self.sin_port = htons(9999); Com conexo self.sin_addr.s_addr = INADDR_ANY;

read () Processa write () close ()

bind(s, (struct sockaddr*)&self, sizeof(self)); bind listen listen(s, 5); while (1) { client_s = accept accept(s,(struct sockaddr*)&client, &addrlen); do { read (client_s, msg_read, MAXBUF); /* processa aqui a mensagem */ write (client_s, msg_read, strlen(msg_read)+1); } while (strcmp(msg_read,"bye")); close close(client_s); }
14

Sockets - Criao
Utiliza-se a chamada de sistema socket():
 #include <sys/socket.h>  int socket( int domain, int type, int protocol );

Parmetros:
 domain o tipo de rede do socket.
 AF_INET (Address Family Internet) usado para IPv4  Outros tipos: AF_LOCAL, AF_INET6.

 type o tipo de servio de transporte.


 Para sockets TCP usamos SOCK_STREAM  Para sockets UDP usamos SOCK_DGRAM

 protocol o protocolo utilizado (0= padro: TCP/UDP)

Retorno:
 retorna um descritor do socket criado  ou 1 em caso de erro.

15

Sockets - Endereos
Endereos IP e portas so armazenados em estruturas do tipo struct sockaddr_in sin_family o tipo do endereo (AF_INET usado para IPv4) sin_port a porta associada ao endereo. sin_addr contm o endereo IP onde se espera a conexo  INADDR_ANY indica qualquer IP do host. IP e porta devem ser armazenados em network order (Big-Endian).
 Ex: usar a funo
#include <sys/socket.h>

struct sockaddr_in { sa_family_t sin_family; in_port_t sin_port; struct in_addr sin_addr;


/* ... outros campos */ }; struct in_addr { in_addr_t s_addr; };
/* convert host short to network byteorder short */ uint16 htons(uint16 data_in_hostorder); uint16 ntohs(uint16 data_in_netorder );

htons(NUMERO)
16

Sockets - Endereos
... int s; char *IP = 200.129.45.123; ushort Porta = 80; struct sockaddr_in dest; s = socket(AF_INET, SOCK_STREAM, 0)); bzero(&dest, sizeof(dest)); dest.sin_family = AF_INET; dest.sin_port = htons(Porta); inet_aton(IP, &dest.sin_addr.s_addr); connect(s,(struct sockaddr*)&dest, sizeof(dest)) ...
17

Sockets - Associao
Utiliza-se a chamada de sistema bind():
 #include <sys/socket.h>  int bind( int sockfd, struct sockaddr *addr, socklen_t addrlen );

Parmetros:
 sockfd o descritor do socket (retornado pela funo

socket()).  addr a estrutura com o endereo para ser associado.  addrlen o tamanho da estrutura do endereo.

Retorno
 A funo retorna 0 (zero) em caso de sucesso  ou 1 no caso de um erro  Erro comum: EADDRINUSE (Address already in use)
18

Sockets

Traduzindo Endereos IP

Para converter um endereo IP entre as formas de string e binria:


 #include <sys/socket.h>  int  char *

inet_aton(const char * str, struct in_addr * addrptr); inet_ntoa(struct in_addr addr);

A funo inet_aton()
 converte um endereo na notao do ponto (1.2.3.4) para o

formato binrio em byte order de rede (como a struct sockaddr_in espera) e retorna 0 (zero) em caso de sucesso.

A funo inet_ntoa()
 faz a converso inversa.

19

Sockets

Resolvendo Nomes com DNS

Para resolver nomes de hosts usa-se a funo gethostbyname() -- servio DNS


#include <resolv.h> struct hostent * gethostbyname(const char * str); struct hostent { /* tam.endereo (IPv4=4,IPv6=16)*/ int h_length; char **h_addr_list; /* lista de endereos */ char *h_addr; /* primeiro endereo */ /* ... outros campos */ }

...
20

Sockets
Exemplo:

Resolvendo Nomes com DNS

struct hostent *gethostbyname(); struct hostent *h; struct sockaddr_in *server; struct sockaddr_in sockAddr; h = gethostbyname(argv[1]); if (h == 0) { fprintf(stderr, "%s: unknown host", argv[1]); exit(2); } /* copia o endereo obtido (h->h_addr) para &server.sin_addr */ memcpy(&server->sin_addr, h->h_addr, h->h_length); /* continua ... */

...
21

Sockets TCP

listen()

Para colocar um socket em modo de escuta (servidor) usamos a chamada de sistema listen():
 #include <sys/socket.h>  int listen( int sockfd, int backlog );

Parmetros:
 sockfd o descritor do socket.  backlog Nmero mximo de conexes pendentes (fila de

conexes para serem atendidas em sequncia)

Retorno
 O valor de retorno da funo 0 (zero) em caso de sucesso  ou 1 caso contrrio.

22

Sockets TCP

accept()

Atende pedidos de conexo pendentes ou fica bloqueada at a chegada de um.  #include <sys/socket.h>  int accept( int sockfd, struct sockaddr * claddr, socklen_t * len ); Parmetros:  sockfd o descritor do socket.  claddr a estrutura onde ser guardado o endereo do cliente.  len argumento valor/resultado com o tamanho da estrutura do endereo. Retorno  um novo descritor (no negativo) em caso de sucesso  ou 1 caso contrrio.  Cada novo descritor retornado por accept() est associado mesma porta do socket de escuta.
23

Sockets TCP

send()

Usada para enviar dados por um socket conectado.


#include <sys/socket.h> int send( int sockfd, void * buffer, size_t n_bytes, int flags );

Parmetros:  sockfd o descritor do socket.  buffer um ponteiro para os dados a serem enviados.  n_bytes quantidade de bytes a serem enviados a partir do ponteiro buffer.  flags opes para essa operao. O valor de retorno da funo a quantidade de bytes enviados em caso de sucesso ou 1 caso contrrio.

24

Sockets TCP

recv()

Recebe dados por um descritor conectado, ou bloqueia a execuo at que algum dado chegue ao socket:
#include <sys/socket.h> int recv( int sockfd, void * buffer, size_t n_bytes, int flags );

Parmetros:  sockfd o descritor do socket.  buffer um ponteiro para a rea de memria onde devem ser armazenados os dados recebidos.  n_bytes quantidade mxima de bytes a serem recebidos.  flags opes para essa operao. O valor de retorno da funo a quantidade de bytes recebidos em caso de sucesso ou 1 caso contrrio.

25

Sockets UDP

sendto()

Envia dados por um socket NO conectado.

#include <sys/socket.h> int sendto( int sockfd, void * buffer, size_t n_bytes, int flags, Parmetros: const socket.  sockfd o descritor dostruct sockaddr * to, socklen_t addrlen );
    

buffer um ponteiro para os dados a serem enviados. n_bytes quantidade de bytes a serem enviados. flags opes para essa operao. to endereo de destino dos dados. addrlen tamanho em bytes do endereo de destino.

O valor de retorno da funo a quantidade de bytes enviados em caso de sucesso ou 1 caso contrrio.

26

Sockets UDP

recvfrom()

Recebe dados por um descritor NO conectado, ou bloqueia a execuo at que algum dado chegue:

#include <sys/socket.h> int recvfrom( int sockfd, void * buffer, size_t n_bytes, int flags, struct sockaddr * from, socklen_t * addrlen );
Parmetros:
     

sockfd o descritor do socket. buffer um ponteiro para a rea de memria onde devem ser armazenados os dados recebidos. n_bytes quantidade mxima de bytes a serem recebidos. flags opes para essa operao. from ponteiro para a estrutura onde ser escrito o endereo de origem. addrlen argumento valor/resultado com o tamanho do endereo de origem.

O valor de retorno da funo a quantidade de bytes recebidos em caso de sucesso ou 1 caso contrrio.

27

Sockets em Java
Java modernizou a API para trabalhar com sockets O programador no precisa chamar todas as funes, algumas chamadas so automticas Exemplos  Socket: equivale a socket + bind do C  ServerSocket: equivale a socket + bind + listen do C Sockets so implementados no pacote java.net A transmisso e o envio de dados
 So feitos atravs de classes do pacote java.io  Semelhante gravao e leitura em arquivos  Classes DataInputStream DataOutputStream etc., DataInputStream, DataOutputStream,
28

import java.net.*; import java.io.*;

CLIENTE

public class SimpleJavaClient { public static void main(String[] args) { try { Socket s = new Socket Socket("127.0.0.1", 9999); InputStream i = s.getInputStream(); OutputStream o = s.getOutputStream(); String str; do { byte[] line = new byte[100]; System.in.read(line); o.write write(line); i.read read(line); str = new String(line); System.out.println(str.trim()); } while ( !str.trim().equals("bye") ); close(); s.close } catch (Exception err) { System.err.println(err); } } }

import java.io.*; import java.net.*;

SERVIDOR

public class SimpleJavaServer { public static void main(String[] args) { try { ServerSocket(9999); ServerSocket s = new ServerSocket String str; while (true) { Socket c = s.accept accept(); InputStream i = c.getInputStream(); OutputStream o = c.getOutputStream(); do { byte[] line = new byte[100]; i.read read(line); write(line); o.write str = new String(line); } while ( !str.trim().equals("bye") ); close(); c.close } } catch (Exception err){ System.err.println(err); } } }

Servidores Concorrentes
Muitas vezes necessrio para um servidor lidar com vrios clientes de uma nica vez. Para conseguir isto preciso, de alguma maneira, voltar a aceitar conexes, sem esperar que um cliente seja completamente servido. Isto feito atravs da criao de novas threads ou novos processos. Um servidor, aps o retorno da funo accept(), se divide em dois  uma linha de execuo se dedica a atender o cliente,  outra volta a esperar por novos pedidos de conexo.

31

Estrutura Tpica de um Servidor

32

Servidor com conexes concorrentes


pid_t pid; int listenfd, confd; listenfd = socket(...); bind(listenfd, ...); listen(listenfd, LISTENQ);

for( ; ; ) { connfd = accept(listenfd, ...); if ( ( pid = fork() ) == 0 ){ close(listenfd); doit(connfd); close(connfd); exit(0)

close (connfd); }

33

Sockets sem Conexo (Java)


Cliente:
 socket = new DatagramSocket( );  message = new DatagramPacket(msg,length,Addr,Port);  reply = new DatagramPacket( new byte[100],100);  socket.send( message );  socket.receive( reply );  socket.close();

Servidor:
 socket = new DatagramSocket(porta);  socket.receive( message );  socket.send( message );
34

Sockets sem Conexo (C)


Cliente:
 s = socket(AF_INET, SOCK_DGRAM, 0);  sendto(s, msg, length, flags, destaddr, addrlen);  recvfrom(s, msg, length, flags, fromaddr, addrlen);

Servidor:
 s = socket(AF_INET, SOCK_DGRAM, 0);  bind(s, dest, sizeof(dest));  recvfrom(s, msg, length, flags, fromaddr,

addrlen);  sendto(s, msg, length, flags, destaddr, addrlen);


35

Recursos Disponveis
http://www.javaworld.com/javaworld/jw-12-1996/jw-12-sockets_p.html http://java.sun.com/docs/books/tutorial/networking/index.html http://www.cs.odu.edu/~cs476/fall03/lectures/sockets.htm http://orca.st.usm.edu/~seyfarth/network_pgm/net-6.html Tutoriais Sockets Parte I VII (em portugues):
 http://olinux.uol.com.br/artigos/370/1.html  http://olinux.uol.com.br/artigos/376/1.html  http://olinux.uol.com.br/artigos/383/1.html  http://olinux.uol.com.br/artigos/388/1.html  http://olinux.uol.com.br/artigos/395/1.html  http://olinux.uol.com.br/artigos/398/1.html  http://olinux.uol.com.br/artigos/404/1.html
36

Thread fork using Java


/** * A server that accepts connections and prints * out everything that the client sends over. */ public class ThreadedServer { public static void main(String args[]) { ServerSocket ss = new ServerSocket(2059); while(true) { Socket cs = ss.accept(); new WorkerThread(cs).start(); } } }
Default listen backlog of 50

37

Thread fork using Java


public class WorkerThread extends Thread { private Socket cs = null; public WorkerThread(Socket cs) { this.cs = cs; super("WorkerThread"); } public void run() { DataInputStream in = new DataInputStream( cs.getInputStream() ); while((responseLine = in.readLine()) != null) { System.out.println(responseLine); } cs.close(); } }

38

Funo htonl htons ntohl ntohs

De Host Host Network Network

Para Network Network Host Host

Tamanho long short long short

39

You might also like