Você está na página 1de 12

3.

Projeto e implementao de Servidores


3.1 Introduo
Este captulo discute questes fundamentais relacionadas ao projeto de software servidor, incluindo acesso com conexo vs. sem conexo a servidores e implementaes iterativos vs. concorrentes de servidores.

3.2 O Algoritmo conceitual do servidor


Conceitualmente, um servidor segue um algoritmo simples: cria um soquete e o liga a uma porta conhecida onde espera conexes. O servidor entra ento em um ciclo infinito no qual aceita o prximo pedidos de um cliente, processa o pedido, formula a resposta e a envia ao cliente. Infelizmente, este algoritmo vlido apenas para um pequeno conjunto de servidores triviais. Considere, por exemplo, um servio de transferncia de arquivos que necessita de um tempo substancial para tratar cada pedido. Suponha que um primeiro cliente pea a transferncia de um arquivo grande (por exemplo 800 megabytes), enquanto que um segundo cliente pea a transferncia de um arquivo pequeno (por exemplo 20 bytes). Se o servidor esperar at transmitir completamente o primeiro arquivo antes de iniciar a transferncia do segundo, o segundo cliente dever esperar um tempo excessivamente longo para conseguir a transferncia de um pequeno arquivo. Como o arquivo desejado pequeno, o segundo usurio espera que o servidor responda imediatamente. Na prtica, os servidores manipulam pedidos pequenos rapidamente, porque eles tratam mais do que um pedido ao mesmo tempo.

3.3 Servidores concorrentes versus servidores iterativos.


O termo servidor iterativo usado para descrever implementaes que processam um nico pedido de cada vez, e o termo servidor concorrente para descrever implementaes que manipulam mltiplos pedidos ao mesmo tempo. Neste contexto, o termo servidor concorrente est relacionado capacidade do servidor de manipular vrias requisies concorrentemente e no sua implementao usar vrios processos ou linhas de execuo (threads). O importante que, sob a perspectiva do cliente, o servidor parece se comunicar com vrios clientes de forma concorrente. Em geral, servidores concorrentes so mais difceis de projetar e construir, e o cdigo resultante mais complexo e mais difcil de modificar. Entretanto, a maioria dos projetistas escolhe implementar servidores concorrentes, porque servidores iterativos introduzem atrasos desnecessrios em aplicaes distribudas e podem gerar gargalos de desempenho que afetam a muitas aplicaes clientes.

3.4 Acesso orientado a conexo versus acesso sem conexo


No conjunto de protocolos TCP/IP, o TCP fornece um servio de transporte orientado a conexo enquanto que o UDP fornece um servio sem conexo. Por definio, os servidores que usam o TCP so servidores orientados a conexo e os servidores que usam o protocolo UDP so servidores sem conexo1. A escolha entre um servio orientado a conexo e um servio sem conexo depende do protocolo de aplicao. Um protocolo de aplicao projetado para usar um servio de transporte orientado a conexo pode funcionar de forma incorreta ou ineficiente se usar um protocolo de transporte sem conexo.

3.5 Servidores orientados a conexo


