有时,IdTcpServer不会在Disconnect事件中检索信息 [英] IdTcpServer some times don't retrieve the informations at Disconnect event

查看:59
本文介绍了有时,IdTcpServer不会在Disconnect事件中检索信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不知道为什么,但是有时在日志中发生断开连接事件时,他不检索ip和主机名,也许是因为在检索信息之前已经断开连接了吗?如果是的话,如何解决?

I don't know why but sometimes when disconnect event on log he don't retrieve the ip and hostname, maybe because already disconnected before retrieve the informations? and if yes how solve it?

procedure TForm1.IdTCPServer1Connect(AContext: TIdContext);
var
  DadosConexao : TClient;
begin
  DadosConexao := TClient(AContext);

  DadosConexao.PeerIP      := AContext.Connection.Socket.Binding.PeerIP;
  DadosConexao.HostName    := GStack.HostByAddress(DadosConexao.PeerIP);
  DadosConexao.Connected   := Now;
  DadosConexao.LastAction  := DadosConexao.Connected;

  TThread.Queue(nil,
  procedure
  begin
    Memo2.Lines.Add(Format('[%s][%s] connect', [TimeToStr(Now), DadosConexao.PeerIP, DadosConexao.HostName]));
  end);

  RefreshListBox;
end;

procedure TForm1.IdTCPServer1Disconnect(AContext: TIdContext);
var
  DadosConexao : TClient;
begin
  DadosConexao := TClient(AContext);

  TThread.Queue(nil,
  procedure
  begin
    Memo2.Lines.Add(Format('[%s][%s] disconnect', [TimeToStr(Now), DadosConexao.PeerIP, DadosConexao.HostName]));
  end);

  RefreshListBox;
end;

示例,在这里获取信息:

example, here it get the informations:

[17:12:38] [192.168.15.3]连接

[17:12:38][192.168.15.3] connect

[17:12:38] [192.168.15.3]断开连接

[17:12:38][192.168.15.3] disconnect

这里没有:

[17:12:38] [192.168.15.3]连接

[17:12:38][192.168.15.3] connect

[17:12:38] []断开

[17:12:38][] disconnect

推荐答案

TThread.Queue()是异步的,它不会阻塞调用线程.它将指定的方法/过程排队,然后立即退出.主UI线程检查队列中是否有方法/过程以使其尽早运行.因此, TIdContext 对象很可能在匿名过程实际在主UI线程中运行之前被破坏了.

TThread.Queue() is asynchronous, it does not block the calling thread. It queues the specified method/procedure and then exits immediately. The main UI thread checks the queue for methods/procedures to run at its earliest convenience. So the TIdContext object is likely being destroyed before your the anonymous procedure actually runs in the main UI thread.

您需要更改日志记录代码,以使匿名过程捕获单个字符串值,而不是捕获 TClient 对象本身,例如:

You need to change your logging code to have the anonymous procedure capture the individual string values rather than capturing the TClient object itself, eg:

procedure TForm1.IdTCPServer1Connect(AContext: TIdContext);
var
  DadosConexao : TClient;
  PeerIP, HostName: string;
begin
  DadosConexao := TClient(AContext);

  DadosConexao.PeerIP := AContext.Connection.Socket.Binding.PeerIP;
  DadosConexao.HostName := GStack.HostByAddress(DadosConexao.PeerIP);
  DadosConexao.Connected := Now;
  DadosConexao.LastAction := DadosConexao.Connected;

  PeerIP := DadosConexao.PeerIP;
  HostName := DadosConexao.HostName;

  TThread.Queue(nil,
    procedure
    begin
      Memo2.Lines.Add(Format('[%s][%s][%s] connect', [TimeToStr(Now), PeerIP, HostName]));
    end
  );

  RefreshListBox;
end;

procedure TForm1.IdTCPServer1Disconnect(AContext: TIdContext);
var
  DadosConexao : TClient;
  PeerIP, HostName: string;
begin
  DadosConexao := TClient(AContext);

  PeerIP := DadosConexao.PeerIP;
  HostName := DadosConexao.HostName;

  TThread.Queue(nil,
    procedure
    begin
      Memo2.Lines.Add(Format('[%s][%s][%s] disconnect', [TimeToStr(Now), PeerIP, HostName]));
    end
  );

  RefreshListBox;
end;

然后可以通过将日志记录代码包装到其自己的过程中来进一步采取行动:

Which can then be taken a step further by wrapping the logging code into its own procedure:

procedure TForm1.ClientStateUpdated(Client: TClient; Connected: Boolean);
var
  PeerIP, HostName: string;
begin
  PeerIP := Client.PeerIP;
  HostName := Client.HostName;

  TThread.Queue(nil,
    procedure
    begin
      Memo2.Lines.Add(Format('[%s][%s][%s] %s', [TimeToStr(Now), PeerIP, HostName, iif(Connected, 'connect', 'disconnect')]));
    end
  );

  RefreshListBox;
end;

procedure TForm1.IdTCPServer1Connect(AContext: TIdContext);
var
  DadosConexao : TClient;
  PeerIP, HostName: string;
begin
  DadosConexao := TClient(AContext);

  DadosConexao.PeerIP := AContext.Connection.Socket.Binding.PeerIP;
  DadosConexao.HostName := GStack.HostByAddress(DadosConexao.PeerIP);
  DadosConexao.Connected := Now;
  DadosConexao.LastAction := DadosConexao.Connected;

  ClientStateUpdated(DadosConexao, true);
end;

procedure TForm1.IdTCPServer1Disconnect(AContext: TIdContext);
begin
  ClientStateUpdated(TClient(AContext), false);
end;

这篇关于有时,IdTcpServer不会在Disconnect事件中检索信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