【问题标题】:Delphi 2010 - Wininet running out of handlesDelphi 2010 - Wininet 用完了句柄
【发布时间】:2011-10-19 11:43:45
【问题描述】:

我有一个应用程序,它大量使用Wininet 函数从互联网获取一些数据。我有时会收到一个非常奇怪的与句柄相关的错误消息:

Internal error in ConnectToHost when trying to create a session 
ERROR_INTERNET_OUT_OF_HANDLES: No more handles could be generated at this time. Wininet error code = 12001;

发生这种情况时,我注意到我的应用程序创建了 5000 多个句柄。我运行了一个资源配置文件,发现wininet 创建的一些句柄没有被释放。

因此,我创建了一个小应用程序来重现该问题。代码很简单,除了分配一些wininet 句柄然后释放它们之外什么也不做。那是代码:

procedure request(const AUrl : AnsiString);
var
  sMethod     : AnsiString;
  pSession    : HINTERNET;
  pConnection : HINTERNET;
  pRequest    : HINTERNET;
  port        : Integer;
  flags       : DWord;
begin
  pSession := InternetOpen(nil, INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  if Assigned(pSession) then
  try
    Port := INTERNET_DEFAULT_HTTP_PORT;
    pConnection := InternetConnectA(pSession, PAnsiChar(AUrl), port, nil, nil, INTERNET_SERVICE_HTTP, 0, 0);
    if Assigned(pConnection) then
      try
        sMethod := 'GET';
        flags := INTERNET_SERVICE_HTTP;
        pRequest := HTTPOpenRequestA(pConnection, PAnsiChar(sMethod), PAnsiChar(AUrl), nil, nil, nil, flags, 0);
        try
          if Assigned(pRequest) then
            ShowMessage('ok');
        finally
          InternetCloseHandle(pRequest);
        end;
      finally
        InternetCloseHandle(pConnection);
      end;
  finally
    InternetCloseHandle(pSession);
  end;
end;

在我的分析器上运行这个示例,我得到了相同的句柄相关问题。

我认为InternetCloseHandle 没有像应有的那样释放句柄,因为我的资源配置文件告诉我,当我关闭应用程序时,我有 3 个活动句柄。这些是未被释放的句柄:

pRequest
pConnection
pSession

有谁知道如何摆脱这个?

编辑

函数InternetCloseHandle工作正常,返回值为true

编辑

我在互联网上搜索了很多,但我找不到任何人抱怨这一点。但它正在发生。我想知道是否有人复制了这个问题,还是只有我一个人。

【问题讨论】:

  • 如果您正在执行数千个请求(恕我直言),您应该避免打开和关闭句柄,尝试打开一个句柄,做您的事情,然后再使用它,当应用程序关闭时,关闭句柄,瞧.但是,如果你的代码是在一个线程中执行的,那就另当别论了,重新考虑这个过程并考虑最快的解决方案,我找不到其他人抱怨这个错误,我没有搜索太多...
  • @Dorin 我无能为力。 Wininet 需要为每个请求创建一些句柄,所以我必须创建它们并释放它们。奇怪的是,我也找不到任何人抱怨这一点。但是分析器没有说谎,InternetCloseHandle 有问题。
  • 也许使用 TIdHTTP 看看你是否遇到相同的结果?我知道它使用几乎相同的 API 调用,但一定是我们遗漏了什么,你能在多台 PC/VM 上重现这个问题吗?
  • 我在此处发布的代码遇到了这个问题。什么都没有改变,只是那个代码。我猜问题出在 AQTime 上。我今天将尝试其他一些程序。顺便说一句,indy 没有问题并且工作正常。

标签: delphi winapi resources wininet aqtime


【解决方案1】:

原来是 AQtime 问题。我下载了另一个分析器,还查看了任务管理器,似乎正在释放句柄。但有时我仍然会收到no more handles 错误,我不知道为什么。但我会提出另一个问题,因为这个问题只是为了看看为什么这些句柄没有被释放。

感谢我得到的所有帮助。

【讨论】:

  • 嗨,雷菲尔!感谢您发布这个问题 - SmartBear 开发团队能够找到问题的原因并修复它。如果您想解决问题,请随时联系 SmartBear 技术支持 (smartbear.com/support/message/?prod=AQtime) 并参考此主题。
  • 没问题!很高兴我能帮助你。感谢您拥有如此出色的支持团队。
【解决方案2】:

Http 协议有一些限制,Wininet 正在使用它们。 查看WinInet limits connections per server:

WinInet 将与单个 HTTP 1.0 服务器的连接限制为四个同时连接。与单个 HTTP 1.1 服务器的连接仅限于两个同时连接。 HTTP 1.1 规范 (RFC2616) 规定了两个连接的限制。 HTTP 1.0 的四连接限制是一种自我强加的限制,与许多流行的 Web 浏览器使用的标准一致。

也许您应该等到连接关闭后再尝试新连接

【讨论】:

  • 抱歉,我问的不是这个。我正在连接不同的服务器。另外,我正在设置 INTERNET_OPTION_MAX_CONNS_PER_SERVER INTERNET_OPTION_MAX_CONNS_PER_1_0_SERVER 以确保。我的连接不在线程中。我的代码一次建立 1 个连接。不过还是谢谢。
  • 好的,你试过在 InternetCloseHandle 检查返回值吗?
  • 不,我没有。它应该可以工作,但我会看看它。
  • InternetCloseHandle 工作正常。返回值为真。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-29
  • 1970-01-01
相关资源
最近更新 更多