Buscar

TP1 - Relatorio1A-sem nome

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 12 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 12 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 12 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

Universidade Federal de Minas 
Gerais 
 
 
 
Curso de Engenharia Elétrica 
 
 
 
Redes TCP-IP – 2014/1 
 
 
 
Trabalho Prático em Grupo 1 – 
Implementação um programa para 
comunicação via rede utilizando 
soquetes – Parte 1 
 
 
 
 
 
 
1. Introdução 
 
A proposta deste trabalho consiste na implementação de um programa simples de cliente/servidor que utiliza 
interfaces soquetes para a transmissão de mensagens através de uma conexão TCP. Este programa permite que 
o usuário em uma máquina digite e envie uma mensagem para um usuário em outra máquina. É uma versão 
simplificado do programa de chat do Unix. Para isso, escolheu-se utilizar o sistema operacional Ubuntu, versão 
12.04 32 bits, disponível para download gratuitamente na internet. O sistema foi utilizado em uma máquina virtual, 
sendo que o programa escolhido para rodá-la foi o VM Virtual Box, versão 4.3.8 da Oracle. 
O Ubuntu é um sistema operacional constituído principalmente por software livre, construído a partir do núcleo 
Linux. Ele se caracteriza por ter versões lançadas semestralmente e tem como proposta oferecer um sistema que 
qualquer pessoa possa utilizar sem dificuldades, já que possui uma interface gráfica amigável. A grande 
vantagem do uso do Linux é sua gratuidade e sua fácil instalação. 
Um soquete é um ponto de comunicação no qual dois processos podem se comunicar através da rede. Ele é um 
mecanismo de interface onde processos podem mandar mensagens. Existem diversos tipos de redes com 
diferentes protocolos, diferentes formas de endereçamento e de comunicação. Logo, existem diferentes tipos de 
soquetes. 
Para criar um soquete, é preciso realizar a seguinte operação: 
int socket(int domain, int type, int protocol) 
A razão para que esta função receba três argumentos é que soquetes são projetados para suportar qualquer tipo 
de protocolo. O argumento domain especifica a família que vai ser usada, e normalmente é especificado como 
PF_INET, que significa a família da internet. O argumento type indica a semântica de comunicação: SOCK_STREAM 
é usado para denotar um stream de bytes; SOCK_DGRAM indica que um serviço orientado a mensagens, como 
o provido pelo UDP. Quando utilizados juntos, PF_INET e SOCK_STREAM implicam em uso de TCP. O último 
argumento é um número para identificar um determinado tipo de protocolo. No caso do TCP e do UDP, ambos 
só têm um tipo de protocolo, então o valor passado neste parâmetro é 0. 
O próximo passo depende se o programa é um cliente ou um servidor. No servidor, a aplicação executa uma 
abertura passiva, ou seja, o servidor diz que está pronto para aceitar conexões, mas não chega a estabelecer 
uma conexão. O servidor faz isso invocando três operações: 
int bind(int socket, struct sockaddr *address, int addr len) 
int listen(int socket, int backlog) 
int accept(int socket, struct sockaddr *address, int *addr len) 
A operação de bind associa o soquete criado a um endereço específico. Este endereço é o da máquina local, 
o servidor, e é composto por um endereço de IP juntamente com uma porta. A operação de listen define quantas 
conexões podem ficar pendentes no soquete especificado. Já a operação de accept realiza a abertura passiva. 
Esta última operação bloqueia o programa até que algum cliente estabeleça uma conexão, retornando um novo 
soquete correspondente à conexão recém-estabelecida, bem como o endereço do cliente que foi conectado. 
Quando o accept retorna, o soquete original ainda existe e ainda corresponde à abertura passiva, de forma que 
pode ser utilizado em futuras invocações do accept. 
O cliente realiza uma abertura ativa, ou seja, ele diz que quer se comunicar utilizando a seguinte função: 
int connect(int socket, struct sockaddr *address, int addr len) 
Essa função não retorna até que uma conexão TCP seja estabelecida com sucesso, momento quando a 
aplicação está livre para enviar dados. Neste caso, address contém apenas o endereço do participante remoto. 
Na prática, o cliente normalmente especifica apenas o endereço do servidor e deixa o sistema preencher as 
informações locais. Enquanto um servidor utiliza uma porta específica, um cliente não se preocupa com qual 
porta vai usar para se comunicar, porque o sistema operacional escolhe uma livre no momento da comunicação. 
Com a conexão estabelecida, os processos das aplicações invocam as seguintes funções para enviar e receber 
dados: 
int send(int socket, char *message, int msg len, int flags) 
int recv(int socket, char *buffer, int buf len, int flags) 
A primeira função envia uma dada mensagem através de um soquete específico, enquanto a segunda função 
recebe a mensagem do soquete e a salva em um buffer. As duas funções têm alguns flags de controle de certos 
detalhes da operação. 
2. Experimento 
 
