【问题标题】:Howto determine if connection is still alive with Indy?如何确定与 Indy 的连接是否仍然存在?
【发布时间】:2009-09-11 12:16:50
【问题描述】:

我使用 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 条件的行。

这里发生了什么?如何避免尝试使用死连接进行发送?

【问题讨论】:

    标签: delphi tcp delphi-2009 indy


    【解决方案1】:

    好的,我找到了解决方案。我没有存储 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 和连接会导致应用程序停止 - 测试连接消息不会有任何区别。
      • 是否因为等待超时而冻结?
      • Indy 正在阻塞,所以这可能就是应用程序停在那里的原因。检查客户端是否还活着的最好方法是监听客户端“状态消息”。客户应定期检查。如果客户错过了许多此类检查,您可以将其视为不可用。或者您可以使用非阻塞库 (ICS),这样您的应用程序就不会阻塞 TCP 连接。并且以等待连接并不意味着应用程序没有响应的方式设计应用程序。使用非阻塞套接字或线程。
      • 我使用线程进行客户端通信,但不幸的是整个应用程序冻结了,不仅仅是通信线程。
      猜你喜欢
      • 1970-01-01
      • 2011-02-02
      • 2020-01-27
      • 2011-09-20
      • 2012-11-19
      • 2015-04-02
      • 2011-03-12
      • 1970-01-01
      • 2018-06-10
      相关资源
      最近更新 更多