Categorias
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!!!