我不知道为什么,但是有时在日志中发生断开连接事件时,他不检索ip和主机名,也许是因为在检索信息之前已经断开连接了吗?如果是的话,如何解决?
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;
示例,在这里获取信息:
[17:12:38] [192.168.15.3]连接
[17:12:38] [192.168.15.3]断开连接
这里没有:
[17:12:38] [192.168.15.3]连接
[17:12:38] []断开
答案 0 :(得分:1)
TThread.Queue()
是异步的,它不会阻塞调用线程。它将指定的方法/过程排队,然后立即退出。 UI主线程检查队列中是否有方法/过程,以便尽早运行。因此,TIdContext
对象很可能在匿名过程实际在主UI线程中运行之前就被销毁了。
您需要更改日志记录代码,以使匿名过程捕获单个字符串值,而不是捕获TClient
对象本身,例如:
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;
然后可以通过将日志记录代码包装到其自己的过程中来进一步采取行动:
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;