3

https://www.webtide.com/choose/jetty.jsp Web サイトのコンテンツを取得するために、Indy 10 HTTP クライアント (最新の SVN ビルド) と SSL ハンドラー (Delphi 7) を使用しています。

Windows 7 x64 (2 つのシステムでテスト済み) では問題なく動作しますが、WindowsXP x86 (3 つのシステムでテスト済み) では、テスト アプリは TIdHTTP.Get() でハングするだけで、回復の可能性はありません (つまり、ワーカー プロシージャで切断することさえあります)。 /thread は機能しません!)。テスト アプリは復元できないため、タスク マネージャーで閉じる必要があります。

SSL ライブラリ (32 ビット x86!) はhttp://slproweb.com/products/Win32OpenSSL.html にありますが、別のサイトから 5 つの他のバージョンを試しましたが、同じ結果でした。

ソース コード、コンパイル済みの実行可能ファイル、および SSL ライブラリを含む zip パッケージを次に示します。

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

ソース コードは次のとおりです (フォームにはボタンと 2 つのメモがあります)。

 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 でクラッシュ/ハングアップするのはなぜですか?

4

1 に答える 1

1

Indy のプロパティは、基礎となる TCP/IP 接続を確立するときに ConnectTimeoutソケット API 関数にのみ適用されます。は後で呼び出されて SSL ハンドシェイクを開始します。これはアプリケーション データであるため、.connect()SSL_connect()ConnectTimeout

Indy はそのReadTimeoutプロパティを使用して、OpenSSL 接続でソケット レベルの読み取り/書き込みタイムアウトを割り当てますが、OpenSSL バグの回避策として Vista+ でのみです。XP 以前では、デフォルトのソケット読み取り/書き込みタイムアウトが適用されます。はReadTimeout、データの読み取り時に Indy に待機する時間を通知するだけですが、ソケット自体には適用されません。TIdSocketHandle.SetSockOpt()これを行う場合は、TCP/IP 接続を確立した後、SSL ハンドシェイクを開始する前にメソッドを呼び出すことにより、手動で行うことができます。次に例を示します。

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;
于 2013-03-12T21:02:32.380 に答える