Indy 10 + SSL =在Windows 7中有效,在XP上无效 [英] Indy 10 + SSL = works in Windows 7, does not work on XP

查看:170
本文介绍了Indy 10 + SSL =在Windows 7中有效,在XP上无效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Indy 10 Http客户端(最新的SVN版本)和SSL处理程序(Delphi 7)来获取

I'm using the Indy 10 Http Client (latest SVN build) and a SSL Handler (Delphi 7) to get the content of the https://www.webtide.com/choose/jetty.jsp website.

它在Windows 7 x64(在两个系统上测试)上工作正常,但是在WindowsXP x86(在三个系统上测试)上,测试应用程序仅挂在TIdHTTP.Get()上而没有恢复的可能性(这意味着即使在Windows 7中断开连接) worker-procedure/thread不起作用!).测试应用无法恢复,必须通过任务管理器关闭.

It works fine on Windows 7 x64 (tested on two systems), but on WindowsXP x86 (tested on 3 systems) the test app simply hangs on TIdHTTP.Get() without the possibility of a recovery (meaning even disconnecting in a worker-procedure/thread does not work!). The test app cannot be recovered and must be closed with the task manager.

SSL库(32位x86!)来自此处: http://slproweb.com/products/Win32OpenSSL.html 但我尝试了来自不同站点的其他5个版本,结果相同.

The SSL libraries (32bit x86!) are from here: http://slproweb.com/products/Win32OpenSSL.html but I've tried 5 other versions from different sites, with the same results.

这是一个zip程序包,其中包含源代码,已编译的可执行文件和SSL库:

Here is a zip package with source code, compiled executable, and the SSL libraries:

https://www.dropbox.com/s/pd5soxon0qbnnl0/IndyTest.zip

这是源代码(表单有一个按钮和两个备注):

And here is the source code (the form has a button and two memos):

 procedure TForm1.Button1Click(Sender: TObject);
 var IdHTTP1: TIdHTTP;
     sl : TStringList;
     SSL1: TIdSSLIOHandlerSocketOpenSSL;
 begin
   try
    try
      IdHTTP1 := TIdHTTP.Create(nil);
      sl := TStringList.Create;

      SSL1 := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
      SSL1.SSLOptions.Method := sslvSSLv23;

      with IdHTTP1 do
      begin
           ConnectTimeout := 10 * 1000;
           ReadTimeout := 10 * 1000;
           IOHandler := SSL1;

           Request.UserAgent := 'Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.3) Gecko/20040924 Epiphany/1.4.4 (Ubuntu)';
           Memo2.Text := 'connecting...';
           Application.ProcessMessages;
           Memo1.Text := Get('https://www.webtide.com/choose/jetty.jsp');
           Memo1.Lines.Add ('response: '+ResponseText);
           Memo2.Text := 'connected or timeout...';
      end;
    except
      On e: Exception do
           Memo2.Text := 'Exception: '+e.Message;
    end;
   finally
      IdHTTP1.Free;
      SSL1.Free;
      sl.Free;
   end;
 end;

为什么WindowsXP会使其崩溃/挂起?

Why does it crash/hang on WindowsXP?

推荐答案

Indy的ConnectTimeout属性仅在建立基础TCP/IP连接时适用于套接字API connect()函数.稍后会调用SSL_connect()来启动SSL握手,这是应用程序数据,因此不受ConnectTimeout约束.

Indy's ConnectTimeout property only applies to the socket API connect() function when establishing the underlying TCP/IP connection. SSL_connect() is called at a later time to initiate the SSL handshake, which is application data and thus is not subject to the ConnectTimeout.

Indy确实使用其ReadTimeout属性在OpenSSL连接上分配套接字级别的读/写超时,但是仅在Vista +上才可以解决OpenSSL错误.在XP和更早的版本上,将应用默认的套接字读/写超时. ReadTimeout仅告诉Indy在读取数据时要等待多长时间,但不会应用于套接字本身.如果要执行此操作,可以在建立TCP/IP连接之后但开始SSL握手之前,通过调用TIdSocketHandle.SetSockOpt()方法手动进行操作,例如:

Indy does use its ReadTimeout property to assign socket level read/write timeouts on OpenSSL connections, but only on Vista+ as a workaround for an OpenSSL bug. On XP and earlier, default socket read/write timeouts apply. The ReadTimeout only tells Indy how long to wait when reading data, but it is not applied to the socket itself. If you want to do that, you can do it manually by calling the TIdSocketHandle.SetSockOpt() method after establishing the TCP/IP connection but before beginning the SSL handshake, for example:

procedure TForm1.Button1Click(Sender: TObject);
var
  IdHTTP1: TIdHTTP;
  SSL1: TIdSSLIOHandlerSocketOpenSSL;
begin
  try
    IdHTTP1 := TIdHTTP.Create(nil);
    try
      SSL1 := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP1);
      SSL1.SSLOptions.Method := sslvSSLv23;

      with IdHTTP1 do
      begin
        ConnectTimeout := 10 * 1000;
        ReadTimeout := 10 * 1000;
        IOHandler := SSL1;

        OnConnected := IdHTTPConnected;
        OnStatus := IdHTTPStatus;

        Request.UserAgent := 'Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.3) Gecko/20040924 Epiphany/1.4.4 (Ubuntu)';

        Memo1.Text := Get('https://www.webtide.com/choose/jetty.jsp');
        Memo1.Lines.Add('response: '+ ResponseText);

        Memo2.Text := 'finished...';
      end;
    finally
      IdHTTP1.Free;
    end;
  except
    on e: Exception do
      Memo2.Text := 'Exception: ' + e.Message;
  end;
end;

procedure TForm1.IdHTTPStatus(ASender: TObject; const AStatus: TIdStatus; const AStatusText: string);
begin
  case AStatus of
    hsResolving: Memo2.Text := 'resolving...';
    hsConnecting: Memo2.Text := 'connecting...';
    hsConnected: Memo2.Text := 'connected...';
    hsDisconnecting: Memo2.Text := 'disconnecting...';
    hsDisconnected: Memo2.Text := 'disconnected...';
  end;
  Update;
end;

procedure TForm1.IdHTTPConnected(Sender: TObject);
begin
  with TIdHTTP(Sender).Socket.Binding do
  begin
    SetSockOpt(Id_SOL_SOCKET, Id_SO_RCVTIMEO, 10 * 1000);
    SetSockOpt(Id_SOL_SOCKET, Id_SO_SNDTIMEO, 10 * 1000);
  end;
end;

这篇关于Indy 10 + SSL =在Windows 7中有效,在XP上无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