我正在使用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上崩溃/挂起?
答案 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;