2013-03-12 143 views
3

我使用Indy 10 Http Client(最新的SVN版本)和SSL Handler(Delphi 7)来获取https://www.webtide.com/choose/jetty.jsp网站的内容。Indy 10 + SSL =适用于Windows 7,不适用于XP

它可以在Windows 7 x64(在两个系统上测试)上正常工作,但在WindowsXP x86上(在3个系统上测试),测试应用程序只是挂在TIdHTTP.Get()上,没有恢复的可能性一个worker-procedure/thread不起作用!)。测试应用程序无法恢复,必须使用任务管理器关闭。

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

这里是一个压缩包与源代码,编译的可执行文件,和SSL库:

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

+0

你的问题是:如果你想做到这一点,你可以通过调用建立TCP/IP连接之后,但在开始SSL握手,例如前TIdSocketHandle.SetSockOpt()方法做手工? – 2013-03-12 14:06:39

+0

为什么它在WindowsXP上崩溃/挂起? – Casady 2013-03-12 14:09:54

+0

难道你不问调试器为什么会挂起?暂停程序,调试器会告诉你它在哪里等待。你可以使用这个代码连接到任何其他网站,或者它只是这个特定的一个,让你的程序挂起? – 2013-03-12 14:17:46

回答

1

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

Indy使用其ReadTimeout属性在OpenSSL连接上分配套接字级读/写超时,但仅在Vista +上作为OpenSSL错误的解决方法。在XP和更早版本上,默认的套接字读/写超时适用。 ReadTimeout仅告诉Indy在读取数据时等待多久,但它不适用于套接字本身。

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; 
+0

雷米,我试过你的代码。在Win7上运行良好,但在WindowsXP上它仍然挂起(因为现在10分钟测试应用程序有一个沙漏图标)。备忘录2中没有“连接...”。更糟的是,当它挂起时,不能暂停应用程序并在Delphi IDE中使用调试器,因为IDE标题更改为“停止...”并挂起,直到终止应用程序! – Casady 2013-03-12 21:22:24

+0

我认为这里的问题是接收/发送超时不适用,因为它已挂起连接/握手,而不是发送/接收数据时。 – Casady 2013-03-12 21:38:28

+0

@Casady:如果你没有看到'hsConnecting'状态触发'OnStatus'事件,那么Indy并不试图将套接字连接到服务器,这与SSL无关。当连接套接字时,在交换任何数据之前,会立即触发'OnConnected'事件,所以这是设置套接字超时的最早的机会。 – 2013-03-12 22:18:01

相关问题