Relatório do Laboratório 3 Diogo Costa e Lucas Magrini Rigo 180188 e 161064 23 de setembro de 2011 Universidade Federal do Rio Grande do Sul INF01154 Redes de Computadores N For: Valter Roesler 1 Introdução Nesse laboratório aprendemos um pouco mais sobre sockets, tanto no protocolo UDP quando no TCP. 2 UDP Verificar as estruturas analisadas no diretório "esqueleto_udp". Testar programa como está. Transformar o transmissor para enviar um número bits/s na rede de acordo com as seguintes linhas de comando Explicação do algoritmo: Estamos mandando pacotes de tamanho igual a 1250 bytes ou 10 kbits. Para criar uma banda enviamos pacotes durante um segundo para que a soma de bits mandados seja 10 kbits. Assim sendo, já que temos o limite de bytes por pacote, enviamos um pacote, o programa dorme e assim sucessivamente, até o final de um segundo. Para achar o tempo ideal de sleep se considera dois casos: banda múltipla de 10 e banda não múltipla de 10. Na primeira, basta dividir 10 kbits pelo kbits que o usuário optou e multiplicar por mil(passando para milisegundos), como por exemplo 20kbits, a cada 0,5 segundos é enviado um pacote de 1250 bytes. No segundo algoritmo, para calcular o tempo de sleep, arredondamos o número para cima, tornando múltiplo de 10 e novamente se faz a divisão 10 kbits por kbits arredondado, porém em vez de enviar o último pacote com 1250 bytes, enviamos os bytes restantes para completar a banda desejada, como exemplo 47 kbits, calcula-se o sleep(10/50 = 0,2), seja T1 = 0, T2 = 0,4, T3 = 0,6, T4 = 0,8 e T5 = 1, nos tempos T1, T2, T3 e T4 é enviado 1250 bytes(resultando em 40 kbits mandados), já no instante T5 é mandado 7 kbits ou 875 bytes, fechando assim os 47 kbits de banda. Linha de comando para uso: trans -h <numero_ip> -p <porta> -r <kbits/s> Código:
#include < s t d i o. h> #include < s t r i n g. h> # i f d e f _WIN32 # i n c l u d e <winsock2. h> #else # i n c l u d e <sys / types. h> # i n c l u d e <sys / socket. h> # i n c l u d e < n e t i n e t / i n. h> SOCKET i n t i n t main ( i n t argc, char argv ) struct sockaddr_in peer ; SOCKET s ; i n t porta, peerlen, rc, i ; char i p [ 1 6 ], b u f f e r [ 1 0 0 ] ; i n t k b i t s, kbytes, backup ; # i f d e f _WIN32 WSADATA wsadata ; i f ( WSAStartup (MAKEWORD( 2, 2 ), &wsadata )!= 0) p r i n t f ( " Erro no s t a r t u p do socket \ n " ) ; i f ( argc < 7) p r i n t f ( " U t i l i z a r : \ n " ) ; p r i n t f ( " t r a n s h <numero_ip > p <porta > r < k b i t s / s >\ n " ) ; / / Pega parametros for ( i =1; i <argc ; i ++) i f ( argv [ i ] [ 0 ] = = ) switch ( argv [ i ] [ 1 ] ) case h : / / Numero IP i ++; s t r c p y ( ip, argv [ i ] ) ; break ; case p : / / porta i ++; porta = a t o i ( argv [ i ] ) ; i f ( porta < 1024) p r i n t f ( " Valor da porta i n v a l i d o \ n " ) ; 2
break ; case r : / / porta i ++; k b i t s = a t o i ( argv [ i ] ) ; kbytes = k b i t s / 8 ; backup = kbytes ; break ; default : p r i n t f ( " Parametro i n v a l i d o %d : %s \ n ", i, argv [ i ] ) ; else p r i n t f ( " Parametro %d : %s i n v a l i d o \ n ", i, argv [ i ] ) ; / / Cria o socket na f a m i l i a AF_INET ( I n t e r n e t ) e do t i p o UDP (SOCK_DGRAM) i f ( ( s = socket ( AF_INET, SOCK_DGRAM, 0 ) ) < 0) p r i n t f ( " Falha na criacao do socket \ n " ) ; / / Cria a e s t r u t u r a com quem v a i conversar peer. s i n _ f a m i l y = AF_INET ; peer. s i n _ p o r t = htons ( porta ) ; peer. sin_addr. s_addr = inet_addr ( i p ) ; peerlen = sizeof ( peer ) ; f l o a t sleeptime ; sleeptime = ( f l o a t ) 1 0 / k b i t s ; sleeptime = sleeptime 1000; i n t cont, bytessobra ; i f ( k b i t s%10!= 0) cont = k b i t s /10+1; bytessobra = ( ( k b i t s %10) 1000)/8; sleeptime = ( f l o a t )1000/ cont ; else cont = 1; while ( 1 ) i f ( cont > 1) i f ( cont > 1) sendto ( s, b u f f e r, 1250, 0, ( struct sockaddr )& peer, peerlen ) ; 3
cont ; else sendto ( s, b u f f e r, bytessobra, 0, ( struct sockaddr )& peer, peerlen ) ; cont = k b i t s /10+1; else sendto ( s, b u f f e r, 1250, 0, ( struct sockaddr )& peer, peerlen ) ; Sleep ( sleeptime ) ; Imagens: Ao analisar os gráficos do DU Meter, é possível ver o funcionamente do algoritmo, o qual possui um erro de +- 10%. Idade somada, 19+21 = 40kbits/s 500kbits/s: 1Mbits/s: 4
3 TCP Verificar as estruturas analisadas no diretório esqueleto_tcp. Testar programa como está. Analisar eqüidade do tráfego na rede, alterando o programa para ficar enviando dados na máxima velocidade possível, e testando com várias transmissões simultâneas (mínimo de 2 conexões dois servidores (duas instâncias do servidor em portas diferentes) e dois clientes). Gerar log com a média de tráfego por segundo. Pode-se realizar o relatório com duas máquinas, mas se o grupo quiser, poderá utilizar 3 máquinas ou mais (para ver na ferramenta de redes, além do log, a variação de carga na rede) Explicação do algoritmo: Como explicado anteriormente, mandamos cada pacote com 10kbits de tamanho. Assim, no cliente, enviamos inifitamente esse pacote; para saber o quanto de dados foi mandado para o servidor tem um contador que conta quantos pacotes foram enviados, também há uma verificação para analisar se o tempo passado foi aproximadamente 1s, gerando assim a quantidade de bits enviado durante 1s. O código do servidor em nada foi mudado. Nosso ambiente de teste foi um computador com 2 servidores e outro computador com 2 clientes, primeiramente conectamos um cliente a um servidor e esse processo ocupou em torno de 70% da rede, em seguida foi conectado o segundo cliente ao outro servidor ocioso, observou-se que os dois clientes estavam dividindo a bando - em torno de 40% cada, e, finalmente, desconectamos o primeiro cliente e o segundo cliente começou a usar a maior parte da banda. A figura prova o que foi explicado, no trecho central as linhas do cliente 1 (azul) e cliente 2 (vermelho) estão sobrepostas. Imagem: 5
Código: / / t e s t e c l i. cpp : Defines the e n t r y p o i n t f o r the console a p p l i c a t i o n. / / #include < s t d i o. h> #include < s t r i n g. h> #include < s t d l i b. h> #include <time. h> #include < u n i s t d. h> # i f d e f _WIN32 # i n c l u d e <winsock2. h> #else # i n c l u d e <sys / types. h> # i n c l u d e <sys / socket. h> # i n c l u d e < n e t i n e t / i n. h> # i n c l u d e <arpa / i n e t. h> # define SOCKET i n t # define INVALID_SOCKET ( (SOCKET)~0) #define PORTA_CLI 2345 / / porta TCP do c l i e n t e #define PORTA_SRV 2023 / / porta TCP do s e r v i d o r #define STR_IPSERVIDOR " 10.67.105.5 " / / # d efine STR_IPSERVIDOR "192.168.0.146" i n t main ( i n t argc, char argv [ ] ) 6
SOCKET s ; struct sockaddr_in s _ c l i, s_serv ; # i f d e f _WIN32 WSADATA wsadata ; i f ( WSAStartup (MAKEWORD( 2, 2 ), &wsadata )!= 0) p r i n t f ( " Erro no s t a r t u p do socket \ n " ) ; / / abre socket TCP i f ( ( s = socket ( AF_INET, SOCK_STREAM, 0))==INVALID_SOCKET) p r i n t f ( " Erro i n i c i a n d o socket \ n " ) ; return ( 0 ) ; / / seta informacoes IP / Porta l o c a i s s _ c l i. s i n _ f a m i l y = AF_INET ; s _ c l i. sin_addr. s_addr = h t o n l (INADDR_ANY ) ; s _ c l i. s i n _ p o r t = htons (PORTA_CLI ) ; / / associa configuracoes l o c a i s com socket i f ( ( bind ( s, ( struct sockaddr )& s _ c l i, sizeof ( s _ c l i ) ) )!= 0) p r i n t f ( " erro no bind \ n " ) ; close ( s ) ; return ( 0 ) ; / / seta informacoes IP / Porta do s e r v i d o r remoto s_serv. s i n _ f a m i l y = AF_INET ; s_serv. sin_addr. s_addr = inet_addr (STR_IPSERVIDOR ) ; s_serv. s i n _ p o r t = htons (PORTA_SRV ) ; / / connecta socket aberto no c l i e n t e com o s e r v i d o r i f ( connect ( s, ( struct sockaddr )& s_serv, sizeof ( s_serv ) )!= 0) / / p r i n t f ( " erro na conexao %d \ n ", WSAGetLastError ( ) ) ; p r i n t f ( " erro na conexao " ) ; close ( s ) ; # i f 0 / / envia mensagem de conexao aprimorar para dar IP e porta i f ( ( send ( s, " Conectado \ n ", 11,0)) == SOCKET_ERROR) ; 7
p r i n t f ( " erro na t r a n s m i s s o %d \ n ", WSAGetLastError ( ) ) ; closesocket ( s ) ; return 0; / / recebe do teclado e envia ao s e r v i d o r char s t r [1250] = " 123 " ; char ch ; i n t i ; i n t count = 0; time_t i n i c i o, f i n a l ; double d i f ; time (& i n i c i o ) ; while ( 1 ) i f ( ( send ( s, ( const char )& s t r, 1250,0)) < 0) / / p r i n t f ( " erro na t r a n s m i s s o %d \ n ", WSAGetLastError ( ) ) ; p r i n t f ( " erro na t r a n s m i s s o \ n " ) ; close ( s ) ; return 0; count ++; time (& f i n a l ) ; i f ( d i f = d i f f t i m e ( f i n a l, i n i c i o ) >= 1) p r i n t f ( "%f Mbps \ n ", ( count 1250 8/ d i f )/1000000); time (& i n i c i o ) ; count = 0; i f ( strcmp ( ( const char )& s t r, " q " )==0) break ; / / usleep (100000); / / fecha socket e termina programa p r i n t f ( " Fim da conexao \ n " ) ; close ( s ) ; return 0; 1) O que é equidade de tráfego e em qual protocolo ela foi observada nativamente no laboratório? A equidade de tráfego é a divisão justa de banda disponível entre os usuários que estão utilizando o 8
meio. Entende-se divisão justa como divisão em partes iguais. Portanto, quando há mais de um sinal compartilhando o meio, a banda total é dividida em partes de mesmo tamanho para cada usuário. Essa característica foi observada no protocolo TCP. 2) Qual o nível do modelo OSI para fazer controle de fluxo quando o programador utiliza TCP e quando utiliza UDP? O controle de fluxo do protocolo TCP é feito no nível 3, o de transporte. O protocolo UDP não é controlado, portanto caso deseje-se controlar o fluxo, deve criar-se um mecanismo no nível de aplicação, como por exemplo enviar confirmação de recebimento de mensagem (ACK). 4 Conclusão Completo esse laboratório, compreendemos o comportamento dos protocolos do nível de transporte, UDP e TCP, porque eles existem e quando são utilizados. 9