如何在Indy SSL中设置ConnectTimeout / ReadTimeout

使用SSL时如何在Indy中设置ConnectTimeout / ReadTimeout?

MCVE:

program mcve;

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,{$ENDIF}{$ENDIF}SysUtils,IdHTTP,IdSSLOpenSSL,DateUtils;

var
  HTTP    : TIdHTTP;
  SSL     : TIdSSLIOHandlerSocketOpenSSL;
  Started : TDateTime;
begin
  HTTP := TIdHTTP.Create();
  try
    HTTP.ReadTimeout            := 1000;
    HTTP.ConnectTimeout         := 2000;
    SSL                         := TIdSSLIOHandlerSocketOpenSSL.Create(HTTP);
    SSL.ConnectTimeout          := HTTP.ConnectTimeout;
    SSL.ReadTimeout             := HTTP.ReadTimeout;
    SSL.SSLOptions.SSLVersions  := [sslvTLSv1,sslvTLSv1_1,sslvTLSv1_2];
    HTTP.IOHandler              := SSL;
    Started := Now;
    try
      HTTP.Get(ParamStr(1));
    except
      On E: Exception do WriteLn(E.Message);
    end;
    Writeln(FormatDateTime('hh:nn:ss',SecondsBetween(Started,Now) / SecsPerDay));
  finally
    HTTP.Free;
  end;
end.

仅在使用http时,使用https的ConnectTimeout / ReadTimeout才能解决问题:

:~$ ./mcve http://x.x.x.x
Read timed out.
00:00:01 <-- Correct.

:~$ ./mcve https://x.x.x.x
Socket Error # 0

00:03:38 <-- NOT Correct / More than SSL.ReadTimeout value.

从OPM版本10.6.2.5494安装的Lazarus 2.0.6 Indy。

注意:在Windows上使用Delphi和出厂的Indy 10.6.2.5366的相同代码,结果按预期工作

abcd8031 回答:如何在Indy SSL中设置ConnectTimeout / ReadTimeout

您不需要在IOHandler本身上手动设置ConnectTimeoutReadTimeout,而仅在客户端组件(在本例中为TIdHTTP)上手动设置。 TIdTCPClient.Connect()会为您将值分配给IOHandler。

ConnectTimeout在基础套接字连接到服务器时适用,在创建任何SSL / TLS会话之前,因此无论您是否使用SSL / TLS,它的操作都相同。

当Indy尝试从IOHandler的内部连接读取字节时,将应用ReadTimeout。当不使用SSL / TLS时,这意味着它直接进入套接字,从而在没有字节到达套接字时超时。但是,当使用SSL / TLS时,Indy使用OpenSSL的旧版SSL_...() API,而不是其更新的BIO_...() API,这意味着OpenSSL代表Indy进行自己的套接字读取和缓冲,因此当OpenSSL时,Indy超时不提供任何解密的应用程序字节。

TIdSSLIOHandlerSocketOpenSSL在Windows与其他平台上的运行方式的一个差异是仅在Windows Vista +上,TIdSSLIOHandlerSocketOpenSSL确实将ReadTimeout应用于基础套接字的SO_RCVTIMEO和{{通过IOHandler的SO_SNDTIMEO方法发生1}}超时,作为Windows上OpenSSL错误的解决方法。对于其他平台,Indy当前未设置这两个套接字超时。

手动设置这些超时的好地方是IOHandler的Binding.SetSockOpt()事件,该事件在套接字连接到服务器之后以及创建任何SSL / TLS会话之前触发。

本文链接:https://www.f2er.com/3132825.html

大家都在问