Сеансы HTTP

WinINet позволяет получать доступ к ресурсам в Интернете (WWW). Доступ к этим ресурсам можно получить напрямую с помощью InternetOpenUrl (дополнительные сведения см. в разделе Прямой доступ к URL-адресам).

Доступ к ресурсам на www-сайте можно получить по протоколу HTTP. Функции HTTP обрабатывают базовые протоколы, позволяя приложению получать доступ к сведениям на сайте WWW. По мере развития протокола HTTP базовые протоколы обновляются для поддержания поведения функций.

На следующей схеме показаны связи функций, используемых с протоколом HTTP. Затеняемые поля представляют функции, возвращающие дескрипторы HINTERNET , а обычные — функции, использующие дескриптор HINTERNET , созданный функцией, от которой они зависят.

Функции wininet, используемые для http

Дополнительные сведения см. в разделе HintERNET Handles.

Использование функций WinINet для доступа к WWW

Следующие функции используются во время сеансов HTTP для доступа к WWW.

Функция Описание
HttpAddRequestHeaders Добавляет заголовки HTTP-запроса в дескриптор HTTP-запроса. Для этой функции требуется дескриптор, созданный httpOpenRequest.
HttpOpenRequest Открывает дескриптор HTTP-запроса. Для этой функции требуется дескриптор, созданный InternetConnect.
HttpQueryInfo Запрашивает сведения о HTTP-запросе. Для этой функции требуется дескриптор, созданный функцией HttpOpenRequest или InternetOpenUrl .
HttpSendRequest Отправляет указанный HTTP-запрос на HTTP-сервер. Для этой функции требуется дескриптор, созданный httpOpenRequest.
InternetErrorDlg Отображает стандартные диалоговые окна для распространенных ошибок в Интернете. Для этой функции требуется дескриптор, используемый в вызове HttpSendRequest.

 

Инициализация подключения к WWW

Чтобы запустить подключение к www, приложение должно вызвать функцию InternetConnect в корневом элементе HINTERNET , возвращенном InternetOpen. InternetConnect должен установить сеанс HTTP, объявив тип службы INTERNET_SERVICE_HTTP. Дополнительные сведения об использовании InternetConnect см. в разделе Использование InternetConnect.

Открытие запроса

Функция HttpOpenRequest открывает HTTP-запрос и возвращает дескриптор HINTERNET , который может использоваться другими функциями HTTP. В отличие от других открытых функций (таких как FtpOpenFile и InternetOpenUrl), HttpOpenRequest не отправляет запрос в Интернет при вызове. Функция HttpSendRequest отправляет запрос и устанавливает подключение по сети.

HttpOpenRequest принимает дескриптор сеанса HTTP, созданный InternetConnect , и HTTP-команду, имя объекта, строку версии, ссылок, типы принятия, флаги и контекстное значение.

HTTP-команда — это строка, используемая в запросе. Распространенные HTTP-команды, используемые в запросах, включают GET, PUT и POST. Если для этого значения задано значение NULL, HttpOpenRequest использует значение по умолчанию GET.

Имя объекта — это строка, содержащая имя целевого объекта указанной HTTP-команды. Обычно это имя файла, исполняемый модуль или описатель поиска. Если предоставленное имя объекта является пустой строкой, HttpOpenRequest ищет страницу по умолчанию.

Строка версии должна содержать версию HTTP. Если этот параметр имеет значение NULL, функция использует "HTTP/1.1".

Ссылка указывает адрес документа, из которого было получено имя объекта. Если этот параметр имеет значение NULL, ссылочный объект не указан.

Строка, завершающаяся значением NULL, содержащая типы принятия, указывает типы контента, принятые приложением. Установка для этого параметра значения NULL означает, что приложение не принимает типы контента. Если указана пустая строка, приложение указывает, что принимает только документы типа ""text/*". Значение ""text/*"" указывает только текстовые документы, а не рисунки или другие двоичные файлы.

Значения флагов управляют кэшированием, файлами cookie и проблемами безопасности. Для Microsoft Network (MSN), NTLM и других типов проверки подлинности установите флаг INTERNET_FLAG_KEEP_CONNECTION .

Если флаг INTERNET_FLAG_ASYNC был установлен в вызове InternetOpen, для правильной асинхронной операции должно быть задано ненулевое значение контекста.

В следующем примере показан пример вызова HttpOpenRequest.

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

Добавление заголовков запросов

Функция HttpAddRequestHeaders позволяет приложениям добавлять один или несколько заголовков запроса в исходный запрос. Эта функция позволяет приложению добавлять дополнительные заголовки в свободном формате в дескриптор HTTP-запроса; он предназначен для использования сложными приложениями, которым требуется точный контроль над запросом, отправленным на HTTP-сервер.

HttpAddRequestHeaders требуется дескриптор HTTP-запроса, созданный httpOpenRequest, строка, содержащая заголовки, длину заголовков и модификаторы.

Отправка запроса

HttpSendRequest устанавливает подключение к Интернету и отправляет запрос на указанный сайт. Для этой функции требуется дескриптор HINTERNET , созданный httpOpenRequest. HttpSendRequest также может отправлять дополнительные заголовки или дополнительные сведения. Необязательные сведения обычно используются для операций, которые записывают информацию на сервер, например PUT и POST.

После отправки запроса HttpSendRequest приложение может использовать функции InternetReadFile, InternetQueryDataAvailable и InternetSetFilePointer в дескрипторе HINTERNET , созданном HttpOpenRequest , для скачивания ресурсов сервера.

Публикация данных на сервере

Для отправки данных на сервер http-команда в вызове HttpOpenRequest должна иметь значение POST или PUT. Затем адрес буфера, содержащего данные POST, должен быть передан параметру lpOptional в HttpSendRequest. Параметр dwOptionalLength должен иметь размер данных.

Функцию InternetWriteFile можно также использовать для публикации данных в дескрипторе HINTERNET, отправленном с помощью HttpSendRequestEx.

Получение сведений о запросе

HttpQueryInfo позволяет приложению получать сведения о HTTP-запросе. Для функции требуется дескриптор HINTERNET , созданный httpOpenRequest или InternetOpenUrl, значение уровня информации и длина буфера. HttpQueryInfo также принимает буфер, в котором хранятся сведения, и индекс заголовка с отсчитываемого от нуля, который перечисляет несколько заголовков с одинаковым именем.

Скачивание ресурсов из WWW

После открытия запроса с помощью HttpOpenRequest и его отправки на сервер с помощью HttpSendRequest приложение может использовать функции InternetReadFile, InternetQueryDataAvailable и InternetSetFilePointer для скачивания ресурса с HTTP-сервера.

В следующем примере выполняется скачивание ресурса. Функция принимает дескриптор к текущему окну, идентификационный номер поля ввода и дескриптор HINTERNET , созданный httpOpenRequest и отправленный 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).