Мне нужно извлечь данные примерно с 6000 страниц веб-сайта. После некоторых исследований я решил дать WinHTTP выстрел. Я смог получить эту работу, однако я делал это синхронно, поэтому потребовалось некоторое время, чтобы закончить. Теперь я пытаюсь использовать WinHTTP асинхронно, но я попал в блокпост. Я искал несколько руководств и примеров, но я мог найти только документацию MSDN, которая кажется слишком сложной для того, что я делаю. Как уже упоминалось, я не мог найти много ресурсов, поэтому я пошел вперед и дал ему шанс:Несколько асинхронных запросов WinHTTP
std::string theSource = "";
char * httpBuffer;
DWORD dwSize = 1;
DWORD dwRecv = 1;
HINTERNET hOpen =
WinHttpOpen
(
L"Example Agent",
WINHTTP_ACCESS_TYPE_NO_PROXY,
NULL,
NULL,
WINHTTP_FLAG_ASYNC
);
WINHTTP_STATUS_CALLBACK theCallback =
WinHttpSetStatusCallback
(
hOpen,
(WINHTTP_STATUS_CALLBACK) HttpCallback,
WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS,
NULL
);
HINTERNET hConnect =
WinHttpConnect
(
hOpen,
L"example.org",
INTERNET_DEFAULT_HTTPS_PORT,
0
);
HINTERNET hRequest = NULL;
BOOL allComplete = false;
int theRequest = 1;
while (!allComplete)
{
if (theRequest == 1)
{
hRequest = WinHttpOpenRequest
(
hConnect,
L"GET",
L"example.html",
0,
WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
WINHTTP_FLAG_SECURE
);
WinHttpSendRequest
(
hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS,
0,
WINHTTP_NO_REQUEST_DATA,
0,
0,
0
);
}
else if (theRequest == 2)
{
WinHttpReceiveResponse(hRequest, NULL);
}
else if (theRequest == 3)
{
WinHttpQueryHeaders
(
hRequest,
WINHTTP_QUERY_RAW_HEADERS_CRLF,
WINHTTP_HEADER_NAME_BY_INDEX,
NULL,
&dwSize,
WINHTTP_NO_HEADER_INDEX
);
WCHAR * headerBuffer = new WCHAR[dwSize/sizeof(WCHAR)];
WinHttpQueryHeaders
(
hRequest,
WINHTTP_QUERY_RAW_HEADERS_CRLF,
WINHTTP_HEADER_NAME_BY_INDEX,
headerBuffer,
&dwSize,
WINHTTP_NO_HEADER_INDEX
);
delete [] headerBuffer;
dwSize = 1;
while (dwSize > 0)
{
if (!WinHttpQueryDataAvailable(hRequest, &dwSize))
{
break;
}
httpBuffer = new char[dwSize + 1];
ZeroMemory(httpBuffer, dwSize + 1);
if (!WinHttpReadData(hRequest, httpBuffer, dwSize, &dwRecv))
{
std::cout << "WinHttpReadData() - Error Code: " << GetLastError() << "\n";
}
else
{
theSource = theSource + httpBuffer;
}
delete [] httpBuffer;
// Parse the source for the data I'm looking for.
break;
}
}
Ниже моя функция обратного вызова:
void CALLBACK HttpCallback(HINTERNET hInternet, DWORD * dwContext, DWORD dwInternetStatus, void * lpvStatusInfo, DWORD dwStatusInfoLength)
{
switch (dwInternetStatus)
{
default:
std::cout << dwInternetStatus << "\n";
break;
case WINHTTP_CALLBACK_STATUS_HANDLE_CREATED:
std::cout << "Handle created.\n";
theRequest = 1;
break;
case WINHTTP_CALLBACK_STATUS_REQUEST_SENT:
std::cout << "Request sent.\n";
theRequest = 2;
break;
case WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED:
std::cout << "Response received.\n";
theRequest = 3;
break;
}
}
Примечание: Я только при условии этот раздел моего кода, поскольку это часть, относящаяся к моему вопросу/проблеме. Прошу прощения, если отсутствует объявление переменной.
Приведенный выше код работает для меня и фактически получает желаемую информацию, которую я ищу, но только для одной страницы. Подойдя к этому моменту, я понял, что не имел никакого представления о том, что делать, когда речь идет о создании нескольких запросов с помощью этого метода. Опять же, поиск не включался в многое кроме статей MSDN, которые, насколько я могу судить, не являются примерами, которые делают сразу несколько запросов. Кроме того, цикл while, который я использую для открытия/отправки/etc. запросы, основанные на значении Request, кажутся ужасным способом сделать это. Я был бы признателен за любые другие советы по улучшению моего кода.
В общем, вот резюме моей проблемы: мне нужно сделать около 6000 запросов GET с использованием WinHTTP асинхронно. Я не совсем уверен, как это сделать, потому что я новичок в WinHTTP, поэтому я ищу наиболее простой (или, возможно, эффективный) способ работы с несколькими асинхронными запросами.
Вы видите эту статью MSDN: [Асинхронный WinHTTP] (http://msdn.microsoft.com/en-us/magazine/cc716528.aspx)? И, возможно, этот однопоточный, многопроцессорный и простой в понимании [Perl API 'HTTP :: Async'] (https://metacpan.org/module/HTTP::Async) может дать вам некоторое вдохновение в том, как действовать дальше. – Lumi