HTTP 會話

WinINet 可讓您存取 World Wide Web (WWW) 上的資源。 如需詳細資訊,請參閱直接存取 URL) ,方法是使用 InternetOpenUrl (來 直接存取 這些資源。

WWW 上的資源是使用 HTTP 來存取。 HTTP 函式會處理基礎通訊協定,同時允許您的應用程式存取 WWW 上的資訊。 隨著 HTTP 通訊協定發展,基礎通訊協定會更新以維護函式行為。

下圖顯示搭配 HTTP 通訊協定使用的函式關聯性。 陰影方塊代表傳回 HINTERNET 控制碼的函式,而純方塊則代表使用由函式所建立之 HINTERNET 控制碼的函式。

wininet functions used for http

如需詳細資訊,請參閱 HINTERNET 控制碼

使用 WinINet 函式存取 WWW

下列函式會在 HTTP 會話期間用來存取 WWW。

函式 描述
HttpAddRequestHeaders 將 HTTP 要求標頭新增至 HTTP 要求控制碼。 此函式需要 HttpOpenRequest所建立的控制碼。
HttpOpenRequest 開啟 HTTP 要求控制碼。 此函式需要 InternetConnect所建立的控制碼。
HttpQueryInfo 查詢 HTTP 要求的相關資訊。 此函式需要 HttpOpenRequestInternetOpenUrl 函式所建立的控制碼。
HttpSendRequest 將指定的 HTTP 要求傳送至 HTTP 伺服器。 此函式需要 HttpOpenRequest所建立的控制碼。
InternetErrorDlg 顯示常見網際網路錯誤狀況的預先定義對話方塊。 此函式需要呼叫 HttpSendRequest中使用的控制碼。

 

起始與 WWW 的連線

若要開始與 WWW 的連線,應用程式必須在InternetOpen所傳回的根HINTERNET上呼叫InternetConnect函式。 InternetConnect 必須宣告INTERNET_SERVICE_HTTP服務類型來建立 HTTP 會話。 如需使用 InternetConnect的詳細資訊,請參閱 使用 InternetConnect

開啟要求

HttpOpenRequest函式會開啟 HTTP 要求,並傳回其他 HTTP 函式可以使用的HINTERNET控制碼。 不同于其他開啟的函式 (,例如 FtpOpenFileInternetOpenUrl) , HttpOpenRequest 不會在呼叫時將要求傳送至網際網路。 HttpSendRequest函式會傳送要求,並透過網路建立連線。

HttpOpenRequest 會採用 InternetConnect 所建立的 HTTP 會話控制碼,以及 HTTP 動詞、物件名稱、版本字串、參考者、接受類型、旗標和內容值。

HTTP 動詞是要求中使用的字串。 要求中使用的常見 HTTP 動詞包括 GET、PUT 和 POST。 如果此值設定為 NullHttpOpenRequest 會使用預設值 GET。

物件名稱是包含指定 HTTP 動詞目標物件名稱的字串。 這通常是檔案名、可執行模組或搜尋規範。 如果提供的物件名稱是空字串, HttpOpenRequest 會尋找預設頁面。

版本字串應該包含 HTTP 版本。 如果此參數為 Null,函式會使用 「」HTTP/1.1」。

參考者會指定從中取得物件名稱的檔位址。 如果此參數為 Null,則未指定任何參照者。

包含接受類型的 Null終止字串表示應用程式接受的內容類型。 將此參數設定為 Null 表示應用程式不接受任何內容類型。 如果提供空字串,應用程式會指出它只接受類型為 「」text/*「 的檔。 值 「」text/*「」 表示僅限文字的檔,而不是圖片或其他二進位檔案。

旗標值會控制快取、Cookie 和安全性問題。 針對 Microsoft Network (MSN) 、NTLM 和其他類型的驗證,請設定 INTERNET_FLAG_KEEP_CONNECTION 旗標。

如果在呼叫InternetOpen時設定INTERNET_FLAG_ASYNC旗標,則應該為適當的非同步作業設定非零內容值。

下列範例是 HttpOpenRequest的範例呼叫。

hHttpRequest = HttpOpenRequest( hHttpSession, "GET", "", NULL, "", NULL, 0, 0);

新增要求標頭

HttpAddRequestHeaders函式可讓應用程式將一或多個要求標頭新增至初始要求。 此函式可讓應用程式將額外的自由格式標頭附加至 HTTP 要求控制碼;它適用于需要精確控制傳送至 HTTP 伺服器之要求的複雜應用程式。

HttpAddRequestHeaders 需要 HttpOpenRequest所建立的 HTTP 要求控制碼、包含標頭的字串、標頭的長度和修飾詞。

傳送要求

HttpSendRequest 會建立網際網路的連線,並將要求傳送至指定的網站。 此函式需要HttpOpenRequest所建立的HINTERNET控制碼。 HttpSendRequest 也可以傳送其他標頭或選擇性資訊。 選擇性資訊通常用於將資訊寫入伺服器的作業,例如 PUT 和 POST。

在 HttpSendRequest傳送要求之後,應用程式可以在HttpOpenRequest所建立的HINTERNET控制碼上使用InternetReadFileInternetQueryDataAvailableInternetSetFilePointer函式來下載伺服器的資源。

將資料張貼到伺服器

若要將資料張貼到伺服器,對 HttpOpenRequest 的呼叫中的 HTTP 動詞命令必須是 POST 或 PUT。 接著,應該將包含 POST 資料的緩衝區位址傳遞至HttpSendRequest中的lpOptional參數。 dwOptionalLength參數應該設定為數據的大小。

您也可以使用InternetWriteFile函式,在使用HttpSendRequestEx傳送的HINTERNET控制碼上張貼資料。

取得要求的相關資訊

HttpQueryInfo 可讓應用程式擷取 HTTP 要求的相關資訊。 函式需要HttpOpenRequestInternetOpenUrl所建立的HINTERNET控制碼、資訊層級值,以及緩衝區長度。 HttpQueryInfo 也接受儲存資訊的緩衝區,以及以零起始的標頭索引,以列舉具有相同名稱的多個標頭。

從 WWW 下載資源

使用 HttpOpenRequest 開啟要求並將其傳送至具有 HttpSendRequest的伺服器之後,應用程式可以使用 InternetReadFileInternetQueryDataAvailableInternetSetFilePointer 函式,從 HTTP 伺服器下載資源。

下列範例會下載資源。 函式會接受目前視窗的控制碼、編輯方塊的識別碼,以及由 HttpOpenRequest所建立的HINTERNET控制碼,並由HttpSendRequest傳送。 它會使用 InternetQueryDataAvailable 來判斷資源的大小,然後使用 InternetReadFile下載它。 然後,內容會顯示在編輯方塊中。

int WINAPI Dumper(HWND hX, int intCtrlID, HINTERNET hResource)
{
    LPTSTR lpszData;    // buffer for the data
    DWORD  dwSize;       // size of the data available
    DWORD  dwDownloaded; // size of the downloaded data
    DWORD  dwSizeSum=0;  // size of the data in the textbox
    LPTSTR lpszHolding;  // buffer to merge the textbox data and buffer

    // Set the cursor to an hourglass.
    SetCursor(LoadCursor(NULL,IDC_WAIT));

    // This loop handles reading the data.
    do
    {
        // The call to InternetQueryDataAvailable determines the
        // amount of data available to download.
        if (!InternetQueryDataAvailable(hResource,&dwSize,0,0))
        {
            printf("InternetQueryDataAvailable failed (%d)\n", GetLastError());
            SetCursor(LoadCursor(NULL,IDC_ARROW));
            return FALSE;
        }
        else
        {
            // Allocate a buffer of the size returned by
            // InternetQueryDataAvailable.
            lpszData = new TCHAR[dwSize+1];

            // Read the data from the HINTERNET handle.
            if(!InternetReadFile(hResource,
                                 (LPVOID)lpszData,
                                 dwSize,
                                 &dwDownloaded))
            {
                printf("InternetReadFile failed (%d)\n", GetLastError());
                delete[] lpszData;
                break;
            }
            else
            {
                // Add a null terminator to the end of the data buffer
                lpszData[dwDownloaded]='\0';

                // Allocate the holding buffer.
                lpszHolding = new TCHAR[dwSizeSum + dwDownloaded + 1];

                // Check if there has been any data written
                // to the textbox.
                if (dwSizeSum != 0)
                {
                    // Retrieve the data stored in the textbox if any
                    GetDlgItemText(hX,intCtrlID,
                                   (LPTSTR)lpszHolding,
                                   dwSizeSum);

                    // Add a null terminator at the end of the
                    // textbox data.
                    lpszHolding[dwSizeSum]='\0';
                }
                else
                {
                    // Make the holding buffer an empty string.
                    lpszHolding[0]='\0';
                }

                size_t cchDest = dwSizeSum + dwDownloaded + dwDownloaded + 1;
                LPTSTR* ppszDestEnd = 0;
                size_t* pcchRemaining = 0;

                // Add the new data to the holding buffer
                HRESULT hr = StringCchCatEx(lpszHolding,
                                            cchDest,
                                            lpszData,
                                            ppszDestEnd,
                                            pcchRemaining,
                                            STRSAFE_NO_TRUNCATION);

                if(SUCCEEDED(hr))
                {
                    // Write the holding buffer to the textbox.
                    SetDlgItemText(hX,intCtrlID,(LPTSTR)lpszHolding);

                    // Delete the two buffers.
                    delete[] lpszHolding;
                    delete[] lpszData;

                    // Add the size of the downloaded data to the
                    // textbox data size.
                    dwSizeSum = dwSizeSum + dwDownloaded + 1;

                    // Check the size of the remaining data.
                    // If it is zero, break.
                    if (dwDownloaded == 0)
                        break;
                    else
                    {
                    //  TODO: Insert error handling code here.
                    }
                }
            }
        }
    }
    while(TRUE);

    // Close the HINTERNET handle.
    InternetCloseHandle(hResource);

    // Set the cursor back to an arrow.
    SetCursor(LoadCursor(NULL,IDC_ARROW));

    return TRUE;
}

注意

WinINet 不支援伺服器實作。 此外,它不應該從服務使用。 對於伺服器實作或服務,請使用Microsoft Windows HTTP 服務 (WinHTTP)