Поделиться через


Сеансы 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см. в статье Using 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-terminated, содержащая типы принятия, указывает типы контента, принятые приложением. Установка этого параметра на 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 для дескриптора HINTER NET, созданного HttpOpenRequest для скачивания ресурсов сервера.

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

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

Можно также использовать функцию InternetWriteFile для публикации данных в дескриптореHINTERNETHINTERNET, отправленном с помощью 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 Services (WinHTTP).