如何在单独的线程中发出超时的 HTTP 请求?

发布于 2024-08-25 13:34:28 字数 307 浏览 2 评论 0原文

我已经有一段时间没有用 Delphi 编程了,坦率地说,我认为我不需要这样做,但是...... 我在这里拼命寻找有关此事的一些信息,但现在信息太少了,我什么也找不到。所以也许你们可以帮助我。

目前我的应用程序使用 Synapse 库进行 HTTP 调用,但它不允许设置超时。通常,这不是一个大问题,但现在我绝对必须有一个超时才能很好地处理任何连接问题。

我正在寻找的是一个库(同步或非同步),它允许使 HTTP 请求对用户绝对透明,没有可见或隐藏的延迟。我现在无法立即终止线程,并且可能有许多频繁的请求没有响应的服务器,这不好。

编辑:谢谢大家的回答!

I haven't programmed in Delphi for a while and frankly didn't think I'll ever have to but...
Here I am, desperately trying to find some information on the matter and it's so scarce nowadays, I can't find anything. So maybe you guys could help me out.

Currently my application uses Synapse library to make HTTP calls, but it doesn't allow for setting a timeout. Usually, that's not a big problem, but now I absolutely must to have a timeout to handle any connectivity issues nicely.

What I'm looking for, is a library (synchronous or not) that will allow making HTTP requests absolutely transparent for the user with no visible or hidden delays. I can't immediately kill a thread right now, and with possibility of many frequent requests to the server that is not responding, it's no good.

EDIT: Thanks everybody for your answers!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

把人绕傻吧 2024-09-01 13:34:28

在进行网络通信时,您始终必须考虑延迟和超时。恕我直言,您可以得到的最接近的是将网络通信放在一个线程中。然后您可以检查线程是否在所需的时间内完成,如果不是就让它完成,但忽略结果(没有安全的方法来中止线程)。这还有一个额外的优点:您现在可以使用同步网络调用,这更容易阅读。

