Projetando uma aplicação de protocolo cliente TCP / IP (com código fonte)

Este artigo é uma continuação do meu artigo anterior (http://www.howtodothings.com/showarticle.asp?article=218) destinado a demonstrar como podemos usar o componente TclientSocket em Delphi como um TCP / IP cliente em qualquer TCP / IP. O servidor poderá ser escrito em Delphi utilizando o componente TserverSocket ou qualquer código que funcione como um protocolo TCP / IP servidor. No meu caso, eu estou interagindo com um código Java que funciona como um protocolo TCP / IP servidor.

No meu projeto, estou enviando bytes para o servidor Java, e o servidor Java lê os bytes e faz algumas tarefas enviando bytes diferentes como resposta ao cliente Delphi.

No meu último artigo (http://www.delphi3000.com/article.asp?id=1695), eu expliquei o problema enfrentado e eu achei uma solução para ele.

Neste artigo, darei alguns exemplos de código que eu usei no projeto, dado que algumas pessoas me pediram para enviar o código por e-mail. Eu agradeço o interesse. Vamos lá!

Meu projeto usa umas nove formas e todas precisam interagir com o servidor Java, pelo menos uma vez. Então, acrescentei um DataModule e pus um Componente TClientSocket lá:

Segue o código:

unit DataMod;

interface

uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

ScktComp, OleServer;

type

TdmDataModule = class(TDataModule)

csClientSocket: TClientSocket;

procedure csClientSocketError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);

procedure csClientSocketRead(Sender: TObject;

Socket: TCustomWinSocket);

procedure DataModuleDestroy(Sender: TObject);

private

{ Declarações Privadas}

public

FWaiting : boolean;

{ Declarações Publicas }

end;

var

dmDataModule: TdmDataModule;

implementation

{$R *.DFM}

procedure TdmDataModule.csClientSocketRead(Sender: TObject;

Socket: TCustomWinSocket);

//Lendo dados do servidor pelo soquete

var

Buffer : array [0..4095] of char;

BytesReceived : integer;

MemoryStream : TMemoryStream;

begin

while FWaiting do

begin

MemoryStream := TMemoryStream.Create;

try

/ / Agora o tempo de demora (time delay) depende do tráfego de rede, e você também pode coloca-lo entre parêntesis

/ / Acabei de colocar cerca de 200 milissegundos antes de começar a leitura a partir do servidor.

Sleep(200);

while True do

begin

BytesReceived := Socket.ReceiveBuf(Buffer,SizeOf(Buffer));

if (BytesReceived <= 0) then

Break

else

begin

MemoryStream.Write(Buffer,BytesReceived);

end;

end;

FWaiting := False;

MemoryStream.Position := 0;

// XMLResponse é uma string lista global, estou usando para converter bytes recebidos em caracteres

//Você pode usar outros modos de obter conteúdo de memorystream

XMLResponse.LoadFromStream(MemoryStream);

finally

MemoryStream.Free;

end;

end;

end;

procedure TdmDataModule.csClientSocketError(Sender: TObject;

Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;

var ErrorCode: Integer);

{Sempre que você tiver um  erro específico ao executar o cliente será apresentada uma messagedlg mostrando o erro; nesse momento você tem que verificar se o servidor está funcionando corretamente ou não, e se é necessário fazer o servidor executar adequadamente e em seguida, dizer OK.

O  csClientSocket.Open irá tentar reconectar-se ao servidor. Neste momento, se alguma transação está no meio você tem que reenviar a mesma coisa após reconectar-se}

begin

case ErrorEvent of

eeGeneral :

begin

if MessageDlg('Error Connecting to Java server! ' + #13 + 'Check the server status and try again!!', mtInformation,[mbOk],0) = mrOk then

csClientSocket.Open

end;

eeConnect :

begin

if MessageDlg('Error Connecting to Java server? ' + #13 + 'Check the server status and try again!!', mtInformation,[mbOk],0) = mrOk then

csClientSocket.Open

end;

eeSend :

begin

if MessageDlg('Error Connecting to Java server? ' + #13 + 'Check the server status and try again!!', mtInformation,[mbOk],0) = mrOk then

csClientSocket.Open

end;

eeReceive :

begin

if MessageDlg('Error Connecting to Java server? ' + #13 + 'Check the server status and try again!!', mtInformation,[mbOk],0) = mrOk then

csClientSocket.Open

end;

eeAccept :

begin

if MessageDlg('Error Connecting to Java server? ' + #13 + 'Check the server status and try again!!', mtInformation,[mbOk],0) = mrOk then

csClientSocket.Open

end;

end;

end;

procedure TdmDataModule.DataModuleDestroy(Sender: TObject);

begin

//Fechando a conexão de soquete

csClientSocket.Close;

end;

end.

Terminado o datamodule, você pode inclui-lo em unidades, onde é preciso interagir com o servidor, assim que você pode evitar escrever código para ler dados do servidor, em várias partes do projeto.
Você pode configurar o host/endereço e número da porta do servidor para se comunicar no tempo de execução (runtime parameters) através destes parâmetros. (Assumo que o pessoal do Delphi, não dá  atenção a isso)

Em seguida, o form,  formcreate event; escreva o seguinte código para se conectar ao servidor. Ex: definindo o endereço IP e o número da porta do servidor no componente Active TClientSocket e configurando Active para true.

//Conectando ao servidor Java de uma porta especifica

try

with dmDataModule.csClientSocket do

begin

if Active then Active := False;

/// Obtendo o endereço ou  Host Name do servidor através dos parâmetros  de execução (runtime parameters)

Host := ParamStr(1);

//Obtendo o numero da porta do servidor no qual o servidor atende através dos parâmetros  de execução

Port := StrToInt(ParamStr(2));

//Ativando a conexão
Active := True;

end;

except on ESocketError do

begin

MessageDlg('Unable to Connect to Java Server ' + #13 + 'Please Try Again!',mtInformation,[mbOk],0);

exit;

end;

end;


Uma vez conectado ao servidor, você pode usar um dos métodos do TclientSocket, sendtext ou sendstream, para enviar dados ao servidor.

Examplo:

procedure Send;

begin

//Checando se a conexão de soquete está pronta ou não

//Se não, a manipulação de erro  do TClientSocket deve ser ativada
if csClientSocket.Active then

begin

// Enviando o texto através da conexão de soquete
csClientSocket.Socket.SendText('The string to send');

//Colocando um sinal de aviso até que o servidor envie resposta
dmDataModule.FWaiting := True;

while dmDataModule.FWaiting then

Application.ProcessMessages;

end;

end;

Aproveite bem!!!