A grande vantagem da abordagem orientada a conexo est na facilidade de programao. Como o protocolo de transporte trata automaticamente problemas como a perda de pacotes e a entrega fora de ordem, o servidor no precisa se preocupar com isso. Em vez disso, um servidor orientado a conexo administra e usa conexes. Ele aceita pedidos de conexes de clientes, comunica-se atravs das conexes abertas e as fecha aps ter completado a interao. Enquanto uma conexo permanece aberta, o TCP fornece todos os requisitos de confiabilidade. Ele retransmite dados perdidos, verifica se os dados chegaram sem erro de transmisso e, quando necessrio, reordena os pacotes de entrada. Quando um cliente envia um pedido, o TCP o entrega corretamente ou informa ao cliente que a conexo foi interrompida. Da mesma forma, o servidor pode contar com o TCP para entregar as respostas ao cliente ou para ser informado de que a entrega no possvel. Servidores orientados a conexo tambm possuem desvantagens. Servidores orientados a conexo necessitam de um soquete separado para cada conexo, enquanto que servidores sem conexo permitem a comunicao com mltiplos hospedeiros usando um nico soquete. A alocao de soquetes e a administrao de conexes podem ser especialmente importantes para os sistemas operacionais, j que eles devem rodar permanentemente sem exaurir os recursos disponveis. Para aplicaes triviais, a sobrecarga do protocolo de apresentao em trs vias usado para estabelecer e terminar uma conexo faz o TCP oneroso se comparado ao UDP. A desvantagem mais importante que o TCP no envia pacotes atravs de uma conexo ociosa. Suponha que um cliente estabelece uma conexo com um servidor, troca pedidos e respostas e ento cai: assim que o servidor tiver respondido a todos os pedidos recebidos ele no enviar mais dados ao cliente, provocando uma m utilizao de seus recursos. O servidor tem estruturas de dados (incluindo espao em buffer) alocadas para a

conexo, e estes recursos no sero mais usados. Um servidor projetado para rodar continuamente e se seus clientes carem repetidamente ficar sem recursos (ou seja, sem soquetes, espao em buffer, conexes TCP) e no poder atender a novos pedidos de conexo.

3.6 Servidores sem conexo


Servidores sem conexo tambm possuem vantagens e desvantagens. Se por um lado os servidores sem conexo no sofrem do problema da diminuio (ou esgotamento) de recursos, por outro lado, no podem depender da camada de transporte subjacente para obter a entrega confivel dos dados. Um dos lados deve assumir a responsabilidade pela entrega confivel. Normalmente, os clientes se responsabilizam por retransmitir os pedidos cujas respostas no chegarem. Se o servidor necessitar dividir a sua resposta em vrios pacotes de dados, ele tambm pode precisar implementar um mecanismo de retransmisso. Conseguir confiabilidade atravs de mecanismo de retransmisso e de tempos de espera (timeouts) pode ser extremamente difcil, de modo que programadores novatos devem procurar usar um servio de transporte orientado a conexo. A escolha de um projeto orientado a conexo ou no orientado a conexo depende tambm de a aplicao requerer comunicao do tipo broadcast ou multicast, j que esse tipo de comunicao oferecido apenas pelo UDP.

3.7 Servidores com e sem estado


A informao que um servidor mantm sobre as interaes correntes com os clientes chamada de informao de estado. Servidores que guardam informao de estado so chamados de servidores com estado e os outros de servidores sem estado. A busca de eficincia motiva projetistas a manterem informao de estado nos servidores. A informao de estado pode reduzir o tamanho das mensagens que clientes e servidores trocam, e pode permitir que os servidores respondam rapidamente. Essencialmente, informao de estado permite que um servidor lembre-se do que o cliente requisitou anteriormente e compute uma resposta incremental medida que cada novo pedido chegar. |Por outro lado, a motivao para no manter estado est associada confiabilidade dos protocolos: a informao de estado em um servidor pode ficar incorreta se mensagens forem perdidas, duplicadas ou entregues fora de ordem, ou se o cliente cair e reiniciar a sua execuo.

A interface socket permite que uma aplicao conecte um socket UDP a um ponto remoto, mas a conexo com o servidor no efetivamente realizada.

3.8 Quatro tipos bsicos de servidores


Servidores podem ser iterativos ou concorrentes, e podem usar transporte orientado a conexo ou transporte sem conexo. A Fig. 2 mostra que essas propriedades agrupam os servidores em quatro categorias gerais.
sem conexo iterativo orientado a conexo iterativo

sem conexo concorrente

orientado a conexo concorrente

Figura 1: As quatro categorias gerais definidas pelo oferecimento de concorrncia e pelo uso de servio de transporte orientado a conexo.

3.9 Tempo de processamento de uma requisio


