Indy 10 + SSL =适用于Windows 7,不适用于XP

时间:2013-03-12 13:49:44

标签: delphi openssl jetty indy indy10

我正在使用Indy 10 Http客户端(最新的SVN版本)和SSL处理程序(Delphi 7)来获取https://www.webtide.com/choose/jetty.jsp网站的内容。

它在Windows 7 x64上运行良好(在两个系统上测试),但在WindowsXP x86(在3个系统上测试)上,测试应用程序只挂在TIdHTTP.Get()上而没有恢复的可能性(意味着甚至在worker-procedure / thread不起作用!)。测试应用程序无法恢复,必须使用任务管理器关闭。

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

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

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

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

 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上崩溃/挂起?

1 个答案:

答案 0 :(得分:1)

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

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

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;