我的应用程序挂在对程序TIdStackWindows.Connect
的调用中。当TCP / IP地址存在时没有问题,但如果没有,我就会挂起。 IP地址是文字的 - 不涉及DNS查找。我期待连接尝试在超时后失败(TCPClient.ConnectTimeout
)我设置为1秒,但应用程序在此调用时挂起最多30秒(来自我的应用程序的调用没有线程。我打算将TCP连接移动到一个线程,但长连接超时仍然是一个问题。
如果我在应用程序没有响应时在Delphi IDE中暂停执行,我的定位是:
ntdll.KiUserApcDispatcher:
7C90E450 8D7C2410 lea edi,[esp+$10]
然后我F8几次,直到我看到一个堆栈帧。我当时在:
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的最新版本,那么会涉及到很多迁移吗?
答案 0 :(得分:4)
阻止套接字在API层没有连接超时的概念,因此Indy的ConnectTimeout
是手动实现的超时。 Indy在内部工作线程中调用TIdStack.Connect()
,而TIdTCPClient.Connect()
运行等待该线程终止的睡眠循环。如果循环检测到ConnectTimeout
句点已经过去,它会关闭套接字,这应该会导致阻塞的TIdStack.Connect()
立即退出,但这不是保证。在创建和终止线程时也存在操作系统开销。绝对不应该花费30秒来响应1秒的超时,但另一方面1秒通常太小。线程可能甚至不会在1秒内开始运行。您通常应该将ConnectTimeout
设置为至少5-10秒,以便为操作系统提供足够的时间来完成其工作。