Em geral, servidores iterativos so adequados apenas a protocolos de aplicao triviais. O teste para saber se uma implementao iterativa ser suficiente foca o tempo de resposta necessrio, que pode ser medida local e globalmente. Define-se o tempo de processamento de uma requisio pelo servidor como sendo o tempo total que o servidor leva para tratar um pedido isolado, e o tempo de resposta observado pelo cliente como sendo o atraso total entre o instante em que o pedido enviado e o instante em que a resposta do servidor chega. Evidentemente, o tempo de resposta observado nunca poder ser menor que o tempo de processamento de uma requisio, entretanto, se o servidor mantm uma fila de pedidos esperando atendimento, o tempo de resposta observado pode ser muito maior que o tempo de processamento de uma requisio. Servidores iterativos manipulam um nico pedido por vez. Se um pedido chega enquanto o servidor estiver ocupado manipulando um pedido anterior, o sistema enfileira o novo pedido. Quando o servidor termina o processamento de um pedido, ele consulta a fila. Se N denota o comprimento mdio da fila de pedidos, o tempo de resposta para um pedido de chegada ser aproximadamente igual a N/2 + 1 vezes o tempo que o servidor leva para processar um pedido. Como o tempo de resposta observado proporcional a N, a maioria das implementaes restringe N a um valor pequeno (por exemplo 5) e usa-se servidores concorrentes quanto uma fila pequena no for suficiente. A carga total tratada pelo servidor tambm deve ser considerada na deciso de implementao de servidores iterativos ou concorrentes. Um servidor projetado para manipular K clientes, cada qual

enviando R pedidos por segundo, deve ter um tempo de processamento menor que 1/KR segundos por pedido. Se o servidor no puder tratar os pedidos a essa taxa, ocorrer o transbordamento na fila de espera. Nesse tipo de situao, o projetista dever considerar a implementao de um servidor concorrente.

3.10 Algoritmos para servidores iterativos


Um servidor iterativo fcil de projetar, programar, depurar e modificar. Por isso, a maioria dos programadores escolhe projetar servidores iterativos sempre que a sua execuo fornece respostas suficientemente rpidas para a carga esperada. Normalmente, servidores iterativos so mais adequados a servios simples, acessados por protocolos sem conexo. Entretanto possvel implementar servidores iterativos com conexo e sem conexo.

3.11 Um algoritmo para servidor iterativo orientado a conexo


O Algoritmo 1 apresenta o algoritmo para um servidor iterativo acessado atravs do protocolo orientado a conexo TCP. Os passos do algoritmo so discutidos a seguir com mais detalhes. Algoritmo 1 1. Criar um soquete e lig-lo (bind) ao endereo conhecido para o servio oferecido. 2. Colocar o soquete no modo passivo, tornando-o pronto para ser usado pelo servidor. 3. Aceitar o prximo pedido de conexo ao soquete e obter um novo soquete para a conexo. 4. Repetidamente, ler pedidos do cliente, formular uma resposta e enviar a resposta de volta ao cliente de acordo com o protocolo de aplicao. 5. Quando terminar de atender ao cliente, fechar a conexo e retornar ao passo 3 para aceitar uma nova conexo.
Algoritmo 1: Servidor iterativo orientado a conexo. Um nico processo manipula conexes de clientes, um por vez.

3.12 Ligando um servidor a um endereo usando INADDR_ANY


Um servidor precisa criar um soquete e lig-lo a uma porta conhecida associada ao servio oferecido. Como os clientes, os servidores usam o procedimento getportbyname() para mapear o nome de um servio em um nmero de porta conhecida. Por exemplo, o TCP/IP define um servio de ECHO. Um servidor que implementa o servio de ECHO usa getportbyname() para mapear a cadeia "echo" porta 7. Quando a primitiva bind() especifica um ponto de conexo final para um soquete, ela usa a estrutura sockaddr_in, que contm tanto o endereo IP como o nmero da porta do protocolo. Logo