You will always have to take delays and timeouts into account when doing network communication. The closest you can get IMHO is to put network communication in a thread. Then you can check if the thread finishes in the desired time and if not just let it finish, but ignore the result (there's no safe way to abort a thread). This has an additional advantage: you can now just use synchronous network calls which are a lot easier to read.

執念 2024-09-01 13:34:28

synapse 中,超时可从 TSynaClient 对象,其中 THttpSend 源自。因此,调整超时(假设您使用标准函数)所需要做的就是复制您使用的函数,添加新参数并将超时设置为您需要的值。例如:

function HttpGetTextTimeout(const URL: string; 
                            const Response: TStrings;
                            const Timeout:integer): Boolean;
var
  HTTP: THTTPSend;
begin
  HTTP := THTTPSend.Create;
  try
    HTTP.Timeout := Timeout;
    Result := HTTP.HTTPMethod('GET', URL);
    if Result then
      Response.LoadFromStream(HTTP.Document);
  finally
    HTTP.Free;
  end;
end;

Synapse 默认超时为 5000,如果等待足够长的时间就会超时。由于其紧密包含,突触在线程中运行得非常好。

In synapse, the timeout is available from the TSynaClient object, which THttpSend decends from. So all you have to do to adjust for timeout (assuming your using the standard functions) is to copy the function your using, add a new parameter and set the Timeout to what you need. For example:

function HttpGetTextTimeout(const URL: string; 
                            const Response: TStrings;
                            const Timeout:integer): Boolean;
var
  HTTP: THTTPSend;
begin
  HTTP := THTTPSend.Create;
  try
    HTTP.Timeout := Timeout;
    Result := HTTP.HTTPMethod('GET', URL);
    if Result then
      Response.LoadFromStream(HTTP.Document);
  finally
    HTTP.Free;
  end;
end;

Synapse defaults to a timeout of 5000 and does timeout if you wait long enough. Since its tightly contained, synapse runs perfectly fine in threads.

家住魔仙堡 2024-09-01 13:34:28

[已知仅适用于 D2010]

您可以使用 MSXML 发送客户端请求(将 msxmlole2 添加到 uses 子句)。诀窍是使用 IServerXMLHTTPRequest 而不是 IXMLHTTPRequest,因为前者允许指定超时。下面的代码显示了线程的 Execute() 方法:

procedure TClientSendThread.Execute;
const
  LResolveTimeoutMilliseconds = 2000;
  LConnectTimeoutMilliseconds = 5000;
  LSendTimeoutMilliseconds = 5000;
  LReceiveTimeoutMilliseconds = 10000;
var
  LHTTPServer: IServerXMLHTTPRequest;
  LDataStream: TMemoryStream;
  LData: OleVariant;
begin
  {Needed because this is inside a thread.}
  CoInitialize(nil);
  LDataStream := TMemoryStream.Create;
  try
    {Populate ....LDataStream...}
    LData := MemoryStreamToOleVariant(LDataStream);

    LHTTPServer := CreateOleObject('MSXML2.ServerXMLHTTP.3.0') as IServerXMLHTTPRequest;
    LHTTPServer.setTimeouts(
      LResolveTimeoutMilliseconds,
      LConnectTimeoutMilliseconds,
      LSendTimeoutMilliseconds,
      LReceiveTimeoutMilliseconds
      );
    LHTTPServer.open('POST', URL, False, 0, 0);
    LHTTPServer.send(LData);
    FAnswer := LHTTPServer.responseText;
  finally
    FreeAndNil(LDataStream);
    CoUninitialize;
  end;
end;

我最近发现了这种 MSXML 技术的一个极其烦人的行为,其中如果后续发送的URL保持不变;换句话说,客户端正在缓存 GET 请求。 POST 不会发生这种情况。

显然,一旦发生超时,Execute 方法就会完成,线程就会被清理。

[Known to work on D2010 only]

You can use MSXML to send client requests (add msxml and ole2 to your uses clause). The trick is to use IServerXMLHTTPRequest rather than IXMLHTTPRequest, as the former allows timeouts to be specified. The code below shows the Execute() method of a thread:

procedure TClientSendThread.Execute;
const
  LResolveTimeoutMilliseconds = 2000;
  LConnectTimeoutMilliseconds = 5000;
  LSendTimeoutMilliseconds = 5000;
  LReceiveTimeoutMilliseconds = 10000;
var
  LHTTPServer: IServerXMLHTTPRequest;
  LDataStream: TMemoryStream;
  LData: OleVariant;
begin
  {Needed because this is inside a thread.}
  CoInitialize(nil);
  LDataStream := TMemoryStream.Create;
  try
    {Populate ....LDataStream...}
    LData := MemoryStreamToOleVariant(LDataStream);

    LHTTPServer := CreateOleObject('MSXML2.ServerXMLHTTP.3.0') as IServerXMLHTTPRequest;
    LHTTPServer.setTimeouts(
      LResolveTimeoutMilliseconds,
      LConnectTimeoutMilliseconds,
      LSendTimeoutMilliseconds,
      LReceiveTimeoutMilliseconds
      );
    LHTTPServer.open('POST', URL, False, 0, 0);
    LHTTPServer.send(LData);
    FAnswer := LHTTPServer.responseText;
  finally
    FreeAndNil(LDataStream);
    CoUninitialize;
  end;
end;

I recently discovered an extremely annoying behavior of this MSXML technique in which GET requests will not be re-sent if the URL remains unchanged for subsequent sendings; in other words, the client is caching GET requests. This does not happen with POST.

Obviously, once the timeouts occur, the Execute method completes and the thread is cleaned up.

陌伤ぢ 2024-09-01 13:34:28

Synapse 可以配置为在发生网络错误时引发异常。

RaiseExcept

检查http://synapse.ararat .cz/doc/help/blcksock.TBlockSocket.html#RaiseExcept

如果为 True,则会引发 winsock 错误
例外。否则被设置
仅 LastError 值,您必须
从你的程序中检查一下!默认
值为 False。

Synapse can be configured to raise an Exception when network errors occur.

RaiseExcept

Check http://synapse.ararat.cz/doc/help/blcksock.TBlockSocket.html#RaiseExcept:

If True, winsock errors raises
exception. Otherwise is setted
LastError value only and you must
check it from your program! Default
value is False.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文