Como podemos criar um protocolo TCP / IP Servidor / Cliente no Delphi?
Este artigo é uma versão redefinida o meu artigo anterior
(http://www.howtodothings.com/showarticle.asp?article=220 Fazendo um aplicativo de um cliente TCP / IP (com código de exemplo )...). Talvez isto esteja atrasado, mas espero que seja útil. Neste artigo, eu tentei explicar / debater, em geral, como criar clientes e servidores TCP-IP com o Delphi.
O que eu tentei demonstrar naquele código exemplo?
Eu tentei demonstrar um simples aplicativo de cliente TCP-IP que se conecta a uma porta específica em um servidor TCP-IP e troca dados. Eu não disse nada sobre o servidor exceto que o meu aplicativo estava conversando com um servidor TCP-IP escrito em Java. Mas tudo o que você precisa para conversar com um servidor são as informações de endereço/host e porta/serviço. E para conversar com o servidor, você tem que se certificar de que o servidor está sendo executado. É isso aí. Você não precisa se preocupar em como o é implementado a menos que você queira desenvolver ambos o servidor e o cliente sozinho. Neste artigo, deixe-me dar uma breve visão geral de como escrever um servidor TCP-IP em Delphi.
Isto é o que eu fiz nesse código fonte:
1. Estabeleci uma conexão ao servidor quando o aplicativo é iniciado.
2. Usei um procedimento SendXml para enviar dados ao servidor.
3. Usei o evento OnClientSocketRead para ler de volta os dados do servidor.
4. Usei o evento OnClientSocketError para capturar os erros
Você verá um sinalizador Boolean chamado fWaiting em ambos os procedimentos SendXml e OnClientSocketRead. No meu aplicativo, vou enviar alguns dados para o servidor e aguardar o servidor responder de volta. Vou aguardar essencialmente o evento OnClientSocketRead acontecer na esperança de que o servidor responda o mais rápido possível. Essa é a razão pela qual eu uei um sinalizador Boolean fWaiting.
Onde começa a ter uma idéia de qual o cliente TCP-IP e servidor TCP-IP?
Para pessoas que querem experimentar, gostaria de sugerir-lhes que dêem uma olhada no projeto demo chamado Chat.dpr em ambos Delphi 5 e 6. A seguir, estão os links para o projeto:
Delphi 5:
C:\Program Files\Borland\Delphi5\Demos\Internet\Chat\chat.dpr
Delphi 6:
C:\Program Files\Borland\Delphi6\Demos\Internet\Chat\chat.dpr
O que é basicamente um cliente TCP-IP?
É um aplicativo que se conecta a uma porta específica em um servidor TCP-IP e troca dados ou como stream ou como texto.
O que você precisa criar um com Delphi?
Tudo o que você precisa é um componente TClientSocket disponível na paleta internet para definir as seguintes propriedades:
Endereço: Você pode digitar o endereço IP do servidor TCP-IP ao qual este cliente vi se conectar.
Anfitrião: Em vez de endereços, você pode inserir um nome do alias para o endereço IP aqui na propriedade do Host. É óbvio definir a propriedade ou de endereço ou de Host. Mas o que acontece se você definir as duas? Propriedade Host tem precedência sobre a propriedade Endereço.
Definir a propriedade Host seria melhor em comparação com a propriedade endereço, uma vez que se você mudar o servidor para o TCP-IP ou qualquer outra máquina alterar o endereço IP para qualquer outra coisa, desde que mantenha o mesmo nome do alias, fica tudo bem; você não precisa se preocupar em alterá-lo no protocolo cliente TCP-IP. (Mesmo que se trate de uma ligeira sobrecarga de resolver o nome do host correspondente ao seu endereço IP, vale a pena ter)
Porta: É um número de porta inteiro válido onde o servidor TCP-IP escuta. (e responde.) É sempre um número fixo atribuído pelo servidor. Para esse número de porta, o cliente irá conectar-se e enviar e receber dados.
Serviço: Assim como as propriedades host e endereço estão ligadas entre si em uma forma, propriedades de Porta e Serviço também estão ligadas. Em geral, é algo que o servidor TCP-IP pode fornecer a seus clientes como http, ftp. Estes serviços padrão foram atribuídos a um determinado número de porta no servidor. (ex.: http - porta 80). Como funciona? No servidor, há um arquivo de serviços que mapeia os serviços para suas respectivas portas. Assim, você pode ter sua própria descrição do serviço que mapeia para um determinado número de porta no servidor. Nesse caso, o cliente pode ligar para o serviço usando a propriedade de Serviço e interagir.
ClientType: Esta propriedade determina se a interação entre o servidor e o cliente ocorre de forma sincronizada ou assíncrona.
ctNonBlocking - O padrão. Isso indica que a interação entre o servidor e o cliente ocorre de forma assíncrona. Ou seja, o cliente pode enviar dados para o servidor e aguardar o OnRead de dados ocorrer, quando os dados são enviados de volta do servidor.
ctBlocking- Isto é usado para interação ocorrer sincronicamente entre o servidor e o cliente.
Quando a tornar o código do cliente seguro ao thread?
Se mais de um pedido é enviado para o servidor a partir de um aplicativo de cliente de cada vez, então o código do cliente deve ser seguro ao thread. Caso contrário, a solicitação-resposta podem colidir.
Quando fazer o código do servidor seguro ao thread?
Se mais de uma solicitação for enviada ao servidor ou de um aplicativo de cliente ou de diferentes aplicativos de cada vez, então o código do servidor deve ser seguro ao thread. Isto é aplicável a todos os servidores de TCP-IP escritos em outras línguagens também.
Espero que eu esteja sendo claro na parte de segurança ao thread.
Qual é o melhor lugar para colocar o componente TClientSocket em um aplicativo?
Você pode colocar o componente seja em um formulário ou DataModule. Se você só tem um único formulário no aplicativo do cliente que fala com um servidor, então não há problema em colocar esse componente TClientSocket dessa forma. Mas se você tem muitos formulários de aplicativos do cliente, então é melhor colocar o componente em um DataModule e usar o DataModule sempre que necessário. Eu usei um DataModule no meu aplicativo de cliente, uma vez que eu tinha muitos formulários, cada um conversando com o servidor em um ponto diferente do tempo.
Como é que você estabelece uma conexão com o servidor?
Defina todas as propriedades acima mencionadas e, em seguida, defina ou a propriedade Active para verdadeira ou chame o método Open. Depois de estabelecer uma conexão, você pode enviar os dados usando o método SendText ou SendStream. E você pode usar o evento OnClientSocketRead para ler os dados novamente a partir do servidor.
O que é um servidor TCP-IP?
É um aplicativo que escuta numa determinada porta e responde aos clientes. Poderia ser qualquer servidor normal, como http, ftp ou um servidor personalizado feito para seu aplicativo específico.
O que você precisa para criar com Delphi?
Assim como acontece com o cliente, você precisa de um componente TServerSocket com as seguintes propriedades definidas:
Porta: Você pode atribuir qualquer valor inteiro válido. Para esta porta, o cliente pode conectar-se e interagir com o servidor.
Serviço: Como eu disse anteriormente, você pode ter um nome de serviço associado a um número de porta.
Quando dizemos servidor, ele deve ser capaz de servir mais de um cliente obviamente; só então faz sentido ter um servidor. Certo? Agora, a próxima questão é saber como estes clientes estão se comunicando com o servidor: mais de um cliente de cada vez ou um cliente por vez. Ela leva à seguinte configuração de propriedade que determina se o cliente fala com o servidor de sincronização ou assincronamente.
Como devemos lidar com mais do que uma solicitação de cliente ao mesmo tempo?
A resposta é lançar um novo tópico para cada solicitação de cliente. Isto pode ser alcançado configurando a propriedade ServerType para stThreadBlocking. Será que desovar e destruir uma thread para cada solicitação de cliente vira uma sobrecarga? Sim. Obviamente. Mas se o nosso design do aplicativo exige isso, então não há outra maneira, você tem que ter essa sobrecarga. Podemos reduzir a sobrecarga de criar e destruir threads? Sim. Nós podemos. Como? Cache os threads. Certo.
A propriedade ThreadCacheSize serve para essa finalidade. O valor padrão é 10, mas este valor depende das necessidades do seu aplicativo de cliente. Você deve ter muito cuidado ao definir este valor. Se você definir um valor máximo para ela, você irá acabar com problemas de memória. Se você configurá-la para um valor muito baixo, o cliente terá um tempo de espera para cada solicitação. Então você tem que determinar o melhor valor baseado em estatísticas do cliente.
Se as solicitações do cliente estão chegando, uma de cada vez, então você pode definir a propriedade ServerType para stNonBlocking.
Como é que lemos dados de volta a partir do cliente? Assim como acontece com ClientSocket, temos o evento OnClientRead para ler dados do cliente, entre outros eventos.
É isso. Espero que você possa escrever sozinho tanto um cliente quanto um servidor com esta informação.
Como de costume, sinta-se livre para compartilhar suas opiniões, sugestões e experiências com a nossa comunidade Delphi.