2012-05-18 12 views
2

약 6000 페이지의 웹 사이트에서 데이터를 가져와야합니다. 몇 가지 조사를 한 후에, 나는 WinHTTP를 한방 먹이기로 결정했다. 나는이 일을 할 수 있었지만 일을 동 기적으로하고 있었기 때문에 완료하는 데 시간이 걸렸다. WinHTTP를 비동기 적으로 사용하려고 시도하고 있지만로드 블록을 쳤습니다. 몇 가지 자습서와 예제를 검색했지만 MSDN 설명서 만 찾을 수있었습니다. 이는 내가하고있는 일에 지나치게 복잡하게 보입니다. 언급 한 바와 같이, 나는 많은 자원을 찾을 수 없습니다, 그래서 내가 나서서 그것을 촬영했다 :WinHTTP 여러 비동기 요청

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; 

    } 
} 

참고 :

다음
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; 

    } 
} 

내 콜백 함수이다 나는 단지이 부분을 제공 한을 그것은 내 질문/문제에 관련된 부분이기 때문에 내 코드의. 변수 선언이 누락되면 사과드립니다.

위 코드는 저에게 효과적이며 실제로 원하는 정보를 얻지 만 단일 페이지에 대해서만 제공됩니다. 이 시점에 이르면이 방법으로 여러 요청을 할 때 수행 할 작업에 대해 알지 못한다는 사실을 깨달았습니다. 다시 말하지만 MSDN 기사 외에 검색이 많이 이루어지지 않았습니다. MSDN 기사는 한 번에 여러 요청을하는 예제가 아닙니다. 또한, while 루프는/etc/send를 열기 위해 사용하고 있습니다. theRequest의 값에 기반한 요청은 이것을하는 끔찍한 방법처럼 보입니다. 내 코드를 개선하기 위해 다른 조언을 주시면 감사하겠습니다.

일반적으로 다음은 내 문제 요약입니다. WinHTTP를 비동기 적으로 사용하여 약 6000 건의 GET 요청을 만들어야합니다. 필자는 WinHTTP를 처음 사용하기 때문에이 작업을 수행하는 방법을 완전히 알지 못하므로 여러 비동기 요청을 처리하는 가장 기본적인 (또는 가능한 효율적인) 방법을 찾고 있습니다.

+0

[비동기 WinHTTP] (http://msdn.microsoft.com/en-us/magazine/cc716528.aspx) MSDN 문서를 보았습니까? 그리고이 단일 스레드, 멀티 소켓 및 이해하기 쉬운 [Perl API'HTTP :: Async'] (https://metacpan.org/module/HTTP::Async)는 진행 방법에 대한 영감을 줄 수 있습니다. – Lumi

답변

2

당신은 while (!allComplete) { ... }에서하고있는 일을 반복하고 이런 식으로 더 많은 요청을해야합니다. hConnect을 재사용 할 수 있지만 모든 리소스 요청마다 WinHttpOpenRequest을 수행해야합니다.

+0

몇 가지 예제 코드를 작성하거나 제공해 주시겠습니까? 가능한 경우 후자가 나를 위해 가장 도움이 될 것입니다. 추가 요청을 루프에 통합하고 적절하게 모니터링 할 수있는 방법을 찾지 못했습니다. 각 요청은 현재 코드를 기반으로 언제든지 콜백 함수를 통해 해당 값을 수정할 것이기 때문에 헤더를 쿼리하거나 데이터를 읽는 theRequest의 값에 의존 할 수 없습니다. –

+1

'theRequest'는이 시나리오에서 전역 변수가 될 수 없으며, 특정'hRequest'에만 적용됩니다. 따라서'theRequest' +'hRequest' 값을 가진 일종의 구조체 콜렉션이 필요합니다. –