WinHTTP会话概述

WinHTTP会话概述

Microsoft Windows HTTP服务(WinHTTP)公开了一组C / C ++函数,使您的应用程序能够访问Web上的HTTP资源。 本主题概述了如何使用这些函数与HTTP服务器交互。

0x01.使用WinHTTP API访问Web

下图显示了与HTTP服务器交互时通常调用WinHTTP函数的顺序。 阴影框表示生成HINTERNET句柄的函数,而平面框表示使用这些句柄的函数。

WinHTTP会话概述_第1张图片

0x02.初始化WinHTTP

在与服务器交互之前,WinHTTP必须通过调用WinHttpOpen进行初始化。 WinHttpOpen创建会话上下文以维护有关HTTP会话的详细信息,并返回会话句柄。使用此句柄,WinHttpConnect功能然后能够指定目标HTTP或安全超文本传输​​协议(HTTPS)服务器。

注意: 对特定资源发出请求之前,对WinHttpConnect的调用不会导致与HTTP服务器的实际连接。

0x03.打开请求

WinHttpOpenRequest函数打开特定资源的HTTP请求,并返回一个可以被其他HTTP函数使用的HINTERNET句柄。 WinHttpOpenRequest在调用时不会将请求发送到服务器。 WinHttpSendRequest函数实际上通过网络建立连接并发送请求。

以下示例显示了使用默认选项调用WinHttpOpenRequest的示例。

HINTERNET hRequest = WinHttpOpenRequest(hConnect,L“GET”,NULLNULLNULLNULL0);

0x04.添加请求标头

WinHttpAddRequestHeaders函数允许应用程序将附加的自由格式请求头附加到HTTP请求句柄。它适用于需要精确控制发送到HTTP服务器的请求的复杂应用程序。

WinHttpAddRequestHeaders函数需要一个由WinHttpOpenRequest创建的HTTP请求句柄,该字符串包含头部,头部的长度和任何修饰符。

以下修饰符可以与WinHttpAddRequestHeaders一起使用。

Modifier 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 替换或删除标头。如果标头值为空,并且找到标头,则将其删除。如果标头值不为空,则替换标头值。

0x05.发送请求

WinHttpSendRequest函数建立与服务器的连接,并将请求发送到指定的站点。此函数需要一个由WinHttpOpenRequest创建的HINTERNET句柄。 WinHttpSendRequest也可以发送附加头或可选信息。可选信息通常用于向服务器写入信息的操作,例如PUTPOST
WinHttpSendRequest函数发送请求后,应用程序可以使用HINTERNET句柄上的WinHttpReadDataWinHttpQueryDataAvailable函数下载服务器的资源。

0x06.将数据发布到服务器

要将数据发布到服务器,调用WinHttpOpenRequest中的HTTP动词必须是POSTPUT。当调用WinHttpSendRequest时,dwTotalLength参数应设置为以字节为单位的数据大小。然后使用WinHttpWriteData将数据发布到服务器。
或者,将WinHttpSendRequestlpOptional参数设置为包含要发布到服务器的数据的缓冲区的地址。使用此技术时,必须将WinHttpSendRequestdwOptionalLengthdwTotalLength参数设置为要发布的数据的大小。以这种方式调用WinHttpSendRequest消除了调用WinHttpWriteData的需要。

0x07.获取有关请求的信息

WinHttpQueryHeaders函数允许应用程序检索有关HTTP请求的信息。该函数需要由WinHttpOpenRequest创建的HINTERNET句柄,信息级别值和缓冲区长度。 WinHttpQueryHeaders也接受一个存储信息的缓冲区和一个基于零的头索引,枚举多个同名的头。
使用在查询信息标志页面上找到的任何信息级别值以及一个修饰符来控制信息存储在WinHttpQueryHeaderslpvBuffer参数中的格式。

0x08.从Web下载资源

在使用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 );

你可能感兴趣的:(windows之API函数)