O livro-texto (referência [1]) implementa um código do programa “Simplex-Talk”, que utiliza as funções aqui 
descritas para realizar a comunicação entre um cliente e um servidor. Foi então realizado um experimento que 
vem do exercício número 32 do capítulo 1 do livro-texto, de forma que algumas modificações foram realizadas 
no código do livro. 
O enunciado do problema 32 é o seguinte (tradução livre): 
Obtenha e construa o programa exemplo de soquete “Simplex-talk” mostrado no texto. Comece um servidor e 
um cliente, em janelas separadas. Enquanto o primeiro cliente está rodando, inicie mais 10 outros clientes que 
conectam com o mesmo servidor; esses outros devem ser iniciados em background com sua entrada direcionada 
de um arquivo. O que acontece com os 10 outros clientes? A conexão deles falha, ou dá “time out”, ou acontece 
com sucesso? Outras chamadas são bloqueadas? Agora deixe o primeiro cliente sair. O que acontece? Tente 
isso também com o valor de MAX_PENDING igual a 1. 
Para realizar a implementação do código do Simplex-Talk, utilizou-se a IDE Eclipse Kepler para C e C++. Para 
instalar o Eclipse, é necessário ter uma plataforma JDK instalada na máquina. Para Linux, o JDK mais utilizado é o 
OpenJDK, que pode ser baixada com o comando de terminal 
$ sudo apt-get install openjdk-7-jre 
Após instalar o JDK, foi possível então instalar o Eclipse. 
No Eclipse, foi criado um novo projeto para o código servidor e outro projeto para o código do cliente, e o 
compilador escolhido para eles foi o Linux GCC. 
2.1 Servidor 
 
O código implementado para o servidor foi o seguinte: 
#include <stdio.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <netdb.h> 
/* Bibliotecas que tiveram que ser incluídas */ 
#include <string.h> 
#include <strings.h> 
#include <unistd.h> 
#include <arpa/inet.h> 
#include <stdlib.h> 
#define SERVER_PORT 54321 
#define MAX_PENDING 5 
#define MAX_LINE 256 
int main() 
{ 
 struct sockaddr_in sin; 
 char buf[MAX_LINE]; 
 socklen_t len; 
 int s, new_s; 
 /* construção da estrutura de endereçamento */ 
 bzero((char *)&sin, sizeof(sin)); 
 sin.sin_family = AF_INET; 
 sin.sin_addr.s_addr = INADDR_ANY; 
 sin.sin_port = htons(SERVER_PORT); 
 /* configuração da abertura ativa */ 
 if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) { 
 perror("simplex-talk: socket"); 
 exit(1); 
 } 
 if ((bind(s, (struct sockaddr *)&sin, sizeof(sin))) < 0) { 
 perror("simplex-talk: bind"); 
 exit(1); 
 } 
 listen(s, MAX_PENDING); 
 len = sizeof(sin); 
 /* espera pela conexão, então recebe e imprime o texto */ 
 while(1) 
 { if ((new_s = accept(s, (struct sockaddr *)&sin, &len)) < 0) { 
 perror("simplex-talk: accept"); 
 exit(1); 
 } 
 while ((len = recv(new_s, buf,sizeof(buf), 0))) 
 { fputs(buf, stdout); 
 close(new_s); 
 } 
} 
 