bind() no pode especificar um nmero de porta de protocolo sem especificar um endereo IP. Infelizmente, selecionar o endereo IP do servidor onde sero aceitas conexes pode ser difcil. Roteadores e hospedeiros multi-homed podem ter vrios endereos IP. Se o servidor especificar um endereo IP particular, o soquete no aceitar comunicaes de clientes que enviarem pedidos para um outro IP da mquina. Para resolver este problema, a interface socket define uma constante especial, INADDR_ANY, que pode ser usada no lugar de um endereo IP. INADDR_ANY especifica um endereo coringa que pode assumir qualquer um dos endereos IPs do hospedeiro. INADDR_ANY torna possvel a um mesmo servidor aceitar qualquer comunicao endereada a qualquer endereo IP do hospedeiro.

3.13 Colocando o soquete no modo passivo


Um servidor TCP chama listen() para colocar o servidor no modo passivo. listen() tambm recebe um argumento que especifica o comprimento da fila interna de requisies para o soquete. A fila de pedidos guarda os pedidos de conexo TCP que chegaram de clientes e ainda no foram aceitas.

3.14 Aceitando conexes e usando-as.


O servidor TCP chama accept() para obter o prximo pedido de conexo (ou seja, para retir-lo da fila de pedidos de conexo). A chamada retorna o descritor de um soquete a ser usado pela nova conexo. Uma vez aceita uma nova conexo, o servidor usa recv() ou read() para obter pedidos do protocolo de aplicao do cliente e send() ou write() para enviar respostas. Finalmente, ao terminar o atendimento ao cliente, o servidor chama close() para liberar o soquete.

3.15 Algoritmo de servidor iterativo sem conexo


Servidores iterativos so mais adequados para servios que tm um baixo tempo de processamento de requisio. A maioria dos servidores iterativos usa protocolos no orientados a conexo (v. Algoritmo 2), como o UDP, pois os protocolos de transporte orientados a conexo, como o TCP, apresentam maiores custos (overhead).

Algoritmo 2
1. Criar um soquete e lig-lo a um endereo conhecido para o servio sendo oferecido. 2. Repetidamente, ler a prxima requisio do cliente, formular uma resposta e envila ao cliente de acordo com o protocolo de aplicao.
Algoritmo 2: Servidor iterativo sem conexo. Uma nica linha de execuo trata pedidos (datagramas) de clientes, um por vez.

O procedimento de criao de um soquete para um servidor iterativo sem conexo o mesmo usado para o servidor orientado a conexo. Neste caso, porm, o soquete do servidor permanece desconectado e pode aceitar datagramas de entrada de qualquer cliente.

3.16 Formando o endereo de resposta em um servidor sem conexo


A interface socket fornece duas formas de especificar um ponto terminal de comunicao remoto. Conforme visto anteriormente, uma dessas formas usando connect(). Entretanto, um servidor sem conexo no pode usar connect() para encontrar o endereo remoto, pois procedendo dessa maneira restringiria o servidor a comunicar-se com um nico endereo IP e nmero de porta. Portanto, um servidor sem conexo usa um soquete desconectado. Ele gera endereos de resposta explicitamente e usa sendto() para especificar tanto o datagrama a ser enviado como o endereo para onde o datagrama dever ser enviado. A primitiva sendto() tem a seguinte forma:
retcode = sendto(s, message, len, flags, toaddr, toaddrlen);

onde s um soquete desconectado, message o endereo de um buffer que contm os dados que devem ser enviados, len especifica o nmero de bytes no buffer, flags especifica opes de controle e depurao, toaddr um ponteiro para uma estrutura sockaddr_in que contm o endereo do destinatrio da mensagem e toaddrlen um inteiro que especifica o tamanho da estrutura de endereo. A interface socket fornece uma maneira fcil para que servidores sem conexo obtenham o endereo do cliente. A chamada recvfrom() tem dois argumentos que especificam dois buffers. O sistema coloca o datagrama recebido em um buffer e o endereo do remetente no outro buffer. A chamada recvfrom() tem a seguinte forma:
retcode = recvfrom (s, buf, len, flags, from, fromlen);

