我有使用Indy HTTP组件(使用Windows套接字)的Delphi应用程序。在执行Indy过程时,有时会收到#10060套接字错误(WSAETIMEDOUT-尝试建立连接但未建立连接的超时):
CheckForSocketError(IdWinsock2.Connect(ASocket, @LAddr, SizeOf(LAddr)));
...
connect : TconnectProc;
...
TconnectProc = function ( const s: TSocket; const name: PSockAddr; const namelen: Integer): Integer; stdcall;
实际上,所有这些都只是包裹在Windows连接函数https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect中,该函数给出错误和消息WSAETIMEDOUT。所以-我的问题是-这可能根本就是编程错误吗?即使我的服务器在另一台计算机上运行,并且该服务器在处理请求时遇到问题,即使在这种情况下,低级连接也应正常执行,如果该服务器无法处理GET / POST请求,则当然会出现错误应该是,但是那些错误应该只在执行其他Socket函数期间出现,而不是在connect
函数中出现,不是吗?
我正在尝试解决问题https://serverfault.com/questions/973648/is-it-possible-that-unencrypted-traffic-can-cause-windows-socket-10057-10060?noredirect=1#comment1266907_973648,现在我正在寻找代码中发生的事情。
我的服务器端代码非常简单-它只是已实现的TIdHttpServer组件(我仅在此处提供事件名称):
MyForm.IdHTTPServerCommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
那么-我的实现会带来什么磨损,什么会导致WSAETIMEDOUT
出现connect
?是的,有时我的过程可能会很长,但是经过数年的努力,它成功地返回了答案,并且没有任何通信错误。而且我猜想,该连接功能甚至不能依赖(不使用/引发)OnCommandGet事件,因此,我无法控制服务器端如何处理来自客户端的套接字连接功能?
这可能与TCP(而非HTTP)保持连接有关,也许某些Windows更新减少了客户端对Windows TCP保持连接的客户端设置,现在这表现为这种错误。
答案 0 :(得分:1)
Indy TCP客户端(如TIdHTTP
)具有公共ConnectTimeout
属性,默认情况下将其设置为0(无限)。如果未指定超时,则如果在主UI线程中调用了客户端的TIdTCPClient.Connect()
方法并且TIdAntiFreeze
是活动的,则使用2分钟的硬编码超时,否则将不使用超时。
如果使用了超时,Indy将在工作线程中调用Winsock的connect()
函数,并等待该线程终止。如果Indy的超时时间过去,则关闭套接字以中止connect()
,然后将EIdConnectTimeout
引发给调用者。如果connect()
在Indy的超时时间结束之前退出,则只有connect()
失败时才会向调用者引发异常。
如果未使用超时,Indy将直接调用Winsock的connect()
,等待它自行退出,然后仅在失败时引发异常。
因此,在Indy调用Winsock的WSATIMEDOUT
函数时,您可以从Indy得到connect()
错误的唯一方法是Winsock本身在Indy自身的超时时间过去之前在内部超时。那不一定表示您的代码有问题。这只是意味着您当时尝试连接的Host
根本无法到达。如果服务器可以访问,但无法接受您的连接,则会收到其他错误,例如WSAECONNREFUSED
。
如果服务器在防火墙或路由器后面,请确保它没有阻止连接到达服务器。尝试在服务器计算机(例如WireShark)上运行数据包嗅探器,并确保来自TIdHTTP
的3向TCP握手正确到达服务器计算机。