Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Разработка приложений для Internet

© Александр Фролов, Григорий Фролов
Том 31, М.: Диалог-МИФИ, 1997, 286 стр.

[Назад] [Содеожание] [Дальше]

Классы WinInet

Библиотека MFC значительно упрощают использование программного интерфейса WinInet. Начиная с версии 4.2 в MFC добавлен целый ряд новых классов созданных на основе программного интерфейса WinInet.

Рисунок 1.1 представляет вашему вниманию схему классов WinInet.


CObject -> CInternetSession
        |
        -> CInternetConnection -> CHttpConnection
        |                      |
        |                      -> CFtpConnection 
        |                      |
        |                      -> CGopherConnection 
        |
        -> CFile -> CStdioFile -> CInternetFile -> CHttpFile 
        |                                       |
        |                                       -> CGopherFile
        |
        -> CFileFind -> CFtpFileFind
        |            |
        |            -> CGopherFileFind
        |  
        -> CGopherLocator
        |
        -> CException -> CInternetException

Рис. 1.1. Схема классов WinInet

Более полное описание классам MFC, предназначенным для работы с WinInet, мы дадим несколько позже, а сейчас только представим их список с краткими пояснениями:

Класс

Описание

CInternetSession

Класс подготавливает сеанс связи с Internet. Это самый общий класс, который необходимо использовать для работы с другими классами WinInet

CInternetConnection

Управляет соединением с серверами в Internet вне зависимости от их типа (FTP, WWW, Gopher)

CFtpConnection

Управляет соединением с серверами FTP по протоколу FTP. Позволяет выполнять манипуляции с файлами и каталогами сервера

CHttpConnection

Управляет соединением с серверами WWW по протоколу HTTP

CGopherConnection

Используется для соединения с серверами Gopher

CInternetFile

Используется для получения файлов с серверов WWW и Gopher

CHttpFile

Класс позволяет передать запрос серверу WWW и получить от него ответ (данные)

CGopherFile

Предназначен для работы с серверами Gopher

CFileFind

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

CFtpFileFind

Выполняет поиск файлов на сервере FTP

CGopherFileFind

Выполняет поиск файлов на сервере Gopher

CGopherLocator

Создает объект, связанный с файлом Gopher

CInternetException

Представляет исключения, связанные с ошибками при работе WinInet

Практически все классы библиотеки MFC, управляющие интерфейсом WinInet, а также несколько глобальных функций WinInet определены во включаемом файле afxinet.h. Исключение составляет только класс CFileFind, который определен в другом включаемом файле библиотеки MFC - afx.h. Данные включаемые файлы должны быть указаны в исходных текстах приложений, работающих с интерфейсом WinInet:


#include <afxinet.h>  // Используется интерфейсом WinInet
#include <afx.h>      // Содержит определение класса CFileFind

Общие принципы устройства приложений WinInet

Приложения, взаимодействующие с серверами Internet посредством программного интерфейса WinInet и надстроенных над ним классов библиотеки MFC, должны придерживаться стандартных сценариев установления связи и обмена данными, которые мы рассмотрим в данном разделе.

Сеанс связи

Любое приложение, использующее классы и методы WinInet, должно, в первую очередь, инициализировать сеанс работы с интерфейсом WinInet или, другими словами, сеанс связи. Для этого следует создать объект класса CInternetSession. Одно приложение может установить несколько сеансов связи, если того требует выполняемая им задача.

Только после этого в рамках данного сеанса возможна дальнейшая работа с серверами Internet, будь то установление связи с серверами WWW или FTP, чтение и запись файлов, поиск файлов по заданному адресу и т. д. Единственное что вы можете делать с программным интерфейсом WinInet до того, как создан сеанс - это выполнять разбор адресов URL при помощи глобальной функции AfxParseURL. Описание этой функции и пример ее использования вы найдете в разделе “Адреса URL”.

По окончании работы следует закрыть сеанс связи и удалить соответствующий объект класса CInternetSession, если он был создан динамически.

Настройка сеанса связи

Как только создан объект класса CInternetSession, представляющий сеанс связи, вы можете воспользоваться методами этого класса, чтобы изменить некоторые его характеристики. Так, например, вы можете установить ограничение на выполнение некоторых операций, которые могут отнять много времени. Для этого вы можете использовать методы SetOption и QueryOption. Заметим, однако, что в большинстве случаев изменять характеристики сеанса связи нет никакой необходимости и вы можете сразу приступить к выполнению основной задачи - соединиться с сервером WWW или FTP, просмотреть структуру его каталогов, прочитать или записать файл.

Обработка ошибок

В случае возникновения ошибок, многие методы классов WinInet вызывают исключение CInternetException. Чтобы правильно обрабатывать эти исключения, вы должны поместить методы, которые могут вызвать исключение, в блок try и определить соответствующий блок catch, выполняющий его обработку.

Взаимодействие с серверами Internet

У вас существует две принципиально разные возможности работы с серверами Internet. Первая предполагает, что вам надо только выполнить чтение объекта, адрес которого известен. Вторая возможность требует более сложных манипуляций, зато позволяет выполнять специфические операции, например поиск файлов на сервере FTP, создание и удаление каталогов, передача запросов на сервер WWW и т. д.

Чтение файла с серверов сети Internet

В этом случае вы можете сразу вызвать метод OpenURL класса CInternetSession. Он выполнит соединение с указанным ему сервером и создаст объект класса CInternetFile, соответствующий необходимому вам файлу.

Далее вы можете воспользоваться методами класса CInternetFile, чтобы прочитать данный файл с сервера на локальный компьютер. Для этой цели вы можете вызвать метод Read, который читает файл и записывает считанные данные в буфер, или метод ReadString, который считывает из файла текстовую строку, ограниченную символом перевода строки.

Описанный метод получения файла не позволяет выполнить обратную задачу - записать файл на сервер FTP. Серверы WWW и Gopher такую операцию не допускают в любом случае. От них вы можете только получать информацию.

Взаимодействие с серверами FTP, WWW и Gopher

Чтобы выполнять с серверами Internet специфические операции, например создать на сервере FTP новый каталог или передать запрос на сервер WWW, вы должны сначала установить соединение с сервером данного типа. Для этого в состав класса CInternetSession включены три специальные метода - GetFtpConnection, GetHttpConnection и GetGopherConnection. Они, соответственно, открывают соединение с серверами FTP, WWW и Gopher, а также создают объект представляющий соединение с сервером соответствующего типа.

Так метод GetFtpConnection, который выполняет соединение с сервером FTP, возвращает объект класса CFtpConnection, метод GetHttpConnection - объект класса СHttpConnection, а метод GetGopherConnection - объект класса СGopherConnection. Далее вы можете обращаться к методам этих классов и выполнять различные операции с сервером.

Асинхронный режим WinInet

К сожалению, классы WinInet имеют один недостаток. Большинство операций по взаимодействию с сетью Internet занимают много времени. Даже процедура соединения с сервером может занять несколько десятков секунд. Мы уже не говорим о загрузки с серверов FTP файлов большого размера. Даже если вы имеете соединение с Internet через высокоскоростной модем, получение файла с размерами в несколько мегабайт займет несколько десятков минут.

В самом простом случае классы WinInet используются в синхронном режиме, вызывая соответствующие методы классов непосредственно из основной задачи приложения. Естественно, пользовательский интерфейс приложения в этом случае блокируется. Мало того, что пользователь не сможет работать с таким приложением во время загрузки файла, если вы переключитесь в это время на другое приложение, открыв его окно поверх окна приложения работающего с Internet, а затем попытаетесь переключится обратно, то окно приложения не будет восстановлено.

Иллюстрацией вышесказанного может быть приложение FtpView, описанное нами в разделе “Загрузка файлов с сервера FTP”. Соединитесь с его помощью с каким-либо сервером FTP и попытайтесь загрузить файл большого размера. Вы увидите что в этом случае пользовательский интерфейс приложения блокируется и окно приложения не перерисовывается.

Существует две возможности выхода из этой ситуации.

Во-первых, можно организовать в рамках приложения еще одину задачу, и все вызовы методов WinInet, которые могут занять много времени выполнять именно из нее. При этом основная задача приложения останется свободеной и пользовательский интерфейс блокироваться не будет.

Во-вторых, можно использовать WinInet в асинхронном режиме. При этом методы классов WinInet будут сразу возвращать управление еще до того как соответствующая операция завершится. Возникает вопрос, как же приложение узнает о том что длительная асинхронная операция наконец-то завершилась и можно продолжить работу приложения далее?

Программный интерфейс WinInet извещает приложение о завершении асинхронной операции через специальную функцию обратного вызова. Если вы используете классы MFC, управляющие WinInet, вы можете воспользоваться виртуальным методом OnStatusCallback класса CInternetSession, который вызывается функцией обратного вызова WinInet.

¨     Метод OnStatusCallback также может использоваться и в том случае, если вы вызываете методы WinInet в синхронном режиме. В этом случае OnStatusCallback позволит вашему приложению сообщать пользователю более подробную информацию о исполнении текущей операции

Чтобы воспользоваться методом OnStatusCallback, вы должны наследовать от класса CInternetSession собственный класс, переопределив в нем этот метод.

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

После того как вы создадите объект этого класса, представляющий сеанс связи, вы должны вызвать метод EnableStatusCallback чтобы разрешить использование метода OnStatusCallback.

Теперь дальнейшие вызовы методов классов WinInet могут завершиться с ошибкой ERROR_IO_PENDING, означающей что операция выполняется в асинхронном режиме. Когда асинхронная операция завершится, будет вызван метод OnStatusCallback с кодом завершения INTERNET_STATUS_REQUEST_COMPLETE. Сразу заметим, что метод OnStatusCallback вызывается не только по завершении асинхронной операции. Этот метод также может вызываться раньше и сигнализирует о выполнении какой либо конкретной фазы асинхронной операции.

Метод OnStatusCallback имеет несколько параметров, которые определяют текущее состояние исполняемой операции WinInet. Один и тот же метод OnStatusCallback вызывается для всех асинхронных операций, исполняемых в рамках данного сеанса связи. Чтобы иметь возможность различать, какая операция вызвала метод OnStatusCallback, ему передается идентификатор контекста. Идентификатор контекста является числом типа DWORD и указывается при вызове многих методов классов WinInet. По умолчанию, идентификатор контекста принимается равным единице.

Теперь, когда вы получили общее представление об устройстве приложений WinInet, мы опишем соответствующие классы MFC. Мы будем подробно рассматривать только наиболее важные методы этих классов, которые впоследствии будут использоваться в наших приложениях. Описание остальных методов вы найдете в справочной системе Microsoft Visual C++.

Мы также рекомендуем вам ознакомиться с исходными текстами интересующих вас методов. В них вы сможете найти ответы на многие свои вопросы. Некоторые программисты даже считают исходные тексты MFC самой лучшей документацией к этой библиотеке. Вам также потребуется описание программного интерфейса WinInet, которое вы можете найти на сервере WWW Microsoft по адресу http://www.microsoft.com/workshoop/prog/sdk/docs/wininet/.

Класс CInternetSession

