Sunday, 14 December 2008

Creando una pequeña herramienta de xat con Indy 10 y Delphi 2009

Después de unos días sin postear nada, vengo un un pequeño programa que hice hace un par de días, con el que mediante los componentes de Indy 10 (idTCPClient y idTCPServer) creo una comunicación bidireccional mediante una dirección IP y un puerto.

La aplicación tiene el siguiente aspecto:



El código fuente para hacer funcionar los 2 componentes enviando un String, es el siguiente:



procedure TForm1.Button1Click(Sender: TObject);
var
Bindings: TIdSocketHandles;
begin
Bindings := TIdSocketHandles.Create(IdTCPServer1);
try
with Bindings.Add do
begin
IP := DefaultServerIP.text;
Port := StrToInt(DefaultServerPort.text);
end;
try
IdTCPServer1.Bindings := Bindings;
IdTCPServer1.Active := True;
Log('Server Iniciado en ' + DefaultServerIP.text);
Log('Esperando comunicación cliente...');
except on E: Exception do
ShowMessage(E.Message);
end;
finally
Bindings.Free;
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
IdTCPClient1.Host := IPRemota.text;
IdTCPClient1.Port := StrToInt(PuertoRemoto.text);
try
IdTCPClient1.Connect;
except
raise exception.Create('Error');
end;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
try
if IdTCPClient1.Connected then
IdTCPClient1.Disconnect;
except
on E: Exception do
//nothing
end;
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
timer.enabled := true;
end;

procedure TForm1.Edit2KeyPress(Sender: TObject; var Key: Char);
begin
if key = chr(13) then
Button4Click(Sender);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Button3Click(sender);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
HostName, IPAddr, Err: string;
begin
Memo1.Clear;
Richedit1.Clear;
GetIPFromHost(HostName, IPAddr, Err);
DefaultServerIP.text := IPAddr;
end;

procedure TForm1.IdTCPClient1Connected(Sender: TObject);
begin
Log('Conectado al Servidor ' + DefaultServerIP.text + ':' + DefaultServerPort.text);
end;

procedure TForm1.IdTCPClient1Disconnected(Sender: TObject);
begin
Log('Desconectado del Servidor' + DefaultServerIP.text + ':' + DefaultServerPort.text);
end;

procedure TForm1.Log(s: string);
begin
Memo1.Lines.Add(DateTimeToStr(now) + ' ' + s);
end;

procedure TForm1.TimerTimer(Sender: TObject);
var
sCommand: string;
size : integer;
begin
if not IdTCPClient1.Connected then
Exit;

IdTCPClient1.Socket.WriteLn('PuedoEnviar?');
Log('Enviando petición al servidor');
sCommand := IdTCPClient1.IOHandler.ReadLn;
if sCommand = 'Enviame' then
begin
IdTCPClient1.IOHandler.WriteBufferOpen;
size := Length(Edit2.text) * SizeOf(Char);
IdTCPClient1.IOHandler.Write(Integer(Length(Edit2.text)));
IdTCPClient1.IOHandler.Write(Edit2.text);
IdTCPClient1.IOHandler.WriteBufferClose;
IdTCPClient1.IOHandler.ReadLn;
RIchEdit1.SelStart := RIchEdit1.GetTextLen;
RIchEdit1.SelText := DateTimeToStr(now) + ' - ' + Edit2.text + #13#10;
RichEdit1.SelStart := RichEdit1.Perform(EM_LINEINDEX, richedit1.Lines.Count -1, 0);
Log('Tamaño paquete enviado ' + Inttostr(size) + ' bytes');
end;
timer.enabled := false;
end;

procedure TForm1.IdTCPServer1Connect(AContext: TIdContext);
begin
Log('Connectado a : ' + AContext.Binding.PeerIP + ':' + IntToStr(AContext.Binding.Port));
end;

procedure TForm1.IdTCPServer1Disconnect(AContext: TIdContext);
begin
Log('Desconectado de : ' + AContext.Binding.PeerIP + ':' + IntToStr(AContext.Binding.Port));
end;

procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var
Command: string;
Size: integer;
textoRecibido: string;
begin
if AContext.Connection.Connected then
begin
Command := '';
Command := AContext.Connection.Socket.ReadLn;
if Command = 'PuedoEnviar?' then
begin
AContext.Connection.IOHandler.WriteLn('Enviame');
Size := AContext.Connection.IOHandler.ReadLongInt(true);
textoRecibido := AContext.Connection.IOHandler.ReadString(Size);
AContext.Connection.IOHandler.WriteLn('Enviado');
Log('Tamaño paquete recibido ' + Inttostr(2*size) + ' bytes');
RIchEdit1.SelStart := RIchEdit1.GetTextLen;
RIchEdit1.SelAttributes.Style := [fsBold];
RIchEdit1.SelAttributes.Color := clRed;
RIchEdit1.SelText := DateTimeToStr(now) + ' - ' + textoRecibido + #13#10;
RichEdit1.SelStart := RichEdit1.Perform(EM_LINEINDEX, richedit1.Lines.Count -1, 0);
end;
end;
end;

procedure TForm1.IdTCPServer1Status(ASender: TObject; const AStatus: TIdStatus;
const AStatusText: string);
begin
Memo1.Lines.Add('Status : ' + AStatusText);
end;



Podeis encontrar el ejemplo de la aplicación aquí.
El resultado és el siguiente:



Hay que configurar en las secciones de conexión las IP: puerto del ordenador con el que queremos conectarnos. De momento esta versión és bidireccionar y no permite múltiples conexiones, pero bueno, y a la mejoraré.

0 comments:

Post a Comment