关于tcpclient:Delphi / Indy。 过程TIdStackWindows.Connect的长时间延迟

Delphi/Indy. Long delay in procedure TIdStackWindows.Connect

我的应用程序挂在对过程TIdStackWindows.Connect的调用中。当TCP / IP地址存在时,就没有问题,但是如果没有,我就会死机。 IP地址是字面意义-不涉及DNS查找。我期望连接尝试在超时(TCPClient.ConnectTimeout)后失败,设置为1秒,但是此调用在该调用上挂起了30秒(我的应用程序的调用未线程化。我打算移动TCP连接到线程,但是长连接超时仍然是一个问题)。

如果我在应用程序无响应时暂停在Delphi IDE中执行,我的位置是:

1
2
ntdll.KiUserApcDispatcher:
7C90E450 8D7C2410         lea edi,[esp+$10]

然后我几次F8,直到看到堆栈框架。我当时在:

1
2
3
4
5
6
7
8
9
10
11
12
IdStack.TIdStack.RaiseSocketError(10038)
IdStack.TIdStack.RaiseLastSocketError
IdStack.TIdStack.CheckForSocketError(-1)
IdStackWindows.TIdStackWindows.Connect(912,'10.8.2.170',5001,Id_IPv4)
IdSocketHandle.TIdSocketHandle.Connect
IdIOHandlerStack.TIdConnectThread.Execute
:00451fc1 HookedTThreadExecute + $2D
Classes.ThreadProc($254B910)
System.ThreadWrapper($5456CB0)
:00451ea3 CallThreadProcSafe + $F
:00451f10 ThreadExceptFrame + $3C
:7c80b729 ; C:\\WINDOWS\\system32\\kernel32.dll

经过一番摸索后,我注意到该主题获得了一些访问量。常见的答案似乎是"将其放入线程"。我打算这样做,但是长时间超时仍然会带来问题。为什么连接超时不起作用?我正在使用Indy 10.5.5和Delphi 2006-如果我升级到最新版本的Indy,会涉及很多迁移吗?


阻塞套接字在API层没有连接超时的概念,因此Indy的ConnectTimeout是手动实现的超时。 Indy在内部工作线程中调用TIdStack.Connect(),而TIdTCPClient.Connect()运行一个睡眠循环,等待该线程终止。 如果循环检测到ConnectTimeout周期已过,则会关闭套接字,这可能会导致阻塞的TIdStack.Connect()立即退出,但这不能保证。 创建和终止线程也有OS开销。 绝对不应该花30秒来响应1秒钟的超时,但是另一方面,1秒钟通常太小。 该线程甚至有可能在一秒钟之内开始运行。 通常,您应该至少将ConnectTimeout设置为5-10秒,以使OS有足够的时间来完成其工作。