Класс CInternetSession представляет сеанс. Вы должны создать объект класса CInternetSession перед использованием остальных классов и методов WinInet. Вы можете либо непосредственно создать объект класса CInternetSession, либо сначала наседовать от класса CInternetSession собственный клас и использовать уже его.

Класс CInternetSession наследуется от базового класса CObject, лежащего в основе большинства классов библиотеки MFC:


CObject -> CInternetSession

Кроме конструктора, в состав класса CInternetSession входят несколько методов, выполняющих разнообразные действия. Они позволяют определить и изменить характеристиками данного сеанса связи, открыть для чтения объект на указанном сервере Internet, установить соединение с серверами FTP, WWW и Gopher и т. д. В следующей таблице мы привели список этих методов:

Метод

Описание

CInternetSession

Конструктор класса CInternetSession

Close

Закрывает соединение с Internet. Вы должны вызвать этот метод после того, как вы закончите использовать объект CInternetSession

EnableStatusCallback

Управляет работой функции обратного вызова WinInet. Эта функция реализована как метод OnStatusCallback класса CInternetSession

GetContext

Определяет значение идентификатора контекста для данного сеанса связи

GetFtpConnection

Устанавливает сеанс связи с сервером FTP

GetGopherConnection

Устанавливает сеанс связи с сервером Gopher

GetHttpConnection

Устанавливает сеанс связи с сервером WWW

HINTERNET

Возвращает идентификатор текущего сеанса связи с Internet

OnStatusCallback

Данный метод вызывается когда изменяется состояние сеанса связи. Чтобы разрешить использование этой функции необходимо воспользоваться методом EnableStatusCallback

OpenURL

Открывает объект, расположенный по заданному адресу URL, для загрузки в локальный компьютер

QueryOption

Запрашивает различные характеристики соединения с Internet. Например время, по истечении которого, запрос отменяется в случае если на него не получен ответ, размеры буферов, используемых для чтения и записи и т. д. Вы можете менять все эти характеристики при помощи метода SetOption, также входящего в класс CInternetSession

ServiceTypeFromHandle

Определить тип сервиса (ftp, http, gopher, file), соответствующий данному идентификатору

SetOption

Устанавливает различные параметры сеанса связи с Internet. Чтобы узнать значение текущих параметров связи следует воспользоваться методом QueryOption

Рассмотрим более подробно конструктор класса и те его методы, которые будут нами использоваться в дальнейшем.

Конструктор класса CInternetSession

Конструктор класса CInternetSession имеет следующий прототип:


CInternetSession(
   LPCTSTR pstrAgent = NULL, 
   DWORD dwContext = 1,
   DWORD dwAccessType = PRE_CONFIG_INTERNET_ACCESS, 
   LPCTSTR pstrProxyName = NULL, 
   LPCTSTR pstrProxyBypass = NULL, 
   DWORD dwFlags = 0 
);

Посмотрите, как определен конструктор класса CInternetSession в исходных текстах библиотеки MFC. Вы найдете соответствующий программный код в файле Inet.cpp.

Конструктор класса CInternetSession вызывает единственную функцию программного интерфейса WinInet - InternetOpen, которая выполняет инициализацию WinInet.

Параметры конструктора класса CInternetSession передаются непосредственно функции InternetOpen:


m_dwContext = dwContext;
if (pstrAgent == NULL)
   pstrAgent = AfxGetAppName();

m_hSession = InternetOpen(pstrAgent, dwAccessType,
   pstrProxyName, pstrProxyBypass, dwFlags);

Вернемся теперь к обсуждению параметров конструктора. Все параметры конструктора класса CInternetSession являются необязательными и при создании объекта данного класса вы их можете не указывать.

Через параметр pstrAgent можно явным образом указать название приложения, или программного модуля, работающего с WinInet. Это название используется протоколом HTTP, и передается серверу в качестве имени пользовательского агента.

Если вызвать конструктор класса CInternetSession без параметров или указать в качестве параметра pstrAgent значение NULL, то конструктор самостоятельно определит имя приложения. Для этого конструктор использует глобальную функцию AfxGetAppName (см. фрагмент из файла Inet.cpp представленный выше).

Параметр dwContext определяет идентификатор контекста. Созданный объект будет ассоциироваться с данным идентификатором контекста.

Параметр dwAccessType определяет тип доступа к сети. Можно использовать одно из значений, перечисленных в следующей таблице:

Константа

Тип доступа

INTERNET_OPEN_TYPE_PRECONFIG

Используется тип доступа, указанный в регистрационной базе Windows

INTERNET_OPEN_TYPE_DIRECT

Прямой доступ к Internet

INTERNET_OPEN_TYPE_PROXY

Доступ через proxy сервер

Откройте Control Panel и выберите приложение Internet, которое предназначено для настройки различных параметров доступа к сети Internet

На экране появится диалоговая панель Internet Properties, состоящая из нескольких страниц (рис. 1.2). Выберите страницу Connection, отвечающую за подключение к Internet.

Рис. 1.2. Диалоговая панель Internet Properties

Если включен переключатель Connect to the Internet as needed в группе Dialing, значит ваш компьютер подключается к сети через модем с использованием Dial-Up Networking. Если включен переключатель Connect through a proxy server, значит вы подключены к сети через специальный proxy сервер. Настройки этого сервера вы можете просмотреть, нажав кнопку Setting. В случае, если оба эти переключателя отключены, значит вы подключены к сети напрямую.

Константы PRE_CONFIG_INTERNET_ACCESS и INTERNET_OPEN_TYPE_PRECONFIG определены в файле wininet.h. Ниже мы привели соответствующий фрагмент этого файла:


//
// access types for InternetOpen()
//

#define INTERNET_OPEN_TYPE_PRECONFIG   0   // use registry configuration
#define INTERNET_OPEN_TYPE_DIRECT      1   // direct to net
#define INTERNET_OPEN_TYPE_PROXY       3   // via named proxy

#define PRE_CONFIG_INTERNET_ACCESS  INTERNET_OPEN_TYPE_PRECONFIG
#define LOCAL_INTERNET_ACCESS       INTERNET_OPEN_TYPE_DIRECT
#define GATEWAY_INTERNET_ACCESS     2   // Internet via gateway
#define CERN_PROXY_INTERNET_ACCESS  INTERNET_OPEN_TYPE_PROXY

Как видите, значения констант PRE_CONFIG_INTERNET_ACCESS и INTERNET_OPEN_TYPE_PRECONFIG полностью совпадают.

Если тип доступа, определен параметром dwAccessType как INTERNET_OPEN_TYPE_PROXY, то через параметр pstrProxyName следует указать имя proxy сервера, а через параметр pstrProxyBypass - указатель на строку со списком адресов дополнительных серверов. Вы можете указать в качестве параметра pstrProxyBypass значение NULL. При этом список серверов будет взят из регистрационной базы данных Windows.

Если используются другие типы доступа, то в качестве параметра dwAccessType надо указать значение NULL. Параметр pstrProxyBypass в этом случае значения не имеет.

Последний параметр конструктора dwFlags определяет различные характеристики, перечисленные в следующей таблице:

Константа

Описание

INTERNET_FLAG_DONT_CACHE

Данные, получаемые WinInet из сети кэшируются в специальном каталоге на жестком диске локального компьютера. В случае если пользователь часто запрашивает у WinInet одни и те же файлы, то для ускорения они могут браться не из сети, а из кэша. Константа INTERNET_FLAG_DONT_CACHE запрещает кэшировть принимаемые данные

INTERNET_FLAG_ASYNC

Устанавливает асинхронный режим работы WinInet. Последующие операции с объектом могут завершится с ошибкой ERROR_IO_PENDING. Когда операция закончится, функция обратного вызова, будет вызвана с кодом INTERNET_STATUS_REQUEST_COMPLETE

INTERNET_FLAG_OFFLINE

Операции по загрузке информации выполняются только из кэша. В том случае, если запрашиваемая информация в кэше отсутствует, возвращается ошибка

Если соединение не может быть открыто, то конструктор класса CInternetSession вызывает исключение CInternetException с помощью глобальной функции AfxThrowInternetException. Мы расскажем о классе CInternetException, его методах и функции AfxThrowInternetException в разделе “Класс CInternetException”.

Метод OpenURL

Метод OpenURL выполняет различные действия для разных типов URL. Вы можете использовать метод OpenURL для доступа к серверу FTP:


CStdioFile* OpenURL( 
   LPCTSTR pstrURL, 
   DWORD dwContext = 1, 
   DWORD dwFlags = 0, 
   LPCTSTR pstrHeaders = NULL, 
   DWORD dwHeadersLength = 0 
);

throw ( CInternetException );

Первый параметр pstrURL является обязательным. Через него вы должны передать указатель на строку, содержащую адрес URL объекта. Метод OpenURL предназначен для получения доступа к серверам FTP, WWW, системе Gopher и файлам на локальном компьютере. Поэтому в качестве схемы доступа URL могут быть указаны только ftp:, gopher:, http: и file:.

Метод OpenURL возвращает указатель на объект класса CStdioFile, соответствующий заданному адресу URL. Заметим, что этот указатель может указывать на объекты различных классов, для которых класс CStdioFile является базовым. Класс объекта на который возвращает указатель метод OpenURL, зависит от типа URL.

Метод OpenURL выполняет разбор полученной им строки URL. Для этого используется уже описанный нами метод AfxParseURL (раздел “Глобальная функция AfxParseURL”).

Если метод OpenURL определяет, что в качестве параметра pstrURL вы указали URL файла на локальном компьютере, то он создает новый объект класса CStdioFile и возвращает указатель на него.

При создании объект класса CStdioFile указываются атрибуты CFile::modeRead и CFile::shareCompat. Поэтому файл открывается только для чтения в режиме совместимости. Любой другой процесс может открыть этот файл несколько раз. Операция вызывает ошибку, если файл уже открыт другим процессом в любом другом режиме кроме режима совместимости.

Если вы указали методу OpenURL строку URL со схемой доступа ftp:, gopher: или http:, то он устанавливает связь с соответствующим объектом, используя для этого функцию InternetOpenUrl из программного интерфейса WinInet.

Установив соединение с объектом URL, метод OpenURL создает новый объект класса CGopherFile, CInternetFile или CHttpFile, в зависимости от типа URL и возвращает указатель на этот объект:

Тип URL

Указатель на объект класса

file:

CStdioFile

http:

CHttpFile

gopher:

CGopherFile

ftp:

CInternetFile

Как видите, метод OpenURL может вернуть указатель на объекты класса CStdioFile, CGopherFile, CInternetFile или CHttpFile, используя указатель на объект класса CStdioFile. Такая многофункциональность метода OpenURL возможна благодаря тому, что класс CStdioFile является базовым классом для классов CGopherFile, CInternetFile и CHttpFile:


CFile -> CStdioFile -> CInternetFile -> CHttpFile 
                                     |
                                     -> CGopherFile

Если вы указали URL, не соответствующий схемам доступа ftp:, gopher:, http: и file:, тогда метод OpenURL вернет значение NULL. В режиме отладки также будет выдано сообщение.

Через параметр dwContext методу OpenURL можно передать идентификатор контекста. Этот идентификатор будет использован при вызове функции обратного вызова.

Параметр dwFlags может содержать набор констант (флагов), объединенных оператором ИЛИ. В следующей таблице мы привели краткие описания этих констант:

