我使用Indy进行TCP通信(D2009,Indy 10)。
在评估客户端请求后,我想将答案发送给客户端。因此,我存储TIdContext,就像这样(伪代码)
procedure ConnectionManager.OnIncomingRequest (Context : TIdContext);
begin
Task := TTask.Create;
Task.Context := Context;
ThreadPool.AddTask (Task);
end;
procedure ThreadPool.Execute (Task : TTask);
begin
// Perform some computation
Context.Connection.IOHandler.Write ('Response');
end;
但是,如果客户端在请求和准备发送的答案之间的某处终止连接,该怎么办?如何检查上下文是否仍然有效?我试过了
if Assigned (Context) and Assigned (Context.Connection) and Context.Connection.Connected then
Context.Connection.IOHandler.Write ('Response');
但它没有帮助。在某些情况下,程序只是挂起,如果我暂停执行,我可以看到当前行是if条件的行。
这里发生了什么?如何避免尝试使用死连接发送?
答案 0 :(得分:5)
好的,我找到了解决方案。我没有存储TIdContext,而是使用TIdTcpServer提供的上下文列表:
procedure ThreadPool.Execute (Task : TTask);
var
ContextList : TList;
Context : TIdContext;
FoundContext : Boolean;
begin
// Perform some computation
FoundContext := False;
ContextList := FIdTCPServer.Contexts.LockList;
try
for I := 0 to ContextList.Count-1 do
begin
Context := TObject (ContextList [I]) as TIdContext;
if (Context.Connection.Socket.Binding.PeerIP = Task.ClientInfo.IP) and
(Context.Connection.Socket.Binding.PeerPort = Task.ClientInfo.Port) then
begin
FoundContext := True;
Break;
end;
end;
finally
FIdTCPServer.Contexts.UnlockList;
end;
if not FoundContext then
Exit;
// Context is a valid connection, send the answer
end;
这适合我。
答案 1 :(得分:2)
如果客户端关闭连接,客户端计算机/网卡出现故障,或者您和客户端之间存在其他网络问题,则在下次尝试写入连接时可能不会知道它。
您可以使用心跳。偶尔会通过短暂超时向客户端发送消息,以查看连接是否仍然有效。通过这种方式,您可以更快地知道是否存在意外断开连接。您可以将其包装在“CheckConnection”函数中并在发送响应之前调用它。