有时,IdTcpServer不会在Disconnect事件中检索信息 [英] IdTcpServer some times don't retrieve the informations at Disconnect event
问题描述
我不知道为什么,但是有时在日志中发生断开连接事件时,他不检索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屋!