Константа

Описание

INTERNET_FLAG_RELOAD

Загрузить данные из сети, даже если они уже получены и записаны в кэше

INTERNET_FLAG_DONT_CACHE

Не выполнять кэширование принимаемых данных

INTERNET_FLAG_SECURE

Используется при передаче запросов HTTP с использованием Secure Sockets Layer или PCT

INTERNET_OPEN_FLAG_USE_EXISTING_CONNECT

Указывает использовать установленное соединение с сервером для новых запросов, передаваемых методом OpenUrl. В противном случае каждый последующий вызов OpenUrl будет создавать новвый сеанс связи

INTERNET_FLAG_PASSIVE

Используется при работе с серверами FTP. Выполняется пассивное соединение с сервером. Более подробное описание смотрите в документации к Microsoft Visual C++

Когда вы вызываете метод OpenURL, вы можете указать дополнительный заголовок запроса HTTP, передаваемый серверу. Дополнительный заголовок может быть представлен в формате RFC822, MIME или HTTP.

По умолчанию дополнительный заголовок не указывается. Указатель на строку, содержащую дополнительный заголовок запроса HTTP, передается через параметр pstrHeaders.

Длина дополнительного заголовка передается методу OpenURL через параметр dwHeadersLength. Если вы передаете заголовок в строке, заканчивающейся двоичным нулем, то достаточно указать в качестве параметра dwHeadersLength значение -1L.

Метод OpenURL предназначен для загрузки объектов из сети. Он не выполняет операции, специфические для протоколов FTP, HTTP, Gopher. Для этих целей вы должны использовать другие классы (чтобы открыть соединение определенного вида).

Метод GetFtpConnection

Метод GetFtpConnection выполняет соединение с заданным сервером FTP. При этом он создает соответствующий объект класса CFTPConnection, который будет представлять соединение с данным сервером. Это, кстати, единственный способ, который рекомендуется использовать для создания объектов класса CFtpConnection. Нельзя создавать объекты этого класса, напрямую обращаясь к его конструктору.

После того как вы соединились с сервером FTP и объект класса CFtpConnection создан, вы можете вызывать для него методы этого класса чтобы выполнять различные операции с сервером. Так, например, при помощи метода OpenFile вы можете открыть файл, расположенный на сервере FTP для последующего чтения или записи.

Метод GetFtpConnection имеет множество различных параметров. Однако только первый параметр вы должны будете указать в обязательном порядке. Остальные параметры можно опустить. В этом случае для них будут использоваться значения, принятые по умолчанию, которые подходят в большинстве случаев. Ниже представлен прототип метода GetFtpConnection:


CFtpConnection* 
GetFtpConnection( 
   LPCTSTR pstrServer, 
   LPCTSTR pstrUserName = NULL, 
   LPCTSTR pstrPassword = NULL, 
   INTERNET_PORT nPort = INTERNET_INVALID_PORT_NUMBER, 
   BOOL bPassive = FALSE 
); 

throw( CInternetException );

Как мы уже говорили, метод GetFtpConnection создает объект класса CFtpConnection и возвращает указатель на него. Если в ходе соединения с сервером FTP возникнут какие-либо проблемы, например сервера FTP, который вы указали, вообще не существует в сети или он не активен в настоящее время, тогда метод GetFtpConnection может вызвать исключение CInternetException. Обработав данное исключение, вы сможете определить причины ошибки.

Рассмотрим теперь более подробно параметры метода.

