Delphi 发送 HTTP GET 请求而不等待服务器响应
Delphi send HTTP GET request without wait for the server response
我想在不等待服务器响应的情况下发送 HTTP 请求 (GET)。
我已经通过忽略响应尝试了 IdHTTP
,例如:
aIdHTTP := TIdHTTP.create;
try
aIdHTTP.Get('https://whosebug.com/');
finally
aIdHTTP.free;
free
但它总是等待服务器响应...
一个技巧是在 AWorkMode
为 wmRead
时通过在 TIdHTTP.OnWork
事件中引发异常来关闭连接,这会更快地关闭连接...但是等待 "first byte"响应。
有没有不等待响应就发送数据的方法?
简短的回答是 NO,无论如何 TIdHTTP
都不是。 HTTP 是一种协议,TIdHTTP
遵循该协议,其中包括读取服务器的响应。
正如您发现的那样,您可以 在 TIdHTTP.OnWork
事件中引发异常,但只有从服务器接收到至少 1 个字节后才会起作用。不过,您 可以 指定一个短 TIdHTTP.ReadTimeout
值来避免这种情况。
另一种选择是在 TIdHTTP.OnHeadersAvailable
事件中关闭套接字连接,但这需要 TIdHTTP
读取服务器的完整响应 headers.
IF 响应使用 HTTP 1.1 分块,您 可以 在 TIdHTTP.HTTPOptions
属性。但这也需要读取服务器的完整响应 header.
真的,要完成您的要求,唯一的方法就是完全不使用 TIdHTTP
。使用TIdTCPClient
代替,手动发送自己的HTTP请求,发送后关闭连接,eg:
aIdClient := TIdTCPClient.Create;
try
aIdClient.Host := 'whosebug.com';
aIdClient.Port := 443;
aIdClient.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(aIdClient);
TIdSSLIOHandlerSocketOpenSSL(aIdClient.IOHandler).PassThrough := False;
aIdClient.Connect;
try
aIdClient.IOHandler.WriteLn('GET / HTTP/1.1');
aIdClient.IOHandler.WriteLn('Host: whosebug.com');
aIdClient.IOHandler.WriteLn('Connection: close');
aIdClient.IOHandler.WriteLn;
finally
aIdClient.Disconnect;
end;
finally
aIdClient.free;
end;
但是请求文件而不实际下载它有什么意义呢?
如果你只是想检查服务器是否可以连接,你根本不需要发送任何东西
aIdClient := TIdTCPClient.Create;
try
aIdClient.Host := 'whosebug.com';
aIdClient.Port := 443;
aIdClient.Connect;
aIdClient.Disconnect;
finally
aIdClient.free;
end;
如果您只是想避免通过 HTTP 下载文件的实际内容,您可以使用 TIdHTTP.Head()
而不是 TIdHTTP.Get()
:
aIdHTTP.Head('https://whosebug.com/');
我想在不等待服务器响应的情况下发送 HTTP 请求 (GET)。
我已经通过忽略响应尝试了 IdHTTP
,例如:
aIdHTTP := TIdHTTP.create;
try
aIdHTTP.Get('https://whosebug.com/');
finally
aIdHTTP.free;
free
但它总是等待服务器响应...
一个技巧是在 AWorkMode
为 wmRead
时通过在 TIdHTTP.OnWork
事件中引发异常来关闭连接,这会更快地关闭连接...但是等待 "first byte"响应。
有没有不等待响应就发送数据的方法?
简短的回答是 NO,无论如何 TIdHTTP
都不是。 HTTP 是一种协议,TIdHTTP
遵循该协议,其中包括读取服务器的响应。
正如您发现的那样,您可以 在 TIdHTTP.OnWork
事件中引发异常,但只有从服务器接收到至少 1 个字节后才会起作用。不过,您 可以 指定一个短 TIdHTTP.ReadTimeout
值来避免这种情况。
另一种选择是在 TIdHTTP.OnHeadersAvailable
事件中关闭套接字连接,但这需要 TIdHTTP
读取服务器的完整响应 headers.
IF 响应使用 HTTP 1.1 分块,您 可以 在 TIdHTTP.HTTPOptions
属性。但这也需要读取服务器的完整响应 header.
真的,要完成您的要求,唯一的方法就是完全不使用 TIdHTTP
。使用TIdTCPClient
代替,手动发送自己的HTTP请求,发送后关闭连接,eg:
aIdClient := TIdTCPClient.Create;
try
aIdClient.Host := 'whosebug.com';
aIdClient.Port := 443;
aIdClient.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(aIdClient);
TIdSSLIOHandlerSocketOpenSSL(aIdClient.IOHandler).PassThrough := False;
aIdClient.Connect;
try
aIdClient.IOHandler.WriteLn('GET / HTTP/1.1');
aIdClient.IOHandler.WriteLn('Host: whosebug.com');
aIdClient.IOHandler.WriteLn('Connection: close');
aIdClient.IOHandler.WriteLn;
finally
aIdClient.Disconnect;
end;
finally
aIdClient.free;
end;
但是请求文件而不实际下载它有什么意义呢?
如果你只是想检查服务器是否可以连接,你根本不需要发送任何东西
aIdClient := TIdTCPClient.Create;
try
aIdClient.Host := 'whosebug.com';
aIdClient.Port := 443;
aIdClient.Connect;
aIdClient.Disconnect;
finally
aIdClient.free;
end;
如果您只是想避免通过 HTTP 下载文件的实际内容,您可以使用 TIdHTTP.Head()
而不是 TIdHTTP.Get()
:
aIdHTTP.Head('https://whosebug.com/');