2013-03-12 144 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

相關問題