如何确定与 Indy 的连接是否仍然有效?

发布于 2024-08-04 16:05:16 字数 739 浏览 2 评论 0原文

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

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

I use Indy for TCP communication (D2009, Indy 10).

After evaluating a client request, I want to send the answer to the client. I therefore store the TIdContext, like this (pseudocode)

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;

But what if the client terminates the connection somewhere between the request and the answer being ready for sending? How can I check if the context is still valid? I tried

if Assigned (Context) and Assigned (Context.Connection) and Context.Connection.Connected then
  Context.Connection.IOHandler.Write ('Response');

but it does not help. In some cases the program just hangs and if I pause execution I can see that the current line is the one with the if conditions.

What happens here? How can I avoid trying to send using dead connections?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夏日浅笑〃 2024-08-11 16:05:16

好吧,我找到了解决方案。我没有存储 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;          

这对我有用。

Okay, I found a solution. Instead of storing the TIdContext I use the context list provided by 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;          

That works for me.

江心雾 2024-08-11 16:05:16

如果客户端关闭连接、客户端计算机/网卡死机或者您和客户端之间存在其他网络问题,您可能直到下次尝试写入连接时才知道。

你可以使用心跳。偶尔会向客户端发送一条带有较短超时时间的消息,以查看连接是否仍然有效。这样,您就能更快地知道是否出现意外断开连接。您可以将其包装在“CheckConnection”函数中并在发送响应之前调用它。

If the client closes the connection, the client machine/network card dies or you have some other network problem between you and the client, you might not know about it until the next time you try to write to the connection.

You could use a heartbeat. Occasionally send a message to the client with a short timeout to see if the connection is still valid. This way, you'll know sooner if there has been an unexpected disconnect. You could wrap it in a "CheckConnection" function and call it before sending your response.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文