如何使用Indy判断连接是否仍然有效?

4
我使用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条件语句所在的行。

这里发生了什么?如何避免尝试使用已失效的连接发送信息?

2个回答

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;          

这对我来说没问题。

2
如果客户端关闭连接,客户端机器/网络卡死机或您与客户端之间存在其他网络问题,您可能直到下一次尝试写入连接时才会发现这一点。您可以使用心跳检测。定期向客户端发送一条带有短超时的消息,以查看连接是否仍然有效。这样,如果出现意外断开连接,您将更早地知道。您可以将其包装在一个“CheckConnection”函数中,并在发送响应之前调用它。

问题在于访问TIdContext和连接会导致应用程序停止——测试连接消息也没有任何区别。 - jpfollenius
它是否冻结是因为它正在等待超时? - Bruce McGee
Indy正在阻塞,所以可能这就是应用程序停止的原因。检查客户端是否仍然活动的最佳方法是监听客户端的“状态消息”。客户端应该定期进行检查。如果客户端错过了太多此类检查,您可以将其视为不可用。或者您可以使用非阻塞库(ICS),这样您的应用程序就不会在TCP连接上阻塞。并且设计应用程序的方式,使等待连接并不意味着应用程序没有响应。使用非阻塞套接字或线程。 - Runner
我使用线程进行客户端通信,但不幸的是,整个应用程序都会冻结,而不仅仅是通信线程。 - jpfollenius

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接