Sockets Indy TIdTCPClient连接超时不工作

Sockets Indy TIdTCPClient连接超时不工作,sockets,delphi,tcpclient,indy,connection-timeout,Sockets,Delphi,Tcpclient,Indy,Connection Timeout,我有一个TIdTCPClient正在尝试连接到一个不在线的主机 更新: 在深入了解WINSOCK2之后,这似乎确实是一个问题,这取决于您的操作系统。也许在未来的版本中会有一个补丁。 (详见本问题的评论) 设置: procedure TForm1.btn1Click(Sender: TObject); begin try Self.mmo1.Lines.Add(TimeToStr(now)); Self.idtcpclnt1.Host := '192.148.89.112';

我有一个TIdTCPClient正在尝试连接到一个不在线的主机

更新:
在深入了解WINSOCK2之后,这似乎确实是一个问题,这取决于您的操作系统。也许在未来的版本中会有一个补丁。 (详见本问题的评论)

设置:

procedure TForm1.btn1Click(Sender: TObject);
begin
  try
    Self.mmo1.Lines.Add(TimeToStr(now));
    Self.idtcpclnt1.Host := '192.148.89.112';
    Self.idtcpclnt1.Port := 9200;
    Self.idtcpclnt1.Connect;
  except on E: Exception do
    Self.mmo1.Lines.Add(TimeToStr(now)+ ' : '+E.Message);
  end;
end;

procedure TForm1.idtcpclnt1Status(ASender: TObject; const AStatus: TIdStatus;
    const AStatusText: string);
begin
  Self.mmo1.Lines.Add(TimeToStr(now)+ ' : ' +AStatusText);
end;
  • 德尔福10西雅图
  • Windows 7 64位
  • 印第10.6.2.5311号
ConnectTimeout设置为5000毫秒,因此我希望在5秒后至少获得一个ConnectTimeout。但是,在我当前的机器上,接收超时需要超过20秒

到目前为止,我看到ConnectionTimeout处理正确,但在TIdIOHandlerStack.ConnectClient上,执行实际连接尝试的线程上有一个WaitFor。 我认为这是造成延迟连接超时的原因,但我不知道我能做些什么。有什么想法吗

代码:

procedure TForm1.btn1Click(Sender: TObject);
begin
  try
    Self.mmo1.Lines.Add(TimeToStr(now));
    Self.idtcpclnt1.Host := '192.148.89.112';
    Self.idtcpclnt1.Port := 9200;
    Self.idtcpclnt1.Connect;
  except on E: Exception do
    Self.mmo1.Lines.Add(TimeToStr(now)+ ' : '+E.Message);
  end;
end;

procedure TForm1.idtcpclnt1Status(ASender: TObject; const AStatus: TIdStatus;
    const AStatusText: string);
begin
  Self.mmo1.Lines.Add(TimeToStr(now)+ ' : ' +AStatusText);
end;
此代码的结果:


如果连接线程没有及时终止,则可能意味着对
Close()
的上一次调用没有导致套接字API
connect()
立即中止。虽然这并不能保证在所有平台上都能实现,但我从未见过这种情况在Windows上发生。当
connect()
上的另一个线程被阻塞时,关闭一个线程中的套接字会立即导致错误。请进一步诊断以确定真正的问题是
connect()
未中止还是线程等待未唤醒。这是两个完全不同的问题。感谢您的快速响应,我不确定我是否正确理解您的意思,但我的印象是,在调用
Close
后,
LThread.WaitFor
需要超过10秒才能完成。我说的是
TIdIOHandlerStack
中的第282行:
TIdIOHandlerStack.ConnectClient.DoConnectTimeout
在我看来,WinSock2在我的机器上有大约20秒的最小阻塞时间。这导致连接线程等待其FBinding.connect调用完成。我能看到的最后一件事是调用
CheckForSocketError(IdWinsock2.connect(ASocket,IdWinsock2.PSOCKADDR(@LAddr),LSize))在TIdStackWindows中,无论有人想对连接线程执行什么操作,它都会阻塞这奇怪的20秒。
Close()
调用Winsock
shutdown()
closesocket()
函数,这将中止任何正在进行的阻塞Winsock函数。我发现很难相信Winsock的
connect()
函数会在关闭套接字后持续阻塞20秒,但我认为这是可能的。关闭套接字是中止阻塞套接字调用的唯一方法,这就是Indy使用工作线程进行连接的原因。也就是说,我有一些新代码在Windows上以非阻塞模式运行
connect()
,因此没有使用线程,超时得到了更好的尊重,但我对该版本没有ETA。深入挖掘后,我不得不同意。然而,我有多个运行Windows 7的客户端存在此“问题”,甚至Windows Server 2012也受到同样的影响。