【发布时间】:2015-06-26 10:26:06
【问题描述】:
我有一个使用 WinINet 函数异步下载文件的函数。我使用的方法是:
- InternetOpen
- InternetSetStatusCallback
- InternetOpenUrl(同步)
- InternetReadFileEx(异步)
- InternetReadFileEx 在回调函数中直到接收到的缓冲区为0
我怎样才能等到InternetOpenUrl 完成,以便返回的句柄有效?如果我运行InternetOpenUrl async,由于可能的重定向,我无法判断何时收到最后一个INTERNET_STATUS_RESPONSE_RECEIVED。另外,当InternetOpenUrl 完成后,我想用INTERNET_OPTION_URL 标志调用InternetQueryOption,以获取所有重定向后的最终URL(如果有)。
std::vector<DOWNLOAD_CONTEXT> contexts;
void Download(TCHAR *url, unsigned int crc32, unsigned int length)
{
HINTERNET hInternet = InternetOpen(_T("Test"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
InternetSetStatusCallback(hInternet, DownloadProgress);
DOWNLOAD_CONTEXT context;
context.hInternet = hInternet;
contexts.push_back(context);
HINTERNET hUrl = InternetOpenUrl(hInternet, url, _T(""), 0, INTERNET_FLAG_RELOAD, DWORD_PTR(&*(contexts.end()-1)));
/* if InternetOpenUrl would have been executed in blocking mode,
here I would have executed the first async InternetReadFileEx,
and InternetQueryOption to get the final URL*/
}
void CALLBACK DownloadProgress(
_In_ HINTERNET hInternet,
_In_ DWORD_PTR dwContext,
_In_ DWORD dwInternetStatus,
_In_ LPVOID lpvStatusInformation,
_In_ DWORD dwStatusInformationLength
)
{
DOWNLOAD_CONTEXT *context = (DOWNLOAD_CONTEXT*)dwContext;
switch (dwInternetStatus)
{
case INTERNET_STATUS_HANDLE_CREATED:
context->hUrl = (HINTERNET)((LPINTERNET_ASYNC_RESULT)lpvStatusInformation)->dwResult;
break;
case INTERNET_STATUS_RESPONSE_RECEIVED:
size = 0;
InternetQueryOptionA(context->hUrl, INTERNET_OPTION_URL, nullptr, &size);
link = new char[size];
InternetQueryOptionA(context->hUrl, INTERNET_OPTION_URL, link, &size);
MessageBoxA(NULL, link, "", MB_OK);
delete[] link;
/* if this is the last response (the HTTP status code is 200)
we initiate InternetReadFileEx recursion */
break;
...
default:
MessageBoxA(NULL, "Status: Unknown (%d)\n", "", MB_OK);
break;
}
}
此外,由于InternetOpenUrl 尚未完成,因此在回调内部,一些 WinINet 函数将因ERROR_INTERNET_INCORRECT_HANDLE_STATE 而失败。虽然 InternetQueryOption 确实在每个 INTERNET_STATUS_RESPONSE_RECEIVED 处显示 URL。
InternetOpenUrl 将生成以下回调状态序列:
- INTERNET_STATUS_HANDLE_CREATED
- INTERNET_STATUS_DETECTING_PROXY
- INTERNET_STATUS_SENDING_REQUEST
- INTERNET_STATUS_REQUEST_SENT
- INTERNET_STATUS_RECEIVING_RESPONSE
- INTERNET_STATUS_RESPONSE_RECEIVED
- INTERNET_STATUS_REDIRECT
- INTERNET_STATUS_DETECTING_PROXY
- INTERNET_STATUS_RESOLVING_NAME
- INTERNET_STATUS_NAME_RESOLVED
- INTERNET_STATUS_CONNECTING_TO_SERVER
- INTERNET_STATUS_CONNECTED_TO_SERVER
- INTERNET_STATUS_SENDING_REQUEST
- INTERNET_STATUS_REQUEST_SENT
- INTERNET_STATUS_RECEIVING_RESPONSE
- INTERNET_STATUS_RESPONSE_RECEIVED
我如何知道最后一个 INTERNET_STATUS_RESPONSE_RECEIVED 何时到达(HTTP 状态 200)?
【问题讨论】:
标签: c++ asynchronous callback msdn wininet