Наиболее важный параметр pstrServer. Через него вы передаете методу GetFtpConnection адрес сервера, с которым необходимо установить соединение. Вполне естественно, что этот параметр является обязательным (конечно, корпорация Microsoft могла бы предусмотреть и для этого параметра значение по умолчанию, например ftp://ftp.microsoft.com).

Следующие два параметра pstrUserName и pstrPassword задают имя и пароль, под которым выполняется соединение с сервером FTP. Если вы не укажете имя, то по умолчанию используется anonymous. Если имя не указано, то пароль также не должен задаваться. В этом случае в качестве пароля для соединения с сервером WinInet будет использовать адрес вашей электронной почты.

Заметим, что если вы указали имя lpszUsername, то это не означает, что вы должны обязательно задавать и пароль. В случае если имя задано, а пароль нет (через параметр lpszPassword передается значение NULL или параметр не используется совсем), то в качестве пароля используется пустая строка.

Следующий параметр метода GetFtpConnection - nPort. Он определяет номер порта TCP/IP который используется сервером FTP для соединения. По умолчанию в качестве этого параметра используется значение INTERNET_INVALID_PORT_NUMBER. В этом случае метод GetFtpConnection использует при соединении с сервером FTP стандартный для него порт номер 21.

Последний параметр метода - bPassive определяет режим работы с сервером FTP. Если параметр bPassive содержит значение TRUE, то выполняется пассивное соединение с сервером.

Метод GetHttpConnection

Метод GetHttpConnection имеет сходное название с методом GetFtpConnection, и служит для соединения с сервером WWW. Для этого он создает объект класса CHttpConnection, который будет представлять соединение с сервером WWW.

Заметим, что в отличие от ранее рассмотренного метода GetFtpConnection, метод GetHttpConnection не выполняет соединения с сервером в полном смысле этого слова. Физическое соединение в сети не устанавливается. Отсюда, кстати следует, что даже если вы укажите данному методу адрес несуществующего сервера WWW, он не заметит подвоха, послушно установит “соединение” и создаст объект CHttpConnection.

Фактическое соединение с сервером WWW произойдет несколько позже, когда вы будете передавать запросы серверу, используя методы класса CHttpConnection.

Ниже мы привели прототип метода GetHttpConnection:


CHttpConnection* 
GetHttpConnection( 
   LPCTSTR pstrServer, 
   INTERNET_PORT nPort = INTERNET_INVALID_PORT_NUMBER, 
   LPCTSTR pstrUserName = NULL, 
   LPCTSTR pstrPassword = NULL 
);

throw( CInternetException );

Только первый параметр метода GetHttpConnection является обязательным. Он задает адрес сервера WWW с которым надо соединиться. Второй параметр - nPort - задает имя порта TCP/IP, который используется сервером WWW для соединения со своими клиентами.

По умолчанию в качестве параметра nPort используется значение INTERNET_INVALID_PORT_NUMBER. В этом случае метод GetHttpConnection использует порт номер 80, стандартный для серверов WWW.

Последние два параметра метода GetHttpConnection - pstrUserName и pstrPassword задают имя пользователя и пароль, под которым ваше приложение будет соединятся с сервером WWW.

Метод GetHttpConnection создает объект класса CHttpConnection и возвращает указатель на него. В случае возникновения ошибок, метод GetHttpConnection может вызвать исключение CInternetException, которое вы должны обрабатывать в своем приложении.

Метод EnableStatusCallback

Чтобы разрешить программному интерфейсу WinInet вызывать метод OnStatusCallback, необходимо воспользоваться методом EnableStatusCallback, прототип которого мы представили ниже:


BOOL 
EnableStatusCallback( BOOL bEnable = TRUE );

throw ( CInternetException );

Метод EnableStatusCallback имеет только один параметр, который разрешает или запрещает использование метода OnStatusCallback. По умолчанию параметр bEnable содержит значение TRUE, которое разрешает его использование.

Метод EnableStatusCallback возвращает ненулевое значение в случае успешного завершения или ноль в случае ошибки. Данный метод может вызывать исключение CInternetException. Вы можете определить причину исключения, воспользовавшись методами класса CInternetException.

Метод OnStatusCallback

Виртуальный метод OnStatusCallback класса CInternetSession вызывается программным интерфейсом WinInet и информирует приложение о состоянии связи.

Если вы желаете использовать метод OnStatusCallback, вы должны наследовать от класса CInternetSession новый класс, в котором следует переназначить метод OnStatusCallback. Затем вы должны вызвать метод EnableStatusCallback и разрешить использование метода OnStatusCallback.

Прототип метода OnStatusCallback мы привели ниже:


virtual void 
OnStatusCallback( 
   DWORD dwContext, 
   DWORD dwInternetStatus, 
   LPVOID lpvStatusInformation, 
   DWORD dwStatusInformationLength 
);

Через параметр dwContext методу OnStatusCallback передается идентификатор контекста операции о состоянии которой информируется приложение. Параметр dwInternetStatus содержит код состояния. По нему вы можете определить причину вызова метода. Дополнительная информация передается в буфере, по адресу lpvStatusInformation. Размер этого буфера передается в параметре dwStatusInformationLength. Ниже представлены возможные значение параметра dwInternetStatus:

INTERNET_STATUS_RESOLVING_NAME

Определяет IP-адрес имени, записанного в параметре lpvStatusInformation.

INTERNET_STATUS_NAME_RESOLVED

В буфере lpvStatusInformation находится IP-адрес сервера, имя которого вы указали.

INTERNET_STATUS_CONNECTING_TO_SERVER

Выполняется соединение по адресу сокета, указанного в буфере lpvStatusInformation.

INTERNET_STATUS_CONNECTED_TO_SERVER

Установлено соединение по адресу сокета, указанного в буфере lpvStatusInformation.

INTERNET_STATUS_SENDING_REQUEST

Передается информационный запрос на сервер. Параметр lpvStatusInformation не используется.

INTERNET_STATUS_REQUEST_SENT

Информационный запрос передан на сервер. Параметр lpvStatusInformation не используется.

INTERNET_STATUS_RECEIVING_RESPONSE

Ожидает ответ на запрос, переданный серверу. Параметр lpvStatusInformation не используется.

INTERNET_STATUS_RESPONSE_RECEIVED

Получен ответ на запрос, переданный серверу. Параметр lpvStatusInformation не используется.

INTERNET_STATUS_CLOSING_CONNECTION

Соединение с сервером закрывается. Параметр lpvStatusInformation не используется.

INTERNET_STATUS_CONNECTION_CLOSED

Соединение с сервером закрыто. Параметр lpvStatusInformation не используется.

INTERNET_STATUS_HANDLE_CREATED

Функция InternetConnect из программного интерфейса WinInet создала новый идентификатор.

INTERNET_STATUS_HANDLE_CLOSING

Данный идентификатор удален.

INTERNET_STATUS_REQUEST_COMPLETE

Асинхронная операция завершена. Параметр lpvStatusInformation содержит значение NULL, но параметр dwStatusInformationLength используется. Он содержит код завершения асинхронной операции.

Если параметр dwStatusInformationLength содержит значение ERROR_INTERNET_EXTENDED_ERROR, вы можете получить дополнительную информацию об ошибке, обратившись к функции InternetGetLastResponseInfo.

Если параметр dwStatusInformationLength имеет значение INTERNET_STATUS_REQUEST_COMPLETE, тогда параметр lpvStatusInformation содержит указатель на структуру типа INTERNET_ASYNC_RESULT.

Данная структура определена в файле wininet.h следующим образом:


typedef struct {
    DWORD dwResult; // код завершения операции
    DWORD dwError;  // код ошибки
} INTERNET_ASYNC_RESULT, * LPINTERNET_ASYNC_RESULT;

В поле dwResult находится код завершения операции. Если во время выполнения операции возникла ошибка, тогда в поле dwError будет записан код ошибки. Если операция завершилась успешно, в поле dwError записана константа ERROR_SUCCESS.

¨     В том случае если вы используете библиотеку MFC в виде библиотеки dll, необходимо добавить в самом начале переопределенного вами метода OnStatusCallback строку следующего вида:


AFX_MANAGE_STATE( AfxGetStaticModuleState() );

Метод QueryOption

Метод QueryOption, позволяет определить различные характеристики сеанса связи. В состав класса CInternetSession входят два метода QueryOption, которые имеют различные параметры. Ниже мы привели прототипы этих методов:


BOOL 
QueryOption( 
   DWORD dwOption, 
   LPVOID lpBuffer, 
   LPDWORD lpdwBufLen 
) const;
  
BOOL 
QueryOption( 
   DWORD dwOption, 
   DWORD& dwValue 
) const;

В обоих прототипах метода QueryOption первый параметр dwOption типа DWORD определяет информацию, которую надо получить. Через параметр lpBuffer вы должны передать методу QueryOption указатель на буфер, а через параметр lpdwBufLen - размер этого буфера. Метод QueryOption помещает запрашиваемую информацию в буфер lpBuffer, а в lpdwBufLen записывает ее длину.

Если вы используете второй прототип метода QueryOption, то вместо буфера lpBuffer указываться переменная типа DWORD, адрес которой передается через параметр dwValue.

Некоторые наиболее интересные константы, используемые в качестве параметра dwOption, описаны ниже.

INTERNET_OPTION_CALLBACK

Адрес функции обратного вызова, установленной для данного сеанса.

INTERNET_OPTION_CONNECT_TIMEOUT

Время, отведенное на установление соединения. Задается в миллисекундах. Если соединение не устанавливается в течении данного времени, оно отменяется. По умолчанию время на соединение никак не ограничено.

INTERNET_OPTION_CONNECT_RETRIES

Количество попыток соединения. В случае неудачной попытки соединения выполняется соответствующее количество повторных попыток. По умолчанию выполняется 5 попыток.

INTERNET_OPTION_CONNECT_BACKOFF

Задержка в миллисекундах между повторными попытками соединения.

INTERNET_OPTION_CONTROL_SEND_TIMEOUT

Время, отведенное для передачи запроса, не связанного с передачей данных. Задается в миллисекундах. По умолчанию время на передачу запроса не ограничено

INTERNET_OPTION_CONTROL_RECEIVE_TIMEOUT

Время, отведенное для приема запроса, не связанного с получением данных. Задается в миллисекундах. По умолчанию время на прием запроса не ограничено.

INTERNET_OPTION_DATA_SEND_TIMEOUT

Время, отведенное для передачи запроса с данными. Задается в миллисекундах. По умолчанию время на передачу запроса не ограничено.

INTERNET_OPTION_DATA_RECEIVE_TIMEOUT

Время, отведенное для запроса на прием данных. Задается в миллисекундах. По умолчанию время на прием запроса не ограничено.

INTERNET_OPTION_HANDLE_TYPE

Тип идентификатора Internet, например INTERNET_HANDLE_TYPE_CONNECT_FTP или INTERNET_HANDLE_TYPE_HTTP_REQUEST.

INTERNET_OPTION_CONTEXT_VALUE

Идентификатор контекста, связанный с данным идентификатором Internet.

INTERNET_OPTION_READ_BUFFER_SIZE

Размер буфера, используемого для чтения данных с сервера FTP.

INTERNET_OPTION_WRITE_BUFFER_SIZE

Размер буфера, используемого для передачи данных на сервер FTP.

INTERNET_OPTION_ASYNC_ID

Идентификатор последнего асинхронного запроса, который выполнен в данной задаче.

INTERNET_OPTION_ASYNC_PRIORITY

Приоритет асинхронной операции загрузки данных.

INTERNET_OPTION_PARENT_HANDLE

Родительский идентификатор.

INTERNET_OPTION_KEEP_CONNECTION

Определяет, используется ли данным идентификатором уже существующее соединение.

INTERNET_OPTION_USERNAME

Имя пользователя, связанное с идентификатором, который возвращает функция InternetConnect из программного интерфейса WinInet.

INTERNET_OPTION_PASSWORD

Пароль, связанный с идентификатором, который возвращает функция InternetConnect из программного интерфейса WinInet.

INTERNET_OPTION_REQUEST_FLAGS

Информация о текущем процессе загрузки. Если загрузка идет из кэш-памяти, то возвращается флаг INTERNET_REQFLAG_FROM_CACHE.

INTERNET_OPTION_EXTENDED_ERROR

Код ошибки программного интерфейса Winsock, который вызвал ошибку ERROR_INTERNET_ в данной задаче приложения.

Если метод QueryOption завершился без ошибок, он возвращает значение TRUE. В противном случае возвращается значение FALSE. Причину ошибки можно определить, обратившись к функции GetLastError.

Метод SetOption

Метод SetOption позволяет установить различные характеристики сеанса связи. Прототип метода SetOption практически полностью соответствует прототипу метода QueryOption:


BOOL 
SetOption( 
   DWORD dwOption, 
   LPVOID lpBuffer, 
   DWORD dwBufferLength 
);
  
BOOL 
SetOption( 
   DWORD dwOption, 
   DWORD dwValue 
);

Метод Close

Одно приложение может создать несколько объектов класса CInternetSession. Объект CInternetSession должен существовать на протяжении всего сеанса связи с Internet. Когда вам понадобится завершить работу с Internet, вызовите для объекта CInternetSession виртуальный метод Close, определенный в классе CInternetSession:


virtual void Close();

Следует отметить, что деструктор класса CInternetSession сам вызывает метод Close.

Класс CInternetException

Для обработки ошибок, возникающих при работе с WinInet, в состав библиотеки MFC включен новый класс CInternetException. Точно также как и другие классы MFC, предназначенные для обработки различных исключительных ситуаций, класс CInternetException наследован от базового класса CException:


CObject -> CException -> CInternetException

Элементы данных класса CInternetException

Класс CInternetException содержит два элемента данных - m_dwError и m_dwContext. Они позволяют узнать код ошибки и идентификатор контекста операции, ставшей причиной вызова исключения.

Код ошибки содержится в элементе данных m_dwError. Причина вызова исключения может быть не связана с WinInet напрямую. В этом случае в качестве кода ошибки m_dwError будет фигурировать один из кодов ошибок Win32. Их список вы найдете в документации Visual C++.

Список кодов ошибок, связанных с WinInet, вы можете найти в документации по ActiveX SDK, а также в Internet по следующему адресу: http:\\www.microsoft.com/intdev. Ниже мы перечислили для примера несколько таких кодов и дали им краткие описания:

Код ошибки

Описание

ERROR_INTERNET_TIMEOUT

Время, отведенное на выполнение запроса истекло

ERROR_INTERNET_INTERNAL_ERROR

Внутренняя ошибка WinInet

ERROR_INTERNET_LOGIN_FAILURE

Неудачная попытка соединения с сервером FTP

ERROR_FTP_DROPPED

Операция с сервером FTP не завершена из за разрыва сеанса связи

Обработка исключения CInternetException

В приложениях, которые представлены в этой книге, используется ряд методов, которые могут вызвать исключение CInternetException. Мы организуем обработку этих исключений с помощью блоков try и catch. В блок try заключаются методы, способные вызвать исключение CInternetException, а ниже помещается блок catch для обработки этого исключения:


try
{
   // Вызов метода, который может стать причиной исключения
   . . .
}
catch (CInternetException* pEx)
{
   // Обрабатываем исключение CInternetException
   TCHAR szErr[1024];
   if (pEx->GetErrorMessage(szErr, 1024))
      AfxMessageBox(szErr);
   else
      AfxMessageBox("GetFtpConnection Error");

   // Удаляем исключение
   pEx->Delete();
}

Во всех наших примерах обработчики исключения CInternetException выполняют примерно одни и те же действия. Сначала определяется причина, вызвавшая исключение. Для этой цели вызывается метод GetErrorMessage. Этот метод записывает текстовое сообщение об ошибке в буфер, указанный первым параметром. Размер буфера должен быть указан во втором параметре метода. Если текстовое описание ошибки недоступно, тогда метод GetErrorMessage возвращает нулевое значение и мы отображаем на экране свое собственное сообщение об ошибке.

В завершение блока catch мы удаляем уже обработанное исключение, для чего вызываем метод Delete. Описание этого метода вы не обнаружите в справочной системе, что однако не мешает использовать его в своих приложениях. Если вы не удалите исключение, то по завершении приложения отладчик сообщит вам о наличии неосвобожденных областей памяти.

¨     Обратите внимание, что надо использовать именно метод Delete, а не оператор delete, название которого начинается с маленькой буквы.

Как вызвать исключение CInternetException - функция AfxThrowInternetException

Чтобы принудительно вызвать исключение CInternetException из своего приложения воспользуйтесь глобальной функцией AfxThrowInternetException:


void AFXAPI AfxThrowInternetException( 
   DWORD dwContext, 
   DWORD dwError = 0 
);

Функции AfxThrowInternetException передаются два параметра. Через параметр dwError передается код ошибки, а через параметр dwContext - идентификатор контекста операции, вызвавшей ошибку. По умолчанию в качестве кода ошибки используется нулевое значение. В этом случае функция AfxThrowInternetException определяет код ошибки самостоятельно, обращаясь к функции GetLastError программного интерфейса Windows.

Функция AfxThrowInternetException создает объект класса CInternetException, присваивает элементам m_dwError и m_dwContext этого объекта значения, полученные через параметры dwContext и dwError и вызывает исключение.

В режиме отладки данная функция выводит в окне Debug сообщение о вызове исключения CInternetException с соответствующим кодом ошибки - "Warning: throwing CInternetException for error...".

Класс CInternetConnection

Класс CInternetConnection управляет наиболее общими характеристиками соединения с серверами Internet. Если приложению требуется использовать расширенный сервис серверов FTP, HTTP и системы Gopher, воспользуйтесь классами CFtpConnection, CHttpConnection и CGopherConnection. Эти классы наследуются от базового класса CInternetConnection, добавляя к нему набор специфических методов. Сам класс CInternetConnection наследуется от базового класса CObject:


CObject -> CInternetConnection -> CFtpConnection 
                               |
                               -> CHttpConnection 
                               |
                               -> CGopherConnection

В состав класса CInternetConnection, кроме конструктора, входят три метода GetContext, GetSession, GetServerName и оператор HINTERNET.

Все методы класса CInternetConnection предназначены для определения параметров соединения с сервером. Метод GetContext позволяет узнать идентификатор контекста объекта, представляющего соединение. Метод GetSession определяет объект класса CInternetSession, в рамках которого установлено соединение с сервером. Метод GetServerName возвращает имя сервера.

Оператор HINTERNET не представляет особого интереса и позволяет узнать идентификатор сеанса связи с Internet. Он используется, если в вашем приложении одновременно применяются классы MFC, управляющие WinInet и функции программного интерфейса WinInet.

Мы не будем напрямую вызывать методы класса CInternetConnection в своих приложениях и поэтому не станем останавливаться на них более подробно и рассмотрим только оператор HINTERNET, так как он входит во многие другие классы WinInet.

Оператор HINTERNET

Как мы упоминали, конструктор класса CInternetSession вызывает функцию InternetOpen из программного интерфейса WinInet чтобы выполнить инициализацию библиотеки WinInet и создать новый сеанс связи с Internet. Функция InternetOpen возвращает идентификатор типа HINTERNET, который используется при последующих вызовах функций WinInet.

Когда вы используете библиотеку MFC, вы можете определить идентификатор сеанса, воспользовавшись оператором HINTERNET, который входит в состав класса CInternetSession:


operator HINTERNET() const;

Класс CFtpConnection

Класс CFtpConnection наследуется от базового класса CInternetConnection:


CObject -> CInternetConnection -> CFtpConnection

Класс CFtpConnection предназначен для соединения с серверами FTP. Методы этого класса позволяют приложению обмениваться файлами с сервером FTP, а также выполнять различные сервисные операции, такие как создание и удаление каталогов, переименование и удаление файлов и т. д.

Для класса CFtpConnection определен конструктор класса, но вам никогда не потребуется обращаться к нему напрямую. Объект CFtpConnection создается косвенно при вызове метода GetFtpConnection для объекта класса CInternetSession:


// Определяем указатель на объект класса CFtpConnection
CFtpConnection*  m_FtpConnection = NULL;
         
// Пытаемся соединиться с сервером sServer
m_FtpConnection = 
   m_InternetSession -> GetFtpConnection( sServer );

Метод Close закрывает соединение с сервером FTP. Вы должны вызвать этот метод после завершения работы с объектом CFtpConnection. В принципе, вызов метода Close можно совсем опустить. В этом случае соединение будет разорвано автоматически деструктором класса CFtpConnection.

Работа со структурой каталогов сервера FTP

Среди методов класса CFtpConnection можно выделить группу методов, ориентированных на работу со структурой каталогов сервера FTP. В следующей таблице мы представили краткие описания этих методов:

Метод

Описание

SetCurrentDirectory

Позволяет перейти в заданный каталог на сервере FTP

GetCurrentDirectory

Определяет имя текущего каталога на сервере FTP. Смотри также метод GetCurrentDirectoryAsURL

GetCurrentDirectoryAsURL

Определяет адрес URL текущего каталога на сервере FTP

RemoveDirectory

Удаляет определенный каталог с сервера FTP

CreateDirectory

Создает на сервере FTP новый каталог

Рассмотрим для примера методы GetCurrentDirectory и GetCurrentDirectoryAsURL. Другие методы, предназначенные для работы со структурой каталогов сервера FTP, вы можете изучить самостоятельно.

Метод GetCurrentDirectory

Метод GetCurrentDirectory позволяет определить имя текущего каталога на сервере FTP. В состав класса CFtpConnection входят два метода GetCurrentDirectory, имеющие различный набор параметров.

Прототип метода GetCurrentDirectory с одним параметром представлен ниже. Как видите, этому методу передается ссылка на строку strDirName. В нее метод GetCurrentDirectory записывает имя текущего каталога сервера:


BOOL GetCurrentDirectory( CString& strDirName ) const;

В случае успешного завершения метод GetCurrentDirectory возвращает ненулевое значение и ноль в случае ошибки. Чтобы определить причину возникшей ошибки можно воспользоваться функцией GetLastError.

Другой метод GetCurrentDirectory имеет два параметра. Параметр pstrDirName должен содержать указатель на буфер, в который будет записано имя текущего каталога. Размер этого буфера вы должны записать в переменную типа DWORD и передать указатель на него через параметр lpdwLen:


BOOL GetCurrentDirectory( 
   LPTSTR pstrDirName, 
   LPDWORD lpdwLen 
) const;

В случае успешного завершения метод GetCurrentDirectory возвращает ненулевое значение, а в переменную по адресу lpdwLen записывает длину строки с именем каталога.

Метод GetCurrentDirectoryAsURL

В класс CFtpConnection входят два метода GetCurrentDirectoryAsURL, различающиеся своими парамтерами, которые позволяют определить текущий каталог на сервере FTP в формате URL. Прототипы этих методов мы привели ниже:


BOOL GetCurrentDirectoryAsURL( CString& strDirName ) const;
  
BOOL GetCurrentDirectoryAsURL( 
   LPTSTR pstrDirName, LPDWORD lpdwLen 
) const;

Назначение параметров представленных выше методов GetCurrentDirectoryAsURL полностью соответствует уже описанным нами методам GetCurrentDirectory, за исключением того, что эти методы определяют текущий каталог в формате URL.

Работа с файлами

Другая группа методов класса CFtpConnection предназначена для работы с файлами:

Метод

Описание

Rename

Переименовывает файл, находящийся на сервере FTP

Remove

Удаляет файл с сервера FTP

PutFile

Записывает файл на сервер

GetFile

Позволяет загрузить определенный файл с сервера FTP

OpenFile

Открывает файл, расположенный на сервере FTP для последующего чтения или записи

Еще один метод, который входит в состав класса CFtpConnection - Close. Этот метод закрывает соединение с сервером FTP, для чего он вызывает метод Close класса CInternetConnection. Деструктор класса CFtpConnection закрывает соединение с сервером даже если вы не вызвали метод Close.

Мы рассмотрим только три метода для работы с файлами. Это методы GetFile, PutFile и OpenFile. Описание остальных методов вы найдете в справочной системе Microsoft Visual C++.

Метод GetFile

Метод GetFile копирует файл с сервера FTP на диск локального компьютера. При этом вы фактически не имеете никакой возможности следить за процессом копирования. Если вы должны знать, какая часть файла скопирована в данный момент, то вместо метода GetFile надо использовать пару методов - метод OpenFile класса CFtpConnection и метод Read класса CInternetFile. Сначала надо открыть файл на сервере FTP при помощи метода OpenFile, а затем считывать из него данные с помощью метода Read. Мы продемонстрируем оба этих метода получения файла с сервера FTP в разделе “Загрузка файлов с сервера FTP”.

Ниже мы привели прототип метода GetFile:


BOOL GetFile( 
   LPCTSTR pstrRemoteFile, 
   LPCTSTR pstrLocalFile, 
   BOOL bFailIfExists = TRUE, 
   DWORD dwAttributes = FILE_ATTRIBUTE_NORMAL, 
   DWORD dwFlags = FTP_TRANSFER_TYPE_BINARY, 
   DWORD dwContext = 1 
);

Имя файла на сервере, который надо получить, передается методу GetFile через параметр pstrRemoteFile, а имя файла на диске локального компьютера - через параметр pstrLocalFile. Вы должны обязательно задать только эти два параметра. Остальные параметры имеют значения, принимаемые по умолчанию, и могут не указываться.

Параметр bFailIfExists определяет действие метода GetFile в случае, если в качестве параметра pstrLocalFile вы указали имя файла, который уже существует на диске локального компьютера. Если вы укажете в качестве параметра bFailIfExists значение TRUE или опустите этот параметр, тогда метод GetFile завершится с ошибкой. Если же параметр bFailIfExists равен FALSE то файл на локальном диске будет перезаписан. Предварительно у пользователя запрашивается разрешение на перезапись файла.

Метод GetFile позволяет выбрать атрибуты для файла, который создается на локальном диске компьютера. Эти атрибуты передаются методу через параметр dwAttributes.

Атрибут

Описание

FILE_ATTRIBUTE_NORMAL

Нормальный файл

FILE_ATTRIBUTE_READONLY

Файл, который можно открыть только для чтения

FILE_ATTRIBUTE_HIDDEN

Скрытый файл

FILE_ATTRIBUTE_SYSTEM

Системный файл

FILE_ATTRIBUTE_TEMPORARY

Временный файл

FILE_ATTRIBUTE_COMPRESSED

Компрессованый файл

FILE_ATTRIBUTE_DIRECTORY

Каталог

FILE_ATTRIBUTE_ARCHIVE

Архивный файл

В случае успешного завершения метод GetFile возвращает ненулевое значение. Если метод завершился с ошибкой, то он возвращает ноль, а причину ошибки можно узнать с помощью функции GetLastError.

Метод передачи данных с сервера FTP на локальный компьютер можно задавать через параметр dwFlags. Если вам надо передать двоичный файл без всяких перекодировок, укажите в качестве этого параметра значение FTP_TRANSFER_TYPE_BINARY (метод FTP Image - тип I).

Если вам надо принять только текстовые данные, то вы можете использовать для этого параметра значение FTP_TRANSFER_TYPE_ASCII. При этом выполняется перекодировка данных в зависимости от программного обеспечения, установленного на сервере (метод FTP ASCII - тип A).

Идентификатор контекста для операции загруки файла можно указать в параметре dwContext. По умолчанию в качестве идентификатора контекста используется значение 1.

Метод PutFile

По сравнению с методом GetFile, метод PutFile выполняет обратную задачу. Он позволяет записать файл с локального компьютера на сервер FTP. Также как и метод GetFile, этот метод не позволяет контролировать или вмешиваться в процесс загрузки.

Если вы желаете иметь более полный контроль за загрузкой файла на сервер, вы должны использовать вместо метода PutFile два метода - метод OpenFile класса CFtpConnection и метод Write класса CInternetFile.

Метод OpenFile открывает и создает файл на сервере FTP, а метод Write позволяет записывать в него порции данных из буфера на локальном компьютере. Приведем прототип метода PutFile:


BOOL PutFile( 
   LPCTSTR pstrLocalFile, 
   LPCTSTR pstrRemoteFile, 
   DWORD dwFlags = FTP_TRANSFER_TYPE_BINARY, 
   DWORD dwContext = 1 
);

Параметр pstrLocalFile указывает имя файла, записанного на локальном компьютере, который передается на сервер FTP и записывается в файл, определенный параметром pstrRemoteFile.

Параметр dwFlags определяет метод передачи файла, а параметр dwContext - идентификатор контекста. Назначение этих параметров полностью соответствует соответствующим параметрам метода GetFile.

Метод OpenFile

Если методы GetFile и PutFile вас не устраивают, потому что вы не получаете в этом случае достаточный контроль за передачей и приемом файла или если надо выполнить обмен данными между файлами на сервере FTP и оперативной памятью локального компьютера, то вы можете сначала открыть файл при помощи метода OpenFile, а затем считывать из него или записывать в него данные непосредственно из буфера на локальном компьютере при помощи методов Read и Write класса CInternetFile.

Метод OpenFile возвращает указатель на объект класса CInternetFile. Впоследствии вы можете использовать методы класса CInternetFile чтобы выполнять чтение из соответствующего файла или запись.

Приведем прототип метода OpenFile:


CInternetFile* OpenFile( 
   LPCTSTR pstrFileName, 
   DWORD dwAccess = GENERIC_READ, 
   DWORD dwFlags = FTP_TRANSFER_TYPE_BINARY, 
   DWORD dwContext = 1 
);

Имя файла, который надо открыть, передается методу OpenFile через параметр pstrFileName.

Режим, в котором открывается файл, задается параметром dwAccess. Если файл открывается для чтения, то в качестве параметра dwAccess используется значение GENERIC_READ, а если для записи - GENERIC_WRITE.

Параметр dwFlags определяет метод передачи файла, а параметр dwContext - идентификатор контекста. Назначение этих параметров полностью соответствует соответствующим параметрам методов GetFile и PutFile.

После того, как вы открыли файл на сервере, вы можете обращаться только к методам Read, Write и Close класса CInternetFile, а также метод FindFile класса CFtpFileFind. До тех пор, пока файл не будет закрыт, вы не сможете вызвать другие методы для данного сеанса связи с сервером FTP. В противном случае они будут завершаться с ошибкой, имеющий код FTP_ETRANSFER_IN_PROGRESS.

Класс CHttpConnection

Класс CHttpConnection позволяет приложению взаимодействовать с сервером WWW. Этот класс наследуется от базового класса CInternetConnection:


CObject -> CInternetConnection -> CHttpConnection

Кроме конструктора в состав класса CHttpConnection входит только один метод OpenRequest, который устанавливает соединение с сервером HTTP.

Конструктор класса CHttpConnection никогда не вызывается напрямую. Объект класса CHttpConnection создается при вызове метода GetHttpConnection класса CInternetSession. Поэтому мы опустим описание конструктора класса и сразу перейдем к методу OpenRequest.

Метод OpenRequest

Метод OpenRequest создает запрос для передачи его серверу WWW. После того, как запрос создан, его можно модифицировать при помощи метода AddRequestHeaders класса CHttpFile, а затем передать серверу, вызвав метод SendRequest, входящий в состав класса CHttpFile.

Определены два варианта метода OpenRequest. Ниже мы привели для вас их прототипы:


CHttpFile* OpenRequest( 
   LPCTSTR pstrVerb, 
   LPCTSTR pstrObjectName, 
   LPCTSTR pstrReferer = NULL, 
   DWORD dwContext = 1, 
   LPCTSTR* pstrAcceptTypes = NULL, 
   LPCTSTR pstrVersion = NULL, 
   DWORD dwFlags = INTERNET_FLAG_EXISTING_CONNECT 
);
  
CHttpFile* OpenRequest( 
   int nVerb, 
   LPCTSTR pstrObjectName, 
   LPCTSTR pstrReferer = NULL, 
   DWORD dwContext = 1, 
   LPCTSTR* pstrAcceptTypes = NULL, 
   LPCTSTR pstrVersion = NULL,  
   DWORD dwFlags = INTERNET_FLAG_EXISTING_CONNECT 
);

Представленные варианты метода OpenRequest отличаются только типом первого параметра. Этот параметр определяет команду, которая передается в запросе.

В первом варианте метода OpenRequest параметр pstrVerb должен содержать указатель на строку с командой в текстовом виде. Если использовать в качестве pstrVerb значение NULL, то по умолчанию передается команда "GET". Вы можете использовать команды, предоставленные в следующей таблице:

Команды

Описание

POST

Передать запрос на сервер, содержащий дополнительные данные. Это может быть, например, обращение к расширению CGI или ISAPI в котором ему передаются данные из формы, заполненной пользователем

GET

Запрос на получение объекта с сервера WWW

HEAD

Запрос на получение информации об объекте с сервера WWW. Сам объект не принимается

PUT

Записать данный объект на сервер по определенному адресу URL

LINK

Устанавливает связь между ресурсом, идентифцируемом адресом URL и другими ресурсами

DELETE

Предлагает серверу удалить ресурс по данному адресу URL

UNLINK

Удалляет связи ресурса с указанным адресом URL

¨     Отметим, что обычно используются только команды GET, HEAD и PUT

Во втором варианте метода OpenRequest параметр nVerb имеет целочисленный тип. В этом случае для задания команды вы должны использовать константы, представленные в следующей таблице.

Команда

Константа

POST

HTTP_VERB_POST

GET

HTTP_VERB_GET

HEAD

HTTP_VERB_HEAD

PUT

HTTP_VERB_PUT

LINK

HTTP_VERB_LINK

DELETE

HTTP_VERB_DELETE

UNLINK

HTTP_VERB_UNLINK

Эти константы определены в классе CHttpConnection следующим образом:


class CHttpConnection : public CInternetConnection
{
public:
   enum {
      _HTTP_VERB_MIN      = 0,
      HTTP_VERB_POST      = 0,
      HTTP_VERB_GET       = 1,
      HTTP_VERB_HEAD      = 2,
      HTTP_VERB_PUT       = 3,
      HTTP_VERB_LINK      = 4,
      HTTP_VERB_DELETE    = 5,
      HTTP_VERB_UNLINK    = 6,
      _HTTP_VERB_MAX      = 6,
   };
. . .

Объект, на который нацелена данная команда передается методу OpenRequest через параметр pstrObjectName. Он должен содержать указатель на строку с именем объекта, например именем файла, исполняемого модуля CGI, расширения ISAPI и т. д.

Все остальные параметры метода OpenRequest являются необязательными. Вы можете их не указывать, тогда для них будут использоваться значения, принятые по умолчанию.

Так, через параметр pstrReferer можно передать адрес URL объекта, из которого вы получили адрес запрашиваемого объекта. По умолчанию этот параметр равен NULL и соответствующий адрес не используется.

Параметр dwContext задает идентификатор контекста для данной операции запроса. Более подробно идентификатор контекста рассматривается в описании метода GetFile класса CFtpConnection.

С помощью параметра pstrAcceptTypes ваше приложение может сообщить серверу тип информации, который оно может воспринять. Например, приложение может принимать и обрабатывать только текстовый файлы, файлы изображений, и т. д.

Если вы не укажете параметр pstrAcceptTypes или запишете в него значение NULL, то сервер будет считать, что приложение способно работать только с текстовыми файлами типа "text/*".

Переменная pstrVersion содержит указатель на строку, в которой определяется версия HTTP, используемая вашим приложением. Если вы опустите этот параметр, то будет использоваться версия HTTP/1.0.

В качестве параметра dwFlags может использоваться один из флагов, определенных в следующей таблице. Они позволяют управлять загрузкой файлов из сети или из кэша.

Флаг

Описание

INTERNET_FLAG_RELOAD

Указывает на необходимость загрузки запрашиваемого объекта или информации непосредственно с сервера Internet, даже в том случае если данная информация уже содержится в кэше

INTERNET_FLAG_DONT_CACHE

Предупреждает запись полученной информации к кэш

INTERNET_FLAG_MAKE_PERSISTENT

Записывает полученную с сервера информацию в кэш и запрещает ее удаление во время операции очистки кэша

INTERNET_FLAG_SECURE

Использует семантику защищенных транзакций (secure transaction semantics)

INTERNET_FLAG_NO_AUTO_REDIRECT

Отменяет автоматическое перенаправление запросов методом SendRequest класса CHttpFile. Используется только в запросах по протоколу HTTP

Метод OpenRequest возвращает указатель на объект класса CHttpFile, соответствующий запрашиваемому объекту.

Класс CInternetFile

В 28 томе, посвященном библиотеке MFC мы описывали классы CFile и CStdioFile, предназначенные для работы с файловой системой компьютера. Среди классов WinInet, входящих в библиотеку MFC, существует класс CInternetFile, наследованный от базового класса CStdioFile. В этом классе определены только самые общие методы для работы с серверами Internet.

От класса CInternetFile наследуются еще два класса WinInet - CGopherFile и CHttpFile. Эти классы ориентированны на работу, соответственно, с серверами Gopherf и HTTP:


CObject -> CFile -> CStdioFile -> CInternetFile -> CGopherFile
                                                |
                                                -> CHttpFile

Краткое описание методов, входящих в состав класса CInternetFile мы представили в следующей таблице:

Метод

Описание

CInternetFile

Конструктор класса CInternetFile

Abort

Закрывает файл на сервере, не принимая во внимание все возможные предупреждения и ошибки

Close

Закрывает файл CInternetFile и освобождает используемые им ресурсы

Flush

При записи данных на сервер классы WinInet выполняют их буферизацию. Метод Flush принудительно передает данные из буфера на сервер

HINTERNET

Возвращает идентификатор текущего сеанса связи с Internet

Read

Считывает данные с сервера

ReadString

Считывает строку символов из файла на сервере

Seek

Перемещает указатель в открытом файле на сервере

SetReadBufferSize

Устанавливает размер буфера для данных, которые загружаются с сервера

SetWriteBufferSize

Устанавливает размер буфера для данных, которые записываются на сервер

Write

Записывает данные на сервер

WriteString

Записывает в файл на сервере строку символов, закрытую нулем

Кроме перечисленных методов в состав класса CInternetFile входит элемент данных m_hFile, содержащий идентификатор файла.

Методы SetWriteBufferSize и SetReadBufferSize

Программный интерфейс WinInet не выполняет буферизации при обмене данными с серверами Internet. Однако если вы используете классы MFC, то можете выполнять буферизацию данных если работаете с методами класса CInternetFile и методами классов, наследуемых от него.

Размер буфера для операций чтения и записи устанавливается отдельно. Для этого в состав класса CInternetFile включены методы SetWriteBufferSize и SetReadBufferSize, которые, соответственно, устанавливают размер буфера, для записи и для чтения данных с сервера:


BOOL SetWriteBufferSize( UINT nWriteSize );
BOOL SetReadBufferSize( UINT nReadSize );

Параметры nWriteSize и nReadSize устанавливают размер буфера в байтах.

В случае успешного завершения методы SetWriteBufferSize и SetReadBufferSize возвращают ненулевое значение. Если методы завершились с ошибкой, то они возвращает ноль, а причину ошибки можно узнать с помощью функции GetLastError.

Метод ReadString

Метод ReadString считывает строку данных с сервера, ограниченную символом перевода на новую строку. Определены два варианта метода ReadString. Они различаются только способом записи полученной строки.

Первый вариант метода ReadString наиболее универсален. Он записывает полученные с сервера данные в строку класса CString, ссылка на которую передается через параметр rString:


virtual BOOL ReadString( CString& rString );
throw ( CInternetException );

Когда все данные получены, данный вариант метода ReadString возвращает значение FALSE.

Второй вариант метода ReadString записывает полученные данные в буфер pstr:


virtual LPTSTR ReadString( LPTSTR pstr, UINT nMax );
throw ( CInternetException );

Максимальный размер буфера вы должны указать в параметре nMax. В конце полученных данных записывается нулевой символ.

Когда все данные получены, метод ReadString, прототип которого приведен выше, возвращает значение NULL.

В случае возникновения ошибок во время приема данных, метод ReadString может вызвать исключение CInternetException. Причины, вызвавшие исключение можно определить, воспользовавшись методами класса CInternetException.

Метод WriteString

Антипод метода ReadString - метод WriteString записывает указанную ему строку данных в файл на сервере. Указатель на эту строку вы должны передать методу WriteString через параметр pstr:


virtual void WriteString( LPCTSTR pstr );
throw CInternetException( );

Если во время передачи данных возникнут какие-либо проблемы, метод WriteString может вызвать исключение CInternetException.

Метод Close

По окончании работы с файлом на сервере, его следует закрыть. Для этого вы можете воспользоваться методом Close:


virtual void Close();
throw( CInternetException );

В случае ошибки, метод Close может вызвать исключение CInternetException. Поэтому вы должны учесть такую возможность и поместить вызов этого метода внутри блока try.

Класс CHttpFile

Класс CHttpFile наследуется от базового класса CInternetFile. Он позволяет работать с сервером WWW по протоколу HTTP. В следующей таблице мы представили описание методов класса CHttpFile:

Метод

Описание

CHttpFile

Конструктор класса. Создает объект CHttpFile

AddRequestHeaders

Добавляет заголовок к запросу HTTP, передаваемому на сервер WWW

SendRequest

Передает запрос HTTP на сервер WWW

QueryInfo

Получает ответ или заголовок запроса от сервера WWW

QueryInfoStatusCode

Определяет код состояния, связанный с данным запросом HTTP

GetVerb

Определяет действие, которое было указано в запросе, переданном на сервер WWW

GetObject

Определяет объект, для которого был выполнен запрос на сервер WWW

GetFileURL

Позволяет получить имя файла на сервере WWW в формате URL

Close

Закрывает объект CHttpFile и освобождает все используемые им ресурсы

Метод AddRequestHeaders

Метод AddRequestHeaders добавляет один или несколько заголовков к запросу HTTP, который затем будет передаваться на сервер. Данный метод только подготавливает запрос HTTP, для выполнения фактической передачи запроса серверу необходимо воспользоваться методом SendRequest класса CHttpFile.

В классе CHttpFile определены два метода AddRequestHeaders, которые имеют различный набор параметров:


BOOL AddRequestHeaders( 
   LPCTSTR pstrHeaders, 
   DWORD dwFlags = HTTP_ADDREQ_FLAG_ADD_IF_NEW, 
   int dwHeadersLen = -1 
);
  
BOOL AddRequestHeaders( 
   CString& str, 
   DWORD dwFlags = HTTP_ADDREQ_FLAG_ADD_IF_NEW 
);

Строка с заголовками, которые надо добавить к запросу, указывается методу AddRequestHeaders через параметр pstrHeaders, как указатель типа LPCTSTR или через строку str класса CString. В первом случае вы должны использовать строку, закрытую нулем, или специально указать длину строки при помощи параметра dwHeadersLen. Если вы добавляете к запросу сразу несколько заголовков, то они должны быть разделены парой символов - CR и LF.

Параметр dwFlags позволяет изменить способ добавления заголовков к запросу. Для этого вы должны указать в качестве этого параметра один из флагов, представленных в следующей таблице:

Флаг

Описание

HTTP_ADDREQ_FLAG_COALESCE

Объединить заголовки, которое имеют одинаковые имена

HTTP_ADDREQ_FLAG_REPLACE

Замещает заголовок с указанным именем. Если методу AddRequestHeaders передается только название заголовка, без значения, то соответствующий заголовок удаляется из запроса. Если вы используете этот режим добавления, то вы можете указать методу AddRequestHeaders только один заголовок.

Совместно с этим флагом может использоваться флаг HTTP_ADDREQ_FLAG_ADD

HTTP_ADDREQ_FLAG_ADD_IF_NEW

Добавляет новый заголовок только в том случае, если заголовок с таким именем отсутствует. В противном случае метод AddRequestHeaders завершается с ошибкой

HTTP_ADDREQ_FLAG_ADD

Добавляет заголовок только в том случае, если заголовок с таким именем отсутствует. Может использоваться совместно с флагом HTTP_ADDREQ_FLAG_REPLACE

В случае успешного завершения метод AddRequestHeaders возвращает ненулевое значение. Если метод завершился с ошибкой, то он возвращает ноль, а причину ошибки можно узнать с помощью функции GetLastError.

Метод SendRequest

Метод SendRequest позволяет передать подготовленный запрос на сервер WWW.

Определены два варианта метода SendRequest, различающиеся типом и количеством параметров. Все параметры метода являются необязательными и их можно не указывать:


BOOL SendRequest( 
   LPCTSTR pstrHeaders = NULL, 
   DWORD dwHeadersLen = 0, 
   LPVOID lpOptional = NULL, 
   DWORD dwOptionalLen = 0 
);
throw ( CInternetException )
  
BOOL SendRequest( 
   CString& strHeaders, 
   LPVOID lpOptional = NULL, 
   DWORD dwOptionalLen = 0 
); 
throw ( CInternetException )

Необязательные параметры pstrHeaders и dwHeadersLen или strHeaders, для второго варианта метода, можно использовать для передачи дополнительных заголовков запроса.

Вы можете записать дополнительные заголовки в строку strHeaders или передать указатель на них через параметр pstrHeaders. Если вы не используете строки и работаете с указателями, то вы также должны задействовать параметр dwHeadersLen записав в него размер заголовка.

Если вам требуется передать сразу после заголовка запроса какие-либо данные, вы можете передать методу указатель на них через параметр lpOptional. В этом случае вы также должны записать в параметр dwOptionalLen длину этих данных.

Метод SendRequest возвращает ненулевое значение в случае успешного завершения или ноль в случае ошибки. Данный метод может вызывать исключение CInternetException. Вы можете определить причину исключения, воспользовавшись методами класса CInternetException.

Метод QueryInfo

Метод QueryInfo позволяет узнать ответ сервера на переданный ему запрос и заголовки самого запроса. Вы можете использовать данный метод после передачи запроса серверу с помощью метода SendRequest и или после того как вы открыли объект на сервере Internet с помощью метода OpenURL.

В состав класса входят три варианта метода QueryInfo, отличающихся набором параметров. Вы можете использовать тот метод, который наиболее подходит для выполнения ваших задач:


BOOL QueryInfo( 
   DWORD dwInfoLevel, 
   LPVOID lpvBuffer, 
   LPDWORD lpdwBufferLength, 
   LPDWORD lpdwIndex = NULL 
) const;
  
BOOL QueryInfo( 
   DWORD dwInfoLevel, 
   CString& str, 
   LPDWORD dwIndex = NULL 
) const;
  
BOOL QueryInfo( 
   DWORD dwInfoLevel, 
   SYSTEMTIME* pSysTime, 
   LPDWORD dwIndex = NULL 
) const;

Тип информации, запрашиваемой методом QueryInfo, определяется параметром dwInfoLevel, одинаковым у всех трех реализаций метода. В качестве этого параметра следует указать комбинацию атрибута и флага, определяющего тип получаемой информации:

Флаг

Назначение

HTTP_QUERY_CUSTOM

Определяет имя заголовка и записывает его в буфер lpvBuffer

HTTP_QUERY_FLAG_REQUEST_HEADERS

Данный флаг позволяет узнать заголовок запроса который был передан на сервер

HTTP_QUERY_FLAG_SYSTEMTIME

Некоторые заголовки содержат дату и время. Чтобы не утруждать себя разбором строки с датой и временем следует указать данный флаг и воспользоваться третьим вариантом метода QueryInfo, который сразу занесет эти данные в структуру типа SYSTEMTIME.

HTTP_QUERY_FLAG_NUMBER

Для тех заголовков, которые имеют числовые значения вы можете воспользоваться флагом HTTP_QUERY_FLAG_NUMBER. В этом случае запрашиваемые данные будут получены в виде 32-битового числа.

В следующей таблице перечислены возможные атрибуты, которые можно указывать в параметре dwInfoLevel:

Значения параметра lpdwIndex и dwIndex

HTTP_QUERY_MIME_VERSION

HTTP_QUERY_CONTENT_TYPE

HTTP_QUERY_CONTENT_TRANSFER_ENCODING

HTTP_QUERY_CONTENT_ID

HTTP_QUERY_CONTENT_DESCRIPTION

HTTP_QUERY_CONTENT_LENGTH

HTTP_QUERY_ALLOWED_METHODS

HTTP_QUERY_PUBLIC_METHODS

HTTP_QUERY_DATE

HTTP_QUERY_EXPIRES

HTTP_QUERY_LAST_MODIFIED

HTTP_QUERY_MESSAGE_ID

HTTP_QUERY_URI

HTTP_QUERY_DERIVED_FROM

HTTP_QUERY_LANGUAGE

HTTP_QUERY_COST

HTTP_QUERY_WWW_LINK

HTTP_QUERY_PRAGMA

HTTP_QUERY_VERSION

HTTP_QUERY_STATUS_CODE

HTTP_QUERY_STATUS_TEXT

HTTP_QUERY_RAW_HEADERS

HTTP_QUERY_RAW_HEADERS_CRLF

Данные, полученные методом QueryInfo, записываются либо в буфер lpvBuffer, либо в строку str, либо в структуру типа SYSTEMTIME, в зависимости от того, какой из прототипов метода используется.

Если вы используете первый прототип метода, то размер буфера вы должны записать в переменной типа DWORD и передать указатель на нее через параметр lpdwBufferLength. После вызова метода в эту переменную будет записана длина строки минус единица.

Чтобы перебрать множественные заголовки с одним и тем же именем вы должны использовать индекс заголовка, который передается через параметр lpdwIndex (или dwIndex) и начинается с нулевого значения. Перед вызовом метода запишите в этот параметр индекс заголовка, который надо получить. После того как метод завершит свою работу, в него будет записан индекс следующего заголовка или значение ERROR_HTTP_HEADER_NOT_FOUND.

В случае успешного завершения метод QueryInfo возвращает ненулевое значение. Если метод завершился с ошибкой, то он возвращает ноль, а причину ошибки можно узнать с помощью функции GetLastError.

Метод QueryInfoStatusCode

Метод QueryInfoStatusCode позволяет определить код завершения данного запроса HTTP. Вы можете использовать данный метод после передачи запроса серверу с помощью метода SendRequest и или после того как вы открыли объект на сервере Internet с помощью метода OpenURL:


BOOL QueryInfoStatusCode( DWORD& dwStatusCode ) const;

В случае успешного завершения метод QueryInfoStatusCode возвращает ненулевое значение. Если метод завершился с ошибкой, то он возвращает ноль, а причину ошибки можно узнать с помощью функции GetLastError.

Фактически метод QueryInfoStatusCode является частным случаем метода QueryInfo, который получает информацию об атрибуте HTTP_QUERY_STATUS_CODE.

Код завершения заносится методом QueryInfoStatusCode в переменную, ссылка на которую передается через параметр dwStatusCode. В следующей таблице представлены группы кодов завершения:

Коды завершения

Описание

200-299

Успешное завершение

300-399

Информация

400-499

Ошибка запроса

500-599

Ошибка сервера

Некоторые коды завершения, которые будут встречаться вами наиболее часто представлены в следующей таблице:

Коды завершения

Описание

200

Объект с данным адресом URL обнаружен

400

Неправильный запрос

404

Объект с данным адресом URL не обнаружен

405

Сервер не поддерживает запрашиваемый метод

500

Неизвестная ошибка сервера

503

Сервер перегружен

Метод GetFileURL

Метод GetFileURL возвращает имя файла в формате URL. Вы можете использовать данный метод после передачи запроса серверу с помощью метода SendRequest и или после того как вы открыли объект на сервере Internet с помощью метода OpenURL.

Прототип метода GetFileURL представлен ниже:


virtual CString GetFileURL( ) const;

Метод Close

Виртуальный метод Close закрывает объект CHttpFile и освобождает все используемые им ресурсы. Вы можете использовать данный метод после передачи запроса серверу с методом SendRequest и или после того как вы открыли объект на сервере Internet с помощью метода OpenURL.

Прототип метода Close представлен ниже:


virtual void Close( );

Метод Close не имеет параметров и не возвращает значения.

Класс CFileFind

Класс CFileFind предназначен для поиска файлов на локальном компьютере. Этот класс наследуется от базового класса CObject:


CObject -> CFileFind -> CFtpFileFind
                     |
                     -> CGopherFileFind

Класс CFileFind служит базовым классом для двух классов WinInet - CFtpFileFind и CGopherFileFind, которые предназначены для поиска файлов в сети Internet на серверах FTP и Gopher.

В следующей таблице мы привели описание методов класса CFileFind:

Метод

Описание

CFileFind

Конструктор класса CFileFind

GetLength

Определяет длину файла в байтах

GetFileName

Определяем имя файла с расширением

GetFilePath

Определяет полный путь файла

GetFileTitle

Определяет заголовок файла, то есть его имя не учитывая расширение

GetFileURL

Определяет адрес файла в формате URL

GetRoot

Определяет корневой каталог, в котором расположен файл

GetCreationTime

Определяет время создания файла

GetLastAccessTime

Определяет время последнего обращения к файлу

GetLastWriteTime

Определяет время последнего изменения файла

MatchesMask

Определяет состояние заданных атрибутов файла

IsDots

Определяет, состоит ли имя файла из символов "." или "..", которые означают каталог верхнего уровня

IsReadOnly

Определяет, является ли данный файл доступным только для чтения

IsDirectory

Определяет, является ли очередной объект, полученный методом FindNext, каталогом или файлом

IsCompressed

Определяет, является ли данный файл компрессованным

IsSystem

Проверяет, является ли файл системным

IsHidden

Определяет, является ли данный файл скрытым

IsTemporary

Позволяет распознать временные файлы

IsNormal

Определяет, является ли файл “нормальным”. Под словосочетанием “нормальный файл” понимаются файлы у которых не установлены другие атрибуты

IsArchived

Определяет является ли данный файл архивным

Close

Завершает поиск файлов

FindFile

Начинает поиск файла или файлов в указанном каталоге

FindNextFile

Продолжает поиск файла или файлов в указанном каталоге. Вы должны использовать этот метод после обращения к методу FindFile

Метод GetLength

После того, как вы нашли файл при помощи метода FindNextFile, вы можете определить его длину. Для этого следует воспользоваться методом GetLength, который возвращает длину файла в байтах:


DWORD GetLength( ) const;

Метод GetFileURL

Обнаружив файл при помощи метода FindNextFile, вы можете определить его адрес в формате URL, вызвав виртуальный метод GetFileURL:


virtual CString GetFileURL( ) const;

Метод GetFileURL возвращает адрес файла в строке класса CString.

Метод GetLastWriteTime

В состав класса CFileFind входят несколько методов, которые определяют различные временные характеристики файла. Вы можете узнать время создания файла, время последнего обращения к файлу и время последнего изменения файла. Для этих целей предназначены методы GetCreationTime, GetLastAccessTime и GetLastWriteTime. Они имеют сходный формат, поэтому мы рассмотрим только метод GetLastWriteTime, остальные методы вы изучите самостоятельно.

Определены два варианта метода GetLastWriteTime, которые используют для своей работы либо традиционную структуру FILETIME, либо более соответствующий концепции библиотеки MFC объект класса CTime:


virtual BOOL GetLastWriteTime( FILETIME* pFileTime ) const;
virtual BOOL GetLastWriteTime( CTime& refTime ) const;

В случае успешного завершения метод GetLastWriteTime возвращает ненулевое значение. Если метод завершился с ошибкой, то он возвращает ноль.

Метод IsDirectory

Метод FindNextFile позволяет обнаружить не только файлы, но также и каталоги. Метод IsDirectory определяет какой объект получен методом FindNextFile - файл или каталог:


BOOL IsDirectory( ) const;

Если объект является каталогом, тогда метод IsDirectory возвращает значение TRUE, а если файлом - тогда FALSE.

Метод Close

Когда вы завершите поиск файлов, следует вызвать метод Close. Он завершает поиск и освобождает все задействованные ресурсы. После того как вы вызвали метод Close, вы можете повторить поиск, используя тот же самый объект CFileFind:


void Close( );

Класс CFtpFileFind

Класс CFtpFileFind наследуется от базового класса CFileFind и позволяет провести поиск файлов на сервере FTP.

Для нас будут представлять интерес конструктор класса CFtpFileFind и все остальные три метода, входящие в состав этого класса. Название этих методов мы привели в следующей таблице:

Метод

Описание

CFtpFileFind

Конструктор класса CFtpFileFind

FindFile

Начинает поиск файла или файлов на сервере FTP

FindNextFile

Продолжает поиск файла или файлов в указанном каталоге сервера FTP. Вы должны использовать этот метод после обращения к методу FindFile

GetFileURL

Определяет адрес файла в формате URL

Если вы решите заняться разработкой приложения, взаимодействующего с серверами FTP, вы будете активно использовать все методы данного класса. Поэтому мы приведем их описания.

Конструктор класса CFtpFileFind

Конструктор класса CFtpFileFind имеет только один обязательный параметр pConnection. В нем вы должны указать объект класса CFtpConnection, представляющий соединение с сервером FTP, в рамках которого вы будете осуществлять поиск файлов или каталогов:


CFtpFileFind( 
   CFtpConnection* pConnection, 
   DWORD dwContext = 1 
);

В качестве второго параметра вы можете указать идентификатор контекста, который будет соответствовать данному объекту класса CFtpFileFind.

Метод FindFile

Чтобы приступить к поиску файла или каталога с заданным имененм надо воспользоваться методом FindFile. Он также позволяет приступить к поиску файлов и каталогов по шаблону имени. Прототип метода FindFile представлен ниже:


virtual BOOL FindFile( 
   LPCTSTR pstrName = NULL, 
   DWORD dwFlags = INTERNET_FLAG_RELOAD 
);

Имя файла или каталога, который вы желаете найти или соответствующий этому имени шаблон, вы должны записать в строку и передать указатель на нее методу FindFile через параметр pstrName. Чтобы выполнить поиск всех объектов - и файлов и каталогов, расположенных в текущем каталоге сервера FTP, вы можете указать в качестве шаблона для поиска символ звездочки * или просто использовать в качестве параметра pstrName значение NULL. Такой же эффект получается если вы просто опустите параметры метода и для них будут использованы значения, принятые по умолчанию.

Параметр dwFlags позволяет управлять процессом поиска. Вы, например, можете указать методу FindFile, что поиск следует осуществлять не используя данные которые записаны в кэш. Вот список флагов, которые можно использовать:

¨     INTERNET_FLAG_RELOAD

¨     INTERNET_FLAG_DONT_CACHE

¨     INTERNET_OPEN_FLAG_RAW_DATA

¨     INTERNET_FLAG_SECURE

¨     INTERNET_OPEN_FLAG_USE_EXISTING

Их описание мы приводили, когда рассказывали о методе OpenRequest класса CHttpConnection.

В случае успешного завершения метод AddRequestHeaders возвращает ненулевое значение. Если метод завершился с ошибкой, то он возвращает ноль, а причину ошибки можно узнать с помощью функции GetLastError.

Метод FindNextFile

После успешно завершившегося вызова метода FindFile вы должны вызвать виртуальный метод FindNextFile один или несколько раз для поиска всех файлов, соответствующих вашим требованиям. Только после того как вы хотя бы один раз вызвали метод FindNextFile вы можете воспользоваться другими методами класса CFindFile, чтобы определить характеристики обнаруженных файлов:


virtual BOOL FindNextFile( );

Метод FindNextFile возвращает ненулевое значение, если вы можете продолжить поиск и снова вызвать метод FindNextFile. Если метод FindNextFile вернул нулевое значение, значит был обнаружен последний файл соответствующий указанному вами шаблону поиска. В этом случае вы можете определить его характеристики, воспользовавшись методами класса FindFile и должны закончить поиск.

Метод GetFileURL

Если в качестве имени файла для поиска вы указали шаблон, то чтобы узнать имя обнаруженного объекта - файла или каталога вы можете воспользоваться методом GetFileURL класса CFtpFileFind:


CString GetFileURL( ) const;

Он возвращает адрес обнаруженного объекта в формате URL. Для определения имени объекта вы также можете воспользоваться некоторыми методами базового класса CFileFind.

Класс CGopherConnection

Класс CGopherConnection управляет соединением с сервером Gopher. Класс CGopherConnection наследуется от базового класса CInternetConnection:


CObject -> CInternetConnection -> CGopherConnection

В состав класса CGopherConnection входят конструктор и три метода - OpenFile, CreateLocator, GetAttribute. Метод OpenFile открывает файл на сервере Gopher. С помощью метода CreateLocator можно выполнить поиск файлов на сервере Gopher, а метод GetAttribute позволяет получить различную информацию о объекте на сервере.

С классом CGopherConnection непосредственно связаны еще два класса - CGopherLocator и CGopherFileFind. Эти классы предназначены для работы с серверами Gopher.

Серверы Gopher, также как и сервера WWW, предоставляют доступ к гипертекстовой информации. Однако они имеют значительно меньше возможностей и таких серверов постепенно становится все меньше и меньше. Существует мнение, что серверы Gopher остались только в тех организациях, которые не в состоянии оплатить создание сервера WWW и перенос на него всей накопленной информации. Поэтому мы не будем подробно останавливаться на соответствующих классах MFC. Дополнительную информацию о них вы можете получить из документации Microsoft Visual C++, а примеры программ в книге Special Edition Using Visual C++ 4.2.

Класс CGopherLocator

Класс CGopherLocator наследуется непосредственно от базового класса CObject. Этот класс предназначен для доступа к серверам Gopher.


CObject -> CGopherLocator

В состав метода CGopherLocator входит конструктор класса, метод GetLocatorType и оператор LPCTSTR.

Метод GetLocatorType разбирает локатор (gopher locator) и определяет его атрибуты, а оператор LPCTSTR позволяет получить прямой доступ к данным, записанным в объекте CGopherLocator как к обычной строке символов.

Класс CGopherFile

Также как класс CHttpFile, класс CGopherFile наследуется от базового класса CInternetFile. Вместе с другими классами WinInet он позволяет организовать поиск и получение файлов с серверов Gopher.

В класс CGopherFile входит конструктор CGopherFile и метод Close, который закрывает соединение с сервером Gopher.

Класс CGopherFileFind

Класс CGopherFileFind наследуется от базового класса CFileFind и используется для поиска файлов на серверах Gopher. В следующей таблице мы привели описание различных методов класса CGopherFileFind:

Метод

Описание

CGopherFileFind

Конструктор класса CGopherFileFind. Создает объект класса CGopherFileFind

FindFile

Начинает поиск файла или файлов на сервере Gopher

FindNextFile

Продолжает поиск файла или файлов в указанном каталоге сервера Gopher. Вы должны использовать этот метод после обращения к методу FindFile

GetLocator

Определяет объект CGopherLocator

GetScreenName

Определяет имя экрана Gopher

GetLength

Определяет длину файла в байтах


[Назад] [Содеожание] [Дальше]