我有一个在主线程上使用Wininet进行同步和异步调用的应用程序。使用标志-INTERNET_FLAG_ASYNC
打开单个根Internet句柄。该句柄用于所有呼叫。要实现同步网络呼叫,我们只需在无限的while循环中等待,直到请求完成。我们间歇性地看到Wininet没有收到任何回应。
下面的一些代码片段/伪代码显示了我们正在尝试执行的操作。
// struct Context{
bool resultReady;
}
// Callback function registered with Wininet to know about the progress of ongoing call
static void CALLBACK StatusCallBack (
IN HINTERNET hInternet,
IN DWORD_PTR dwContext,
IN DWORD dwInternetStatus,
IN LPVOID lpvStatusInformation OPTIONAL,
IN DWORD dwStatusInformationLength )
{
Context* cxt = (Context *)dwContext;
switch (dwInternetStatus) {
// other cases ...
case INTERNET_STATUS_REQUEST_COMPLETE :
cxt->resultReady = true; break;
}
}
// Open root internet handle
HINTERNET root_hnd = InternetOpenA(agentname, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_ASYNC);
// Set status callback
InternetSetStatusCallback(root_hnd, StatusCallBack );
// Open connect handle
Context connect_cxt = {};
HINTERNET connect_hnd = InternetConnectA(root_hnd, hostname, NULL, NULL, INTERNET_SERVICE_HTTP, 0, &connect_cxt);
// Open HTTP request handle
Context http_cxt= {};
DWORD flags = INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_AUTH | INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_RELOAD | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS;
HINTERNET http_hnd = HttpOpenRequestA(connect_hnd, verb, objectname, HTTP_VERSIONA, NULL, NULL, flags, &http_cxt);
HttpSendRequestA(file, NULL, 0, additionalOptions, optionsLen);
while(http_cxt.resultReady == false) {
Sleep(10);
}
这只是我们正在做的一小段。我们在每个步骤都有错误处理,并且也有同步机制。为了调用相同的主机名,我们也重用了Internet连接句柄,但是每次都打开一个新的http请求句柄。
在调试时,我们发现如果对同一服务器有多个异步调用,Wininet将这些调用排队,并且除非之前的请求完成,否则实际上不会发送请求:http://webdebug.net/2013/01/wininet-connection-limit/
我们通过增加允许的连接限制来解决此问题,并在仍然超出限制的情况下在启动时自行调用失败。但是,即使在仅对服务器进行单个异步调用的情况下(有时其他服务器可能正在进行其他调用),我们有时仍会看到相同的症状。一旦完成发送请求,在注册的回调函数中根本不会得到任何响应。
我想知道Wininet是否需要释放在其上打开了句柄的线程以便向我们发送正在进行的回调?此外,还有其他可能缺少的连接限制吗?