HTTP 會話

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

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

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

用於 HTTP 的 wininet 函式

如需詳細資訊,請參閱 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 Services (WinHTTP)