onde s especifica um soquete, buf especifica o buffer onde o sistema ir colocar o prximo datagrama, len especifica o espao disponvel (bytes) no buffer, flags controla casos especiais (p.ex. verificar se chegou um datagrama sem retir-lo do soquete), from especifica o segundo buffer onde o sistema colocar o endereo da fonte, fromlen especifica o endereo de um inteiro. Inicialmente, o inteiro para onde fromlen aponta especifica o tamanho do buffer from. Quando a chamada retorna, fromlen conter o tamanho do endereo da fonte que o sistema colocar no buffer from. Para gerar uma resposta o servidor usa o endereo que recvfrom() armazena no buffer from quando o pedido chega.

3.17 Algoritmos de servidores concorrentes


A principal razo para introduzir concorrncia em servidores a necessidade de fornecer resposta rpida a mltiplos clientes. A concorrncia diminui o tempo de resposta sob as seguintes condies: Para formar uma resposta necessria uma quantidade significativa de operaes E/S; O tempo de processamento varia consideravelmente entre os pedidos; ou O servidor executado em um computador com vrios processadores. No primeiro caso, permitir que o servidor calcule respostas concorrentemente significa que ele pode sobrepor o uso do processador com o uso de dispositivos perifricos, mesmo que a mquina tenha apenas uma CPU. Enquanto o processador trabalha para formar uma resposta, os dispositivos de E/S podem transferir para a memria os dados necessrios para outras respostas. No segundo caso, o mecanismo de compartilhamento de tempo permite que um nico processador manipule pedidos que necessitem pequena quantidade de processamento, sem que esses pedidos tenham que esperar pelo atendimento de outros mais demorados. No terceiro caso, a execuo paralela em um computador com mltiplos processadores permite que um processador processe uma resposta, enquanto outro processador se encarrega de outra resposta. A maioria dos servidores se adapta automaticamente ao hardware disponvel - quanto maior a quantidade de recursos de hardware (p. ex. mais processadores) melhor o desempenho dos servidores.

3.18 Linhas de execuo mestre e escravas


Embora seja possvel a um servidor propiciar algum nvel de concorrncia usando uma nica linha de execuo (thread), a maioria dos servidores concorrentes usa vrias linhas de execuo.. As linhas de execuo de um servidor concorrente podem ser divididas em dois tipos: mestra e escrava. Uma linha conhecida como mestra inicia a execuo. A linha mestra abre um soquete associado porta conhecida para o servio, espera pelo prximo pedido e cria uma escrava (possivelmente em um novo processo) para tratar o pedido. A mestra nunca se comunica diretamente com o cliente, ela passa esta responsabilidade para a escrava. Cada escrava trata da comunicao com um cliente. Aps formar uma resposta e envi-la ao cliente a escrava termina a sua execuo.

3.19 Algoritmo de servidor concorrente sem conexo


A verso mais direta de servidor concorrente sem conexo apresentada pelo algoritmo 3. Deve-se lembrar que embora o custo exato de criar uma nova thread ou processo dependa do sistema operacional e da arquitetura subjacente, a operao pode ser dispendiosa. No caso de protocolos sem

conexo deve-se considerar cuidadosamente se o custo da concorrncia no maior que o ganho em velocidade. De fato, como criar um processo ou thread dispendioso, poucos servidores sem conexo tm implementaes concorrentes. Algoritmo 3
Mestra 1. Mestra 2. Criar um soquete e lig-lo ao endereo conhecido para o servio que est sendo oferecido. Deixar o soquete desconectado. Repetir: chamar recvfrom() para receber o prximo pedido de um cliente e criar uma nova escrava (possivelmente em um novo processo) para manipular a resposta. Comea com uma requisio especfica passada pela Mestra assim como com acesso ao soquete. Formar uma resposta de acordo com o protocolo de aplicao e envi-la ao cliente usando sendto(). Sair (ou seja, a escrava termina aps tratar um pedido).

Escrava 1. Escrava 2. Escrava 3.

Algoritmo 3 : Servidor Concorrente e sem conexo. A servidora mestra aceita pedidos de entrada (datagramas) e cria escravas (processos/threads) para manipular cada um deles.

