Udostępnij za pośrednictwem


Omówienie sesji WinHTTP

Usługi HTTP systemu Microsoft Windows (WinHTTP) uwidacznia zestaw funkcji C/C++, które umożliwiają aplikacji uzyskiwanie dostępu do zasobów HTTP w sieci Web. Ten temat zawiera omówienie sposobu używania tych funkcji do interakcji z serwerem HTTP.

Uzyskiwanie dostępu do sieci Web przy użyciu interfejsu API WinHTTP

Na poniższym diagramie przedstawiono kolejność, w jakiej funkcje WinHTTP są zwykle wywoływane podczas interakcji z serwerem HTTP. Zacienione pola reprezentują funkcje, które generują uchwyt HINTERNET, a zwykłe pola reprezentują funkcje używające tych uchwytów.

funkcje, które tworzą uchwyty

Inicjowanie usługi WinHTTP

Przed rozpoczęciem interakcji z serwerem należy zainicjować winHTTP, wywołując WinHttpOpen. WinHttpOpen tworzy kontekst sesji w celu zachowania szczegółowych informacji o sesji HTTP i zwraca dojście sesji. Korzystając z tego uchwytu, funkcja WinHttpConnect może następnie określić docelowy serwer HTTP lub serwer HTTPS (Bezpieczny protokół przesyłania hipertekstu).

Notatka

Wywołanie WinHttpConnect nie powoduje rzeczywistego połączenia z serwerem HTTP, dopóki żądanie nie zostanie wykonane dla określonego zasobu.

 

Otwieranie żądania

Funkcja WinHttpOpenRequest otwiera żądanie HTTP dla określonego zasobu i zwraca uchwyt HINTERNET, który może być używany przez inne funkcje HTTP. WinHttpOpenRequest nie wysyła żądania do serwera po wywołaniu. Funkcja WinHttpSendRequest faktycznie ustanawia połączenie za pośrednictwem sieci i wysyła żądanie.

W poniższym przykładzie pokazano przykładowe wywołanie WinHttpOpenRequest, które używa opcji domyślnych.

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

Dodawanie nagłówków żądań

Funkcja WinHttpAddRequestHeaders umożliwia aplikacji dołączanie dodatkowych nagłówków żądań w formacie wolnym do dojścia żądania HTTP. Jest ona przeznaczona do użycia przez zaawansowane aplikacje, które wymagają dokładnej kontroli nad żądaniami wysyłanymi do serwera HTTP.

Funkcja WinHttpAddRequestHeaders wymaga obsługi żądania HTTP utworzonej przez WinHttpOpenRequest, ciągu znaków zawierającego nagłówki, długości nagłówków oraz wszelkich modyfikatorów.

Następujące modyfikatory mogą być używane z WinHttpAddRequestHeaders.

Modyfikator Opis
WINHTTP_ADDREQ_FLAG_ADD Dodaje nagłówek, jeśli nie istnieje. Używany z WINHTTP_ADDREQ_FLAG_REPLACE.
WINHTTP_ADDREQ_FLAG_ADD_IF_NEW Dodaje nagłówek tylko wtedy, gdy jeszcze nie istnieje; w przeciwnym razie zwracany jest błąd.
WINHTTP_ADDREQ_FLAG_COALESCE Łączy nagłówki o tej samej nazwie.
WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA Łączy nagłówki o tej samej nazwie za pomocą przecinka. Na przykład dodanie ciągu "Accept: text/*", a następnie "Accept: audio/*" z tą flagą tworzy jeden nagłówek "Accept: text/*, audio/*", powodując połączenie pierwszego znalezionego nagłówka. To w gestii aplikacji wywołującej jest zapewnienie spójnego schematu w odniesieniu do scalonych/oddzielnych nagłówków.
WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON Łączy nagłówki o tej samej nazwie za pomocą średnika.
WINHTTP_ADDREQ_FLAG_REPLACE Zastępuje lub usuwa nagłówek. Jeśli wartość pola nagłówka jest pusta i nagłówek zostanie znaleziony, to jest on usuwany. Jeśli wartość nagłówka nie jest pusta, wartość nagłówka zostanie zamieniona.

 

Wysyłanie żądania

Funkcja WinHttpSendRequest ustanawia połączenie z serwerem i wysyła żądanie do określonej lokacji. Ta funkcja wymaga uchwytu HINTERNET utworzonego przez WinHttpOpenRequest. WinHttpSendRequest może również wysyłać dodatkowe nagłówki lub informacje opcjonalne. Opcjonalne informacje są zwykle używane w przypadku operacji zapisujących informacje na serwerze, takich jak PUT i POST.

Po wysłaniu żądania przez funkcję WinHttpSendRequest aplikacja może użyć funkcji WinHttpReadData i WinHttpQueryDataAvailable na uchwyt HINTERNET do pobrania zasobów serwera.

Publikowanie danych na serwerze

Aby wysłać dane na serwer, czasownik HTTP w wywołaniu WinHttpOpenRequest musi być jednym z dwóch: POST lub PUT. Po wywołaniu WinHttpSendRequest należy ustawić parametr dwTotalLength na rozmiar danych w bajtach. Następnie użyj WinHttpWriteData, aby opublikować dane na serwerze.

Alternatywnie ustaw parametr lpOptional WinHttpSendRequest na adres buforu zawierającego dane do opublikowania na serwerze. W przypadku korzystania z tej techniki należy ustawić zarówno dwOptionalLength, jak i dwTotalLength parametrów WinHttpSendRequest jako rozmiar publikowanych danych. Wywołanie WinHttpSendRequest w ten sposób eliminuje konieczność wywoływania WinHttpWriteData.

Uzyskiwanie informacji o żądaniu

Funkcja WinHttpQueryHeaders umożliwia aplikacji pobieranie informacji o żądaniu HTTP. Funkcja wymaga HINTERNET utworzonego przez WinHttpOpenRequest, wartości poziomu informacji i długości buforu. WinHttpQueryHeaders również akceptuje bufor, który przechowuje informacje i indeks nagłówka zero, który wylicza wiele nagłówków o tej samej nazwie.

Użyj dowolnych poziomów informacji znalezionych na stronie Flagi informacji o zapytaniach z modyfikatorem, aby kontrolować format przechowywania informacji w parametrze lpvBuffer funkcji WinHttpQueryHeaders.

Pobieranie zasobów z sieci Web

Po otwarciu żądania za pomocą funkcji WinHttpOpenRequest, wysyłanie go do serwera za pomocą WinHttpSendRequesti przygotowanie dojścia żądania w celu odebrania odpowiedzi za pomocą WinHttpReceiveResponseaplikacja może użyć WinHttpReadData i funkcji WinHttpQueryDataAvailable w celu pobrania zasobu z serwera HTTP.

Poniższy przykładowy kod pokazuje, jak pobrać zasób z bezpiecznymi semantykami transakcji. Przykładowy kod inicjuje interfejs programowania aplikacji WinHTTP (API), wybiera docelowy serwer HTTPS, a następnie otwiera i wysyła żądanie dla tego bezpiecznego zasobu. WinHttpQueryDataAvailable służy do obsługi żądań w celu określenia ilości dostępnych danych do pobrania, a następnie WinHttpReadData jest używana do odczytywania tych danych. Ten proces jest powtarzany do momentu pobrania i wyświetlenia całego dokumentu.

  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 );