Foram necessárias algumas modificações em relação ao código original do livro. Em primeiro lugar, o Eclipse 
acusou a falta de diversas bibliotecas. Vários trechos do código não estavam sendo reconhecidos e de acordo 
com os erros que o Eclipse indicava, pesquisas na internet levaram à conclusão de que estava faltando mais uma 
biblioteca. 
A variável “len” no código original é do tipo inteiro (int). No entanto, foi necessário alterar seu tipo para 
“socklen_t” , que é um tipo específico para receber o tamanho de um endereço ou guardar o tamanho de um 
buffer. Também foi preciso iniciar a variável “len” logo depois de realizar a operação listen() . “len” foi iniciada 
com o tamanho da estrutura de endereçamento.
2.2 Cliente 
 
O código implementado para o servidor foi o seguinte: 
#include <stdio.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <netdb.h> 
/*bibliotecas que foram incluídas*/ 
#include <stdlib.h> 
#include <strings.h> 
#include <string.h> 
#include <unistd.h> 
#include <arpa/inet.h> 
#define SERVER_PORT 54321 
#define MAX_LINE 256 
int main(int argc, char * argv[]) 
{ char *host; 
 struct sockaddr_in sin; 
 char buf[MAX_LINE]; 
 int s; 
 int len; 
 if (argc==2) { 
 host = argv[1]; 
 } 
 else { 
 fprintf(stderr, "usage: simplex-talk host\n"); 
 exit(1); 
 } 
 /* construção da estrutura de endereçamento */ 
 bzero((char *)&sin, sizeof(sin)); 
 sin.sin_family = AF_INET; 
 sin.sin_addr.s_addr = inet_addr(host); 
 sin.sin_port = htons(SERVER_PORT); 
 /* abertura ativa */ 
 if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) { 
 perror("simplex-talk: socket"); 
 exit(1); 
 } 
 if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) 
 { perror("simplex-talk: connect"); 
 close(s); 
 exit(1); 
 } 
 /* loop principal: obtém e envia linhas de texto */ 
 while (fgets(buf, sizeof(buf), stdin)) { 
 buf[MAX_LINE-1] = '\0'; 
 len = strlen(buf) + 1; 
 send(s, buf, len, 0); 
 } 
 return 0; 
} 
Novamente, foram necessárias modificações em relação ao código original do livro. Assim como no caso do 
servidor, foi necessário incluir novas bibliotecas. 
Para uso em rede local onde não há registro de nomes DNS, não é necessário obter o host pelo DNS. Ao contrário, 
o programa obtém um IP em dotted notation, que é digitado na linha de comando ao executar o programa do 
cliente. Ele é o único argumento necessário para iniciar a conexão, visto que a porta está declarada com um 
valor fixo, que é a mesma porta que em que o servidor realiza a abertura passiva. Para colocar o endereço inserido 
na estrutura de endereçamento em um bloco de 32 bits em network byte order, é utilizada a função inet_addr(). 
De maneira semelhante, a função htons() converte o número da porta para network byte order. 
2.3 Testes e Resultados 
 
2.3.1 Checagem de funcionamento do Simplex-Talk 
 