3.20 Algoritmo de servidor concorrente orientado a conexo


Protocolos de aplicao orientados a conexo usam uma conexo como paradigma bsico para a comunicao. Estes protocolos permitem que os clientes estabeleam uma conexo com um servidor, comuniquem-se atravs da conexo e finalmente descartem a conexo. O Algoritmo 4 especifica os passos que um servidor concorrente usa para um protocolo orientado a conexo. Algoritmo 4
Mestra 1. Mestra 2. Mestra 3. Escrava 1. Escrava 2. Escrava 3. Criar um soquete e lig-lo a uma porta popular associada ao servio oferecido. Deixar o soquete desconectado. Colocar o soquete no modo passivo, deixando-o pronto para ser usado pelo servidor. Repetir: chamar accept() para receber o prximo pedido de um cliente, e cria uma nova thread ou processo escravo para tratar da resposta. Comea com uma conexo passada pela Mestra (ou seja, um soquete para a conexo). Interagir com o cliente usando a conexo: ler os pedidos e enviar as respostas de volta. Fechar a conexo e sair. A escrava sai aps tratar todos os pedidos de um cliente.

Algoritmo 4: Servidor concorrente orientado a conexo. A linha de execuo mestra aceita uma conexo, cria uma escrava para trat-la. Uma vez que a escrava tenha terminado, ela fecha a conexo.

Como no caso sem conexo, a linha servidora mestra nunca se comunica com o cliente diretamente. Enquanto a escrava interage com o cliente, a mestra espera por outras conexes.

3.21 Implementao de concorrncia em servidores


Como o Linux (e o Unix) oferecem duas formas de concorrncia, processos e threads, duas implementaes do paradigma mestre-escravo so possveis. Na primeira, o servidor cria vrios processos, cada um com uma nica linha de execuo. Na outra, o servidor cria vrias linhas de execuo (threads) dentro do mesmo processo.

3.22 Usando programas separados como escravos


O Algoritmo 4 mostra como um servidor concorrente cria uma novo escrava para cada conexo. Na implementao baseada em processos, isso feito pela servidora mestra usando a chamada da primitiva de sistema fork(). Para protocolos de aplicao simples, um nico programa servidor pode conter todo o cdigo necessrio para a mestra e a escrava. Aps a chamada ao fork(), o processo original volta para aceitar o prximo pedido de conexo, enquanto o novo processo torna-se o escravo e manipula a conexo. Em alguns casos, mais conveniente que o processo escravo execute o cdigo de um programa que tenha sido escrito e compilado independentemente. Sistemas como o Linux e o UNIX podem tratar disso facilmente porque eles permitem que o processo escravo chame execve() aps a chamada de fork(). Execve() sobrecarrega o processo escravo com o cdigo de um novo programa.

3.23 Concorrncia aparente usando uma nica linha de execuo


Em alguns casos, pode ser interessante usar uma nica linha de execuo para tratar as requisies de clientes concorrentemente. Em particular, em alguns SOs a criao de threads ou processos to dispendiosa que os servidores no podem criar uma nova thread para cada requisio ou conexo. Mais importante, muitos protocolos de aplicao requerem que o servidor compartilhe informao entre as conexes. O sistema X Window um exemplo tpico de uso de servidor com concorrncia aparente e uma nica linha de execuo. O X permite que vrios clientes insiram texto ou grficos em janelas que aparecem em uma tela mapeada por bits (bit-mapped). Cada cliente controla uma janela. enviando pedidos que atualizam seu contedo. Cada cliente opera independentemente, e pode passar muito tempo sem mudar a tela, ou pode atualiz-la freqentemente. Um servidor para o sistema X integra informaes obtidas dos clientes em uma sesso de memria nica e contgua chamada display buffer. Os dados que chegam dos clientes contribuem para uma estrutura de dados nica e compartilhada. Embora seja possvel obter a desejada concorrncia usando threads que compartilham memria, tambm possvel obter concorrncia aparente se a carga total dos pedidos apresentados ao servidor no exceder a sua capacidade para trat-los. Para fazer isso, o servidor opera como um thread nico que usa a chamada ao sistema select() para operaes de E/S assncronas. O Algoritmo 5

