首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Indy10 ConnectTimeout最小值

Indy10 ConnectTimeout最小值
EN

Stack Overflow用户
提问于 2018-11-12 20:00:33
回答 1查看 451关注 0票数 0

我有一个关于印地10的TIdTCPClientConnectTimeout的问题。

当将ConnectTimeout设置为大于125ms时,Connect()过程将阻塞当前线程125ms。如果它小于125ms,它将在给定的时间内阻塞(例如,如果超时设置为30ms,它将阻塞30ms)。在这两种情况下,连接都是稳定的,我可以发送和接收数据。

为什么TIdTCPClient会有这样的行为?

IMHO Connect()过程应该在成功建立连接后立即退出,并且只有在没有连接可以打开的情况下才阻止超时的整个持续时间。

下面是我用来监控Connect()过程持续时间的代码。

调用TimerConnectTimer的定时器设置为250ms。

我使用的是Windows7专业版下的Lazarus v1.6.4和Indy 10。

代码语言:javascript
复制
procedure TForm1.FormCreate(Sender: TObject);
begin
  timer := TEpikTimer.create(self);
  timer.Clear;
end;

procedure TForm1.TimerConnectTimer(Sender: TObject);
begin
  timer.Start;
  client := TIdTCPClient.create();
  logTime(0);
  // Tested with values between 10ms and 1000ms
  client.ConnectTimeout := SpinEdit1.Value;
  try
    logTime(1);
    // choose ip and port for a running server
    client.connect('192.168.2.51', 9912);
    logTime(2);
  except

  end;

  logTime(3);

  try
    client.Disconnect();
    FreeAndNil(client);
  except

  end;

  logTime(4);
  timer.Clear;
end;

procedure TForm1.logTime(ch: integer);
begin
  StringGrid1.Cells[0, ch] := FormatFloat('0.00', timer.Elapsed*1000);
end;
EN

回答 1

Stack Overflow用户

发布于 2018-11-13 04:39:34

当将ConnectTimeout设置为大于125ms时,Connect()过程将阻塞当前线程125ms。如果它小于125ms,它将在给定的时间内阻塞(例如,如果超时设置为30ms,它将阻塞30ms)。在这两种情况下,连接都是稳定的,我可以发送和接收数据。

为什么TIdTCPClient会有这样的行为?

如果不知道您使用的是Indy10的确切版本,就很难回答这个问题,因为这些年来ConnectTimeout的实现已经发生了变化。但是,总的来说:

如果ConnectTimeout设置为IdTimeoutDefault0,则使用IdTimeoutInfinite

如果在主UI线程中调用Connect(),则使用TIdAntiFreeze,并且使用无限超时,则使用硬编码的2分钟超时。

如果使用了超时,Connect()会产生一个工作线程来将套接字连接到服务器,然后一直等待到超时,直到线程终止。如果在线程终止之前超时,Indy将关闭套接字并终止线程。

假设您使用的是Indy10的最新版本(至少是2016年12月14日的SVN5382版或更高版本),并且没有使用TIdAntiFreeze,那么仅在Windows上,等待应在工作线程终止时立即退出,因为Indy在整个超时期间对线程上的WaitForSingleObject()进行一次调用,并在WFSO退出时立即退出。

如果您使用的是TIdAntiFreeze,或者在非Windows平台上使用Indy,或者使用的是SVN rev 5382之前的Indy10版本,等待会以固定的时间间隔(125ms或TIdAntiFreeze.IdleTimeOut,取较小者)在循环中调用IndySleep() (如果需要,还会调用TIdAntiFreeze.DoProcess()),直到超时或线程终止。在这种情况下,在Connect()退出之前可能会有一个轻微的延迟,因为每个休眠周期必须在Connect()可以检查线程是否已经终止之前完成,并且在整个连接超时内对每个休眠间隔执行此操作。

IMHO Connect()过程应该在成功建立连接后立即退出,并且只有在没有连接可以打开的情况下才阻止超时的整个持续时间。

这正是它目前所做的,至少在Windows上是这样。如果连接成功,线程将终止,Connect()会立即退出(即使使用了TIdAntiFreeze )。当前休眠周期由线程自身终止而结束。在非Windows平台上不是这种情况(目前,可能会在未来的版本中解决)。

请注意,以上所有情况仅在使用超时时适用。如果未使用超时,则也不使用辅助线程。Connect()简单地直接连接套接字,并让尝试阻塞调用线程,直到完成,无论成功与否。

下面是我用来监控Connect()过程持续时间的代码。

我建议使用更像这样的东西:

代码语言:javascript
复制
procedure TForm1.TimerConnectTimer(Sender: TObject);
begin
  try
    timer.Start;
    try
      logTime(0);

      client := TIdTCPClient.create();
      try
        // choose ip and port for a running server
        client.Host := '192.168.2.51';
        client.Post := 9912;

        // Tested with values between 10ms and 1000ms
        client.ConnectTimeout := SpinEdit1.Value;

        logTime(1);
        client.Connect();
        logTime(2);
        client.Disconnect();
        logTime(3);

      finally
        FreeAndNil(client);
      end;

      logTime(4);
    finally
      timer.Clear;
    end;
  except
  end;
end;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53261747

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档