Un saludo a todos/as,
Estoy desarrollando un software que está permanentemente leyendo los datos que le llegan desde un ST (servidor de terminales) y luego mediante DataSnap lo distribuye a otros clientes. La conexión es muy simple, ya que no deja de ser una conexión TCP / IP , y para la lectura de datos uso una TReadingThread. El programa realiza su función perfectamente, ya que se conecta, lee, y replica los datos que le llegan del ST. Mi problema viene cuando esa conexión se pierde por algún motivo, ya que entonces el Cliente TCP es incapaz de reconectar con el Servidor de Terminales.
A continuación os dejo el código. No entiendo por qué no consigue volver a conectar, sin embargo, cuando haces click en cerrar el formulario , si vuelve a conectar con el ST... y sinceramente no doy con la tecla.
Muchas gracias por vuestro tiempo.
Un saludo.
unit Unit2; interface uses System.Classes,IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdGlobal, IdContext,System.SyncObjs,SysUtils; type TDataEvent = procedure(const Data: string) of object; TReadingThread = class(TThread) private { Private declarations } FClient: TIdTCPClient; FData: string; FOnData: TDataEvent; FTermEvent : TEvent; procedure DataReceived; protected procedure Execute; override; public constructor Create(AClient: TIdTCPClient); reintroduce; property OnData: TDataEvent read FOnData write FOnData; end; function ByteToBin(aByte : Byte) : string; var Datos: string; cont : integer; implementation uses Unit1, ServerContainerUnit1, ServerMethodsUnit1; function ByteToBin(aByte : Byte): string; Const c10: Array[Boolean] of Char = ('0', '1'); Var eLoop1: Byte; begin SetLength(Result, 8); For eLoop1 := 7 downto 0 do Result[8-eLoop1] := c10[(aByte and (1 shl eloop1)) <> 0]; end; { TReadingThread } constructor TReadingThread.Create(AClient: TIdTCPClient); begin inherited Create(True); FClient := AClient; FtermEvent := TEvent.Create(nil, true, false, ''); end; procedure TReadingThread.Execute(); var Buffer : TIdBytes; s: string; bin : string; begin { Place thread code here } while not Terminated do begin //vamos a estar testeando la conectividad con el ST. En caso de perder conectividad, reconectamos try if not ClientForm.IdTCPClient1.Connected then begin ClientForm.IdTCPClient1.Connect; end; ClientForm.Memo1.Lines.Add('Conectado ' + DateTimeToStr(Now)); except //ClientForm.IdTCPClient1.Disconnect; //esperamos 5 segundos para intertar reconectar ClientForm.Memo1.Lines.Add('Intentando conectar... ' + DateTimeToStr(Now)); FtermEvent.WaitFor(10000); continue; end; //conectado... try while not Terminated do begin ClientForm.IdTCPClient1.IOHandler.ReadBytes(Buffer,1,False); Assert(Length(Buffer)=1); bin := ByteToBin(Buffer[0]); //Fdata := BytesToString(Buffer,0,1); FData := bin; if (FData <> '') and Assigned(FOnData) then Synchronize(DataReceived); end; except //ha ocurrido algo inesperado, entonces reconectará end; end; end; procedure TReadingThread.DataReceived; begin if Assigned(FOnData) then FOnData(FData); end; end.
procedure TClientForm.FormShow(Sender: TObject); var Ini: TiniFile; Host : string; Puerto : Integer; begin Ini := TIniFile.Create(ChangeFileExt(Application.ExeName, '.INI')); ServerContainer1.DSServer1.Start; //iniciamos el servidor DataSnap //conectamos al ST leyendo los datos del fichero .INI // IdTCPClient1.Host := 'IP'; //Ip del ST // IdTCPClient1.Port := 10001; IdTCPClient1.Host := ini.ReadString('CONFIGURACION', 'IP',Host ); IdTCPClient1.Port := ini.ReadInteger('CONFIGURACION','PUERTO',Puerto); //IdTCPClient1.Connect; try Thread := TReadingThread.Create(IdTCPClient1); Thread.OnData := ClientForm.DatosRecibidos; Thread.Resume; except IdTCPClient1.Disconnect; raise; end; end;
procedure TClientForm.FormClose(Sender: TObject; var Action: TCloseAction); begin IdTCPClient1.Disconnect; //desconectamos del ST ServerContainer1.DSServer1.Stop; //detenemos el servidor if Assigned(Thread) then Thread.Terminate; try IdTCPClient1.Disconnect; finally if Assigned(Thread) then begin Thread.WaitFor; FreeAndNil(Thread); end; end; application.Terminate; end;