10

descreve um servidor com uma nica linha de execuo que manipula vrias conexes concorrentemente.

Algoritmo 5
1. Criar um soquete e lig-lo porta bem-conhecida para o servio. Adicionar o soquete a uma lista de soquetes atravs dos quais a E/S possvel. 2. Usar select() para esperar por E/S nos soquetes existentes. 3. Se o soquete original estiver pronto, usar accept() para obter a prxima conexo e adicionar o novo socket lista de soquetes onde E/S possvel. 4. Se algum soquete diferente do original estiver pronto, usar recv() ou read() para obter o prximo pedido, formar a resposta e usar send() ou write() para enviar a resposta de volta ao cliente. 5. Continuar no passo 2 acima.
Algoritmo 5: Servidor concorrente orientado a conexo implementado por uma nica thread. A thread espera pelo prximo descritor que estiver pronto, o que pode significar ser a chegada de uma nova conexo que um cliente enviou uma mensagem atravs, de uma conexo j existente.

3.24 O problema da ocorrncia de impasse (deadlock) no servidor


Muitas implementaes compartilham uma falha importante: o servidor pode estar sujeito ocorrncia de impasses (deadlock2). Considere um servidor iterativo orientado a conexo. Suponha que uma aplicao cliente mal comportada faa uma conexo com o servidor mas nunca envie pedidos. O servidor aceitar a nova conexo e chamar read() para extrair os pedidos, ficando bloqueado numa chamada ao sistema, esperando por uma requisio que nunca chegar. A condio de impasse no servidor pode ser muito mais sutil se o cliente se comportar mal no consumindo recursos. Por exemplo, suponha que um cliente estabelea uma conexo a um servidor, envie-lhe uma seqncia de requisies, mas nunca leia as respostas. O servidor recebe as requisies, gera as respostas e as envia ao cliente. No lado servidor, o protocolo TCP transmite os primeiros bytes para o cliente atravs da conexo. Eventualmente, o mecanismo de controle de fluxo do TCP ir perceber que o buffer de recepo do cliente est cheio e parar de enviar dados. Se o programa de aplicao servidor continuar gerando respostas, o buffer local do TCP, que armazena dados de sada para a conexo, ir se encher e o processo servidor ficar bloqueado. Impasses acontecem porque os processos ficam bloqueados quando o sistema operacional no pode satisfazer uma chamada ao sistema. Em particular, uma chamada a write() bloquear o processo que a invocou se o TCP no tiver espao no buffer local para onde os dados sero enviados; uma chamada a read() bloquear o processo que a invocou at o TCP receber dados. Em servidores
2

O termo impasse, ou deadlock, refere-se a uma condio na qual um programa ou conjunto de programas no pode prosseguir porque esto bloqueados esperando por um evento que nunca acontecer. No caso tratado, a ocorrncia de um impasse leva a que servidor pare de responder a pedidos.

11

concorrentes, ficar bloqueado apenas a thread escrava associada ao cliente que no envia requisies ou no recebe as respostas. Entretanto, em implementaes que usam uma nica thread, o servidor central ficar bloqueado, no podendo tratar outras conexes. A questo importante aqui que qualquer servidor que use apenas uma thread estar sujeito ocorrncia de impasses.

3.25 Resumo
Foram apresentados algoritmos e discutidos alguns aspectos importantes a considerar quando do projeto de software servidor.

Bibliografia
COMER, D. E., STEVENS, D. L., Internetworking With TCP/IP Volume III: Client-Server Programming and Applications, Linux/POSIX Socket Version, Prentice-Hall International 2001, Captulo 8. STEVENS,W.R.; "UNIX NETWORK PROGRAMMING - Networking APIs: Sockets and XTI" Volume 1 - Second Edition - Prentice Hall - 1998 Obs. Resumo preparado por Magda Patrcia Caldeira Arantes e revisado por Juan Manuel Adn Coello.

12