WinHTTP 세션 개요

WinHTTP(Microsoft Windows HTTP 서비스)는 애플리케이션이 웹의 HTTP 리소스에 액세스할 수 있도록 하는 C/C++ 함수 집합을 노출합니다. 이 항목에서는 이러한 함수를 사용하여 HTTP 서버와 상호 작용하는 방법에 대한 개요를 제공합니다.

WinHTTP API를 사용하여 웹 액세스

다음 다이어그램은 HTTP 서버와 상호 작용할 때 WinHTTP 함수가 일반적으로 호출되는 순서를 보여 줍니다. 음영 처리된 상자는 HINTERNET 핸들을 생성하는 함수를 나타내고 일반 상자는 해당 핸들을 사용하는 함수를 나타냅니다.

핸들을 만드는 함수

WinHTTP 초기화

서버와 상호 작용하기 전에 WinHttpOpen을 호출하여 WinHTTP를 초기화해야 합니다. WinHttpOpen은 HTTP 세션에 대한 세부 정보를 유지하기 위해 세션 컨텍스트를 만들고 세션 핸들을 반환합니다. WinHttpConnect 함수는 이 핸들을 사용하여 대상 HTTP 또는 HTTPS(Secure Hypertext Transfer Protocol) 서버를 지정할 수 있습니다.

참고

WinHttpConnect를 호출하면 특정 리소스에 대한 요청이 수행될 때까지 HTTP 서버에 대한 실제 연결이 발생하지 않습니다.

 

요청 열기

WinHttpOpenRequest 함수는 특정 리소스에 대한 HTTP 요청을 열고 다른 HTTP 함수에서 사용할 수 있는 HINTERNET 핸들을 반환합니다. WinHttpOpenRequest 는 호출 시 서버에 요청을 보내지 않습니다. WinHttpSendRequest 함수는 실제로 네트워크를 통해 연결을 설정하고 요청을 보냅니다.

다음 예제에서는 기본 옵션을 사용하는 WinHttpOpenRequest 에 대한 샘플 호출을 보여줍니다.

HINTERNET hRequest = WinHttpOpenRequest( hConnect, L"GET", NULL, NULL, NULL, NULL, 0);

요청 헤더 추가

WinHttpAddRequestHeaders 함수를 사용하면 애플리케이션이 HTTP 요청 핸들에 자유 형식 요청 헤더를 추가로 추가할 수 있습니다. HTTP 서버로 전송된 요청을 정확하게 제어해야 하는 정교한 애플리케이션에서 사용하기 위한 것입니다.

WinHttpAddRequestHeaders 함수에는 WinHttpOpenRequest에서 만든 HTTP 요청 핸들, 헤더, 헤더 길이 및 한정자가 포함된 문자열이 필요합니다.

다음 한정자는 WinHttpAddRequestHeaders와 함께 사용할 수 있습니다.

한정자 Description
WINHTTP_ADDREQ_FLAG_ADD 헤더가 없는 경우 헤더를 추가합니다. WINHTTP_ADDREQ_FLAG_REPLACE 함께 사용됩니다.
WINHTTP_ADDREQ_FLAG_ADD_IF_NEW 헤더가 아직 없는 경우에만 추가합니다. 그렇지 않으면 오류가 반환됩니다.
WINHTTP_ADDREQ_FLAG_COALESCE 같은 이름의 헤더를 병합합니다.
WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA 쉼표로 같은 이름의 헤더를 병합합니다. 예를 들어 이 플래그와 함께 "Accept: text/*" 뒤에 "Accept: audio/*"를 추가하면 단일 헤더 "Accept: text/*, audio/*"가 형성되어 첫 번째 헤더가 병합됩니다. 병합/별도의 헤더와 관련하여 응집력 있는 구성표를 보장하는 것은 호출 애플리케이션에 달려 있습니다.
WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON 세미콜론을 사용하여 동일한 이름의 헤더를 병합합니다.
WINHTTP_ADDREQ_FLAG_REPLACE 헤더를 바꾸거나 제거합니다. 헤더 값이 비어 있고 헤더가 있으면 제거됩니다. 헤더 값이 비어 있지 않으면 헤더 값이 바뀝니다.

 

요청 보내기

WinHttpSendRequest 함수는 서버에 대한 연결을 설정하고 지정된 사이트로 요청을 보냅니다. 이 함수에는 WinHttpOpenRequest에서 만든 HINTERNET 핸들이 필요합니다. WinHttpSendRequest 는 추가 헤더 또는 선택적 정보를 보낼 수도 있습니다. 선택적 정보는 일반적으로 PUT 및 POST와 같은 정보를 서버에 쓰는 작업에 사용됩니다.

WinHttpSendRequest 함수가 요청을 보낸 후 애플리케이션은 HINTERNET 핸들에서 WinHttpReadDataWinHttpQueryDataAvailable 함수를 사용하여 서버의 리소스를 다운로드할 수 있습니다.

서버에 데이터 게시

서버에 데이터를 게시하려면 WinHttpOpenRequest 호출의 HTTP 동사는 POST 또는 PUT이어야 합니다. WinHttpSendRequest가 호출되면 dwTotalLength 매개 변수를 데이터 크기(바이트)로 설정해야 합니다. 그런 다음 WinHttpWriteData 를 사용하여 데이터를 서버에 게시합니다.