Primeiramente, para verificar o funcionamento do Simplex-talk, realizou-se um teste simples de conexão entre dois 
computadores de uma rede local wifi. Uma máquina rodou o programa do servidor, enquanto outra máquina 
rodou o programa do cliente. A máquina original estava conectada em uma rede wifi, mas a máquina virtual 
mapeia a conexão como se ela fosse realizada através de um cabo Ethernet. A configuração utilizada na 
máquina virtual é “Placa em Modo Bridge” (Figura 1). O endereço da máquina em seu sistema operacional 
original (Windows 7) era 192.168.1.7, enquanto o IP da máquina virtual (onde estava o programa do servidor) foi 
dado por 192.168.1.8 (Figura 2). Com isso, é possível perceber que uma máquina virtual realmente representa uma 
nova máquina na rede, e possui um IP próprio independente. 
 
Figura 1 – Configuração de rede da máquina virtual 
 
Figura 2 – Verificação do endereço IP da máquina do servidor 
Verificado o endereço IP da máquina do servidor, passamos à tarefa de iniciar o programa. Para executá-lo, 
bastou digitar o seu caminho no terminal no Linux. O caminho corresponde ao diretório em que o programa do 
servidor foi compilado em modo Release: 
$ /home/clarisse/workspace/Server/Release/Server 
Na máquina do cliente, também compilou-se o código em modo Release. Depois, para executá-lo no terminal 
do Linux, realizou-se um comando semelhante ao anterior, localizando o programa do cliente no diretório onde 
ele foi compilado, mas acrescentando-se um parâmetro, que é o endereço IP do servidor: 
$ /home/clarisse/workspace/Client/Release/Client 192.168.1.8 
Com isso, mensagens digitadas no terminal do cliente foram enviadas para o servidor com sucesso, demonstrando 
o funcionamento correto do Simplex-talk. 
2.3.2 Execução de 11 clientes simultaneamente com MAX_PENDING = 5 
 
Após a checagem de funcionamento do programa, realizou-se então o exercício 32 do livro-texto, destacando 
que o número máximo de conexões pendentes estava configurado para ser igual a 5. Reiniciou-se o programa 
do servidor e o do cliente. No programa do cliente, a mensagem “cliente 1” foi enviada. Abriram-se então mais 
10 janelas de terminais, e em cada uma delas executou-se novamente o programa do cliente. Na segunda janela 
aberta, enviou-se a mensagem “cliente 2”. Na terceira janela aberta, enviou-se “cliente 3”, e assim 
respectivamente até a mensagem do “cliente 11”. O servidor, até então, só mostrou a mensagem do primeiro 
cliente: 
 
Figura 3 – Saída do servidor quando 11 programas de clientes foram abertos 
 
Esperou-se cerca de 2 minutos com essa situação e então a janela do cliente 1 foi fechada. Imediatamente, o 
servidor recebeu a mensagem “cliente 2”. Fechando a janela de “cliente 2”, o servidor recebe “cliente 3”, e assim 
sucessivamente até o “cliente 7”. No entanto, quando a janela do “cliente 8” é fechada, essa mensagem não 
aparece no terminal do servidor. O mesmo acontece com os outros clientes abertos. Nenhuma mensagem de 
erro é emitida pelos clientes cujas mensagens não apareceram no terminal do servidor. A saída do servidor é 
mostrada da Figura 4: 
 
Figura 4 – Saída do servidor quando as janelas dos clientes vão sendo fechadas após um certo tempo com 
MAX_PENDING = 5 
Repetindo este procedimento sem esperar o tempo de 2 minutos, o resultado é outro. Novamente, abriram-se 11 
janelas de clientes, e para agilizar o processo, cada cliente mandou uma mensagem com um número que 
representa a ordem das conexões: “1”, “2”, “3”, ... “11”. Imediatamente, fecharam-se os terminais na ordem em 
que eles foram conectados, ou seja, primeiro o terminal que mandou a mensagem “1”, depois o que mandou a 
mensagem “2” e assim até o terminal que mandou a mensagem “11”. A Figura 5 mostra a saída do servidor nesta 
situação: 
 
Figura 5 – Saída do servidor quando os terminais dos clientes são fechados imediatamente após o envio das 
mensagens 
Mediante estes dois últimos testes, é possível perceber o que acontece com os clientes de 1 a 7. Inicialmente, o 
cliente 1 se conecta ao servidor. Neste momento, a “accept()” cria um novo soquete (new_s), e entra no último 
loop do código, que é um while correspondente à recepção e exibição de mensagens enviadas por esse cliente, 
que é destacado na Figura 6: 
 
Figura 6 – Destaque do loop final do código do servidor 
Quando o terminal do primeiro cliente é fechado, então o “accept()” é novamente realizado. Aparentemente, 
só então o Simplex-talk reconhece os pedidos de conexão realizados pelos outros terminais. A conexão número 2é imediatamente aceita e a mensagem “cliente 2” é exibida. Como o limite de conexões na fila é de 5, os clientes 
de número 3 a 7 são enfileirados e ficam aguardando sua vez de obter um soquete exclusivo para realizar a 
comunicação com o servidor. 
O que acontece com os clientes de número 8 a 11 parece ser um timeout, apesar de não haver nenhuma 
mensagem de erro emitida por eles. Isso porque quando se espera um tempo aproximado entre 1 e 2 minutos 
para se fechar os terminais dos clientes, as mensagens enviadas por eles não chegam a aparecer na tela, o que 
indica que nenhum novo soquete foi criado para que eles pudessem estabelecer conexão com o servidor. Já 
quando os terminais são fechados imediatamente após o envio de todas as mensagens, as mensagens desses 
clientes chegam, ainda que fora de ordem. Isso indica provavelmente que os clientes 8 a 11 ainda estavam 
tentando realizar a conexão, o que tornou possível encaixá-los na fila um a um a cada vez que uma janela de 
terminal de outro cliente era fechada. 
Em uma tentativa de entender o problema, vários trechos de “printf()” foram colocados no código e o exercício 
foi repetido. O trecho do código do servidor alterado é mostrado na Figura 7 (apenas o trecho final foi alterado, 
sendo que foi declara uma variável “numAcp” que é um contador de número de “accept()”’s que o servidor 
realizou). Novamente, um tempo entre 1 e 2 minutos foi dado antes de se começar a fechar os terminais dos 
clientes abertos. A saída nesta situação está mostrada na Figura 8. 
 
Figura 7 – Inserção de prints para testar o código do servidor 
 
Figura 8 – Saída do servidor após a inserção dos prints 
 
 
 
Com este teste, é possível ver que após o cliente 7 ser fechado, o programa volta ao início do loop mas não 
consegue prosseguir. O que é possível deduzir é que o código do servidor fica preso no “accept()”, porque se 
essa função retornasse algum valor, o código do if/else seria executado e imprimiria alguma das opções de saída 
presentes no if e no else. 
2.3.3 Execução de 11 clientes simultaneamente com MAX_PENDING = 1 
 
Como é solicitado no exercício 32, alterou-se o código do servidor de forma que o número máximo de conexões 
pendentes fosse alterado de 5 para 1. Isso significa que apenas uma conexão pode ser enfileirada pelo servidor. 
Apenas o “define” foi alterado no início do código: 
#define MAX_PENDING 1 
 
Repetiram-se então os testes com a abertura de 11 janelas de clientes, cada um mandando uma mensagem 
numerada de 1 a 11, assim como foi descrito na seção anterior. Primeiro, realizou-se o teste com a espera de 2 
minutos para começar a fechas os terminais dos clientes. A saída é mostrada na Figura 9: 
 
Figura 9 – Saída do servidor quando as janelas dos clientes vão sendo fechadas após um certo tempo com 
MAX_PENDING = 1 
 Também realizou-se o teste de fechar as janelas dos 11 terminais imediatamente após o envio de todas as 
mensagens. Diferentes saídas foram obtidas no servidor para este caso. As figuras 10 e 11 mostram dois exemplos: 
 
Figura 10 – Primeira saída do servidor quando os terminais dos clientes são fechados imediatamente após o 
envio das mensagens e MAX_PENDING = 1 
 
 
Figura 11 – Segunda saída do servidor quando os terminais dos clientes são fechados imediatamente após o 
envio das mensagens e MAX_PENDING = 1 
 
Novamente, o resultado sugere que há ocorrência de timeout, apesar do programa não gerar os erros esperados. 
No primeiro caso, quando espera-se o tempo de 1 a 2 minutos para fechar as janelas dos clientes, a saída mostra 
apenas os clientes 1, 2 e 3. Assim como ocorreu anteriormente, é possível assumir que quando o servidor aceita a 
conexão 1, ele fica “preso” no loop mostrado na Figura 6. Quando o terminal do cliente 1 é fechado, ele aceita 
a conexão do cliente 2 e coloca apenas o próximo cliente na fila: o cliente 3. Os próximos clientes acabam não 
conseguindo um lugar na fila e provavelmente atingem seus respectivos tempos limites de tentativas de conexão. 
O programa então fica novamente preso no código do “accept()”, que não retorna nenhum valor. 
Em seguida, os clientes são abertos, enviam mensagens contendo seus respectivos números de ordem de abertura 
e são fechados imediatamente após todas as mensagens serem enviadas. Esse teste foi realizado 5 vezes, e as 
saídas foram diferentes em todas elas. Duas saídas foram mostradas nas figuras 8 e 9. Devido à incapacidade 
humana de realizar este experimento exatamente com a mesma duração, algumas conexões aparentam dar 
timeout enquanto com outras isso não acontece. É importante notar que as conexões números 1, 2 e 3 sempre 
chegam ao servidor. 
 
2.3.4 Teste de conexão do cliente em uma porta diferente daquela do servidor 
 
Alterando-se a porta do programa do servidor para 54322 e executando-se o cliente, esperava-se que a 
conexão fosse recusada. Isso foi exatamente o que aconteceu. No código do servidor, o “define” ficou o 
seguinte: 
#define SERVER_PORT 54322 
A saída do cliente para essa situação é mostrada na Figura 12. 
 
Figura 12 – Conexão recusada pelo servidor após a alteração de sua porta 
3. Conclusões 
 
O programa Simplex-talk funciona, mas não da forma esperada. Quando existe apenas um cliente conectado a 
um servidor, as mensagens que o cliente envia chegam corretamente. Quando um cliente tenta se conectar a 
um endereço ou porta errados, a conexão é recusada. 
Quando vários clientes tentam se conectar e mandar mensagens ao mesmo tempo, apenas um cliente consegue 
se comunicar por vez. Aparentemente, ao aceitar a conexão do primeiro cliente, o programa do servidor fica 
“preso” no loop de leitura e impressão das mensagens. Quando a conexão do primeiro cliente é fechada, 
aqueles que ficaram tentando se conectar são então processados na fila de espera. Com a inserção de “prints” 
no código do servidor, foi possível ver que após o último cliente que estava na fica ser fechado, o servidor fica 
bloqueado no “accept()”, que não retorna nenhum valor para o novo soquete. 
Se há um número de clientes tentando se conectar que é maior do que o tamanho máximo permitido na fila, 
parece haver um erro de timeout com os clientes que tentam se conectar por último, apesar de que nenhum 
deles exibe mensagem de erro. 
 
4. Bibliografia 
 
[1] PETERSON, L. L.; DAVIE, B. S. Computer Networks: a system approach. 5th Edition. Burlington, USA. Ed. Elsevier, 
2012. 921 p. 
 
[2] Ubuntu. Wikipedia. Disponível em: 
< http://pt.wikipedia.org/wiki/Ubuntu>. Acesso em: 17 mar. 2014. 
 
[3] How to download and install prebuilt OpenJDK packages. Disponível em: 
< http://openjdk.java.net/install/index.html>. Acesso em: 5 mar. 2014.

Outros materiais