delphi - 如果另一端没有从套接字读取数据,如何避免在 Indy 中写入套接字时卡住

标签 delphi indy winsock2

我有一个使用 Indy 的客户端和服务器套接字应用程序,用 Delphi 10.2 编译。

应用程序有一个工作线程,用于处理来自不同端口的请求,并使用如下调用在同一线程内写入响应:

procedure TMyCommManager.WriteResponse(AHandler: TIdIOHandler; SomeData: SomeType);
var 
  idBytes: TidBytes;
  PacketSize: Integer;
begin
  SomeData.GetBytes(idBytes, PacketSize);
  AHandler.Write(DataBuffer, PacketSize);
end;

几乎所有时间一切都按预期工作,但我们注意到工作线程在生产中不时卡住。经过各种迭代后,我们最终发现所有这些都发生在对 TidIOHandler.Write() 的调用中,我很确定它正在发生,因为单个端口的另一端是不读取套接字的响应。

从另一端重置端口后,工作线程解冻并继续按预期工作。

我找到了this answer来自 Remy Lebeau 的问题 Delphi (Indy) Server Freezing on Write ,他在评论中提到(强调我的):

Indy uses blocking sockets, so if the client is not reading inbound data on its end, eventually the socket's internal send buffer will fill up and the socket will become blocked on the server side waiting for the client to empty the buffer. The only way to avoid a deadlock in that scenario would be to set a socket-level send timeout using the socket API directly. Indy does not implement send timeouts in its logic.

我正在寻找设置超时的正确方法,通过 INDY 或通过 Windows 中的直接 API 调用,但我陷入困境,所以我来这里寻求帮助。

如果这是不可能的,我可以在辅助线程上实现超时机制,但我不确定重置我这边辅助线程的连接以让工作线程继续工作。

最佳答案

I'm looking for the correct way to set that timeout, via INDY or via a direct API call in Windows

在我的previous comment ,当我说“直接使用套接字 API 设置套接字级发送超时”时,我指的是通过 setsockopt()SO_SNDTIMEO 套接字选项。功能。

对于Indy来说,可以通过TIdSocketHandle.SetSockOpt()方法来调用setsockopt(),例如:

// Windows

SomeConnection.Socket.Binding.SetSockOpt(Id_SOL_SOCKET, Id_SO_SNDTIMEO, TimeoutInMS);

// 'Nix

var tv: timeval;
...
SomeConnection.Socket.Binding.SetSockOpt(Id_SOL_SOCKET, Id_SO_SNDTIMEO, Integer(@timeval));

or:

GBSDStack.SetSocketOption(SomeConnection.Socket.Binding.Handle, Id_SOL_SOCKET, Id_SO_SNDTIMEO, timeval, sizeof(timeval));

(TIdTCPConnection.Socket 属性是当为 TIdTCPConnection.IOHandler 分配了 TIdIOHandlerSocket< 时访问 TIdIOHandlerSocket 的简写 或后代)。

只要知道,如果确实发生超时,您就无法确切知道哪些数据实际传输到了对等方,因此在大多数协议(protocol)中恢复通常是不可能的。您真正能做的就是关闭连接并重新连接。

关于delphi - 如果另一端没有从套接字读取数据,如何避免在 Indy 中写入套接字时卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56124201/

相关文章:

delphi - 如何使用位/位运算符来控制对象状态?

delphi - 为什么我们不能在 Delphi 7 中执行 PChar ('*' ) ?

string - 为什么使用 const 字符串参数时程序会崩溃?

c++ - 如何在 LSP 中找出确切的 URL?

c++ - 在 C++ 中使用套接字进行文件传输

C++ WinSock 2 - 使用 getpeername() 函数时套接字崩溃

delphi - 如何在其他程序中访问和读取 Label 的标题

ssl - 获取 "EIdHTTPProtocolException with message ' HTTP/1.1 400 BAD REQUEST'”异常

indy - 如何处理 Indy TIdTCPClient 超出 MaxLineLength 的情况

delphi - Indy SSL 到普通套接字泵