또는 WinHttpSendRequestlpOptional 매개 변수를 서버에 게시할 데이터가 포함된 버퍼의 주소로 설정합니다. 이 기술을 사용하는 경우 WinHttpSendRequestdwOptionalLengthdwTotalLength 매개 변수를 모두 게시되는 데이터의 크기로 설정해야 합니다. 이러한 방식으로 WinHttpSendRequest 를 호출하면 WinHttpWriteData를 호출할 필요가 없습니다.

요청에 대한 정보 가져오기

WinHttpQueryHeaders 함수를 사용하면 애플리케이션이 HTTP 요청에 대한 정보를 검색할 수 있습니다. 함수에는 WinHttpOpenRequest에서 만든 HINTERNET 핸들, 정보 수준 값 및 버퍼 길이가 필요합니다. 또한 WinHttpQueryHeaders 는 정보를 저장하는 버퍼와 이름이 같은 여러 헤더를 열거하는 0부터 시작하는 헤더 인덱스를 허용합니다.

쿼리 정보 플래그 페이지에 있는 정보 수준 값을 한정자와 함께 사용하여 정보가 WinHttpQueryHeaderslpvBuffer 매개 변수에 저장되는 형식을 제어합니다.

웹에서 리소스 다운로드

WinHttpOpenRequest 함수를 사용하여 요청을 열고, WinHttpSendRequest를 사용하여 서버로 보내고, WinHttpReceiveResponse로 응답을 받기 위해 요청 핸들을 준비한 후 애플리케이션은 WinHttpReadDataWinHttpQueryDataAvailable 함수를 사용하여 HTTP 서버에서 리소스를 다운로드할 수 있습니다.

다음 샘플 코드는 보안 트랜잭션 의미 체계를 사용하여 리소스를 다운로드하는 방법을 보여 줍니다. 샘플 코드는 WinHTTP API(애플리케이션 프로그래밍 인터페이스)를 초기화하고, 대상 HTTPS 서버를 선택한 다음, 이 보안 리소스에 대한 요청을 열고 보냅니다. WinHttpQueryDataAvailable 은 요청 핸들과 함께 사용하여 다운로드할 수 있는 데이터의 양을 확인한 다음 WinHttpReadData 를 사용하여 해당 데이터를 읽습니다. 이 프로세스는 전체 문서를 검색하고 표시할 때까지 반복됩니다.

  DWORD dwSize = 0;
  DWORD dwDownloaded = 0;
  LPSTR pszOutBuffer;
  BOOL  bResults = FALSE;
  HINTERNET  hSession = NULL, 
             hConnect = NULL,
             hRequest = NULL;

  // Use WinHttpOpen to obtain a session handle.
  hSession = WinHttpOpen( L"WinHTTP Example/1.0",  
                          WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
                          WINHTTP_NO_PROXY_NAME, 
                          WINHTTP_NO_PROXY_BYPASS, 0 );

  // Specify an HTTP server.
  if( hSession )
    hConnect = WinHttpConnect( hSession, L"www.microsoft.com",
                               INTERNET_DEFAULT_HTTPS_PORT, 0 );

  // Create an HTTP request handle.
  if( hConnect )
    hRequest = WinHttpOpenRequest( hConnect, L"GET", NULL,
                                   NULL, WINHTTP_NO_REFERER, 
                                   WINHTTP_DEFAULT_ACCEPT_TYPES, 
                                   WINHTTP_FLAG_SECURE );

  // Send a request.
  if( hRequest )
    bResults = WinHttpSendRequest( hRequest,
                                   WINHTTP_NO_ADDITIONAL_HEADERS, 0,
                                   WINHTTP_NO_REQUEST_DATA, 0, 
                                   0, 0 );


  // End the request.
  if( bResults )
    bResults = WinHttpReceiveResponse( hRequest, NULL );

  // Keep checking for data until there is nothing left.
  if( bResults )
  {
    do 
    {
      // Check for available data.
      dwSize = 0;
      if( !WinHttpQueryDataAvailable( hRequest, &dwSize ) )
        printf( "Error %u in WinHttpQueryDataAvailable.\n",
                GetLastError( ) );

      // Allocate space for the buffer.
      pszOutBuffer = new char[dwSize+1];
      if( !pszOutBuffer )
      {
        printf( "Out of memory\n" );
        dwSize=0;
      }
      else
      {
        // Read the data.
        ZeroMemory( pszOutBuffer, dwSize+1 );

        if( !WinHttpReadData( hRequest, (LPVOID)pszOutBuffer, 
                              dwSize, &dwDownloaded ) )
          printf( "Error %u in WinHttpReadData.\n", GetLastError( ) );
        else
          printf( "%s", pszOutBuffer );

        // Free the memory allocated to the buffer.
        delete [] pszOutBuffer;
      }
    } while( dwSize > 0 );
  }


  // Report any errors.
  if( !bResults )
    printf( "Error %d has occurred.\n", GetLastError( ) );

  // Close any open handles.
  if( hRequest ) WinHttpCloseHandle( hRequest );
  if( hConnect ) WinHttpCloseHandle( hConnect );
  if( hSession ) WinHttpCloseHandle( hSession );