3

Web サイトの約 6000 ページからデータを取得する必要があります。いくつかの調査を行った後、WinHTTP を試してみることにしました。これを機能させることができましたが、同期的に行っていたため、完了するまでに時間がかかりました。現在、WinHTTP を非同期で使用しようとしていますが、障害にぶつかっています。多くのチュートリアルと例を探しましたが、MSDN のドキュメントしか見つかりませんでした。前述のように、多くのリソースを見つけることができなかったので、先に進んで試してみました。

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 の記事以外はあまり見つかりませんでした。MSDN の記事は、私が知る限り、一度に複数の要求を行う例ではありません。さらに、open/send/etc に使用している while ループ。theRequest の値に基づくリクエストは、これを行うにはひどい方法のようです。コードを改善するための他のアドバイスもいただければ幸いです。

一般的に、ここに私の問題の要約があります: WinHTTP を非同期で使用して約 6000 の GET 要求を行う必要があります。私は WinHTTP を初めて使用するため、これを行う方法が完全にはわかりません。そのため、複数の非同期要求を処理するための最も基本的な (またはおそらく効率的な) 方法を探しています。

4

1 に答える 1

2

あなたは自分がしていることを繰り返して、while (!allComplete) { ... }この方法でより多くの要求を撃つことになっています. 再利用できますが、リソース要求ごとhConnectに行う必要があります。WinHttpOpenRequest

于 2012-05-19T06:22:15.960 に答える