Итак, список функций WinAPI, необходимых для работы нам известен. Декларации приведены в предыдущей статье, описания - в соотвествующих статьях. Но кроме этого необходимо знать и соблюдать некоторые правила. Прежде всего, это касается последовательности вызовов функций. Что говорит по этому поводу MSDN?
До использования функций WinINet, приложение должно попытаться установить соединение с Internet с помощью функции InternetAttemptConnect. Эта функция либо вызовет диалоговое окно для инициализации соелинения с Internet, либо проверит наличие уже существующего соединения. Если вызов этой функции потерпит неудачу, приложение может перейти в отключенный режим (offline), что позволит ему обращаться к информации, которая была сохранена в кэше по время предыдущего соединения с Internet.
Далее для проверки соединения с Internet можно использовать функцию InternetCheckConnection. Функция попытается определить доступность сервера, определяемого из URL, который послан функции в качестве параметра, с помощью пинга. Если в вызове функции был установлен флаг FLAG_ICC_FORCE_CONNECTION, а в качестве URL был послан NULL, функция проверит не имеется ли входа в серверную базу данных ближайшего сервера. Если такой сервер существует, то функция выполнит пинг этого сервера.
Затем нужно использовать функцию InternetOpen для установки характеристик соединения с Internet, которые будет использовать клиентское приложение. InternetOpen создает корневой дескриптор HINTERNET, который используется для установки сессий по протоколам http, ftp и gopher. InternetOpen не тестирует соединение с интернет для проверки - корректны ли характеристики посланные ей в качестве параметров.
Для создания индивидуальных сессий используйте функцию InternetConnect. InternetConnect инициализирует сессию для конкретного сайта, используя посланные ей параметры, и создает новый дескриптор HINTERNET, который является сегментом корневого дескриптора, созданного вызовом функции InternetOpen. Функция InternetConnect не пытается обратиться или установить соединение к конкретному сайту, за исключением случаев сессий FTP. Функции FtpFindFirstFile, FtpOpenFile, GopherFindFirstFile, GopherOpenFile и HttpOpenRequest используют дескриптор, созданный вызовом InternetConnect для установки соединения с конкретным сайтом.
Посмотрим, что будет происходить на реальном компьютере. Для начала выполним первую рекомендацию - будем использовать функцию InternetCheckConnection для попытки установки соединения с Internet.
Вызов функции предельно прост, так как функция не принимает никаких параметров:
DECLARE integer InternetAttemptConnect IN WinInet
? InternetAttemptConnect()
Будем использовать компьютер, подключенный к Интернет через локальную сеть, на что указывает индикатор в system tray.
Выполним приведенную выше программу.В результате исполнения этого кода - мы получим 0 (что эквивалентно ERROR_SUCCESS). Попытка соединения удалась.
Но так-ли это? Отсоединяем комьютер от сети
и повторно исполняем приведенную программку. В результате имеем тот же 0, при гарантированной невозможности подключения к всемирной сети.
То есть, получается, что
данная функция сообщает лишь о наличии настройки подключения к Интернет.
Тогда переходим ко второй рекомендуемой проверке, которая осуществляется с помощью функции InternetCheckConnection. Дополним приведенную выше программу:
CLEAR
#Define FLAG_ICC_FORCE_CONNECTION 0x00000001
Declare Integer GetLastError In kernel32
Declare Integer InternetAttemptConnect IN WinInet
Declare Integer InternetCheckConnection In wininet;
STRING lpszUrl,;
INTEGER dwFlags,;
INTEGER dwReserved
? "Result of calling InternetAttemptConnect... "
?? InternetAttemptConnect()
Local llCanConnect2Host, lnError, lcHost2Check
? "Checking http://kodu.neti.ee/~juri4... "
lcHost2Check="http://kodu.neti.ee/~juri4"+CHR(0)
llCanConnect2Host=;
InternetCheckConnection(;
lcHost2Check,;
FLAG_ICC_FORCE_CONNECTION,;
0;
)
?? Iif(;
llCanConnect2Host=0,;
"Can't connect to host!",;
"Connection may be successfully established!";
)
lnError=GetLastError()
If lnError !=0
? "An error occurs on function call! Error number is:"
?? lnError
Endif
?
? "Checking nearest server... "
llCanConnect2Host=;
InternetCheckConnection(;
.Null.,;
FLAG_ICC_FORCE_CONNECTION,;
0;
)
?? Iif(;
llCanConnect2Host=0,;
"Can't connect to host!",;
"Connection may be successfully established!";
)
lnError=GetLastError()
If lnError !=0
? "An error occurs on function call! Error number is:"
?? lnError
Endif
?
? "Checking unavailable host... "
lcHost2Check="http://192.168.0.2/"+CHR(0)
llCanConnect2Host=;
InternetCheckConnection(;
lcHost2Check,;
FLAG_ICC_FORCE_CONNECTION,;
0;
)
?? Iif(;
llCanConnect2Host=0,;
"Can't connect to host!",;
"Connection may be successfully established!";
)
lnError=GetLastError()
If lnError !=0
? "An error occurs on function call! Error number is:"
?? lnError
Endif
Результат исполнения этой программы приведен на рисунке:
Вызов функции с URL несуществующего сервера возвратил код ошибки 12002, которая указывает, что запрос прерван по истечении лимита времени (The request has timed out.)
Что имеем в итоге? Вызов первой функции уверил нас в том, что настройки для соединения с Интернет имеются, вызов второй - что интересующий нас сервер доступен. Осталось соединиться с Интернет. Для этого будем использовать функцию InternetOpen, которая вернет нам дескриптор соединения с Интернет. Взглянем на ее декларацию:
Declare Integer InternetOpen In WinInet ;
String @lpcAgent, ;
Integer nAccessType, ;
String @lpcProxyName, ;
String @lpcProxyBypass, ;
Integer nFlags
Функция принимает пять параметров:
lpсAgent
Указатель на строку с нуль-терминатором (CHR(0)), которая указывает на имя приложения или сущности, вызывающего функции WinINet. Это имя используется как пользовательский агент в протоколе HTTP. Мы можем использовать здесь все, что угодно, например "Visual FoxPro Application".
nAccessType
Тип требующегося доступа. Этот параметр может принимать одно из перечисленных в таблице значений:
Символьная константа |
Hex-значение |
Dec-значение |
Описание |
INTERNET_OPEN_TYPE_DIRECT |
1 |
1 |
Разрешает имена всех хостов локально. |
INTERNET_OPEN_TYPE_PRECONFIG |
0 |
0 |
Запрашивает прокси или прямую конфигурацию из регистра. |
INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY |
4 |
4 |
Запрашивает проки или прямую конфигурацию из регистра и предотвращает использование стартовых Microsoft JScript или Internet Setup (INS) файлов. |
INTERNET_OPEN_TYPE_PROXY |
3 |
3 |
Направляет запрос прокси-серверу, в случае если не предоставлен лист обходов прокси-серверов и имени прокси-сервера нет списке прокси-серверов, которые можно обойти. В этом случае функция использует INTERNET_OPEN_TYPE_DIRECT. |
@lpcProxyName
Указатель на строку с нуль-терминатором (CHR(0)), указывает имя прокси-сервера(серверов) для использования с соединением, когда доступ через прокси-сервер определен установкой параметра nAccessType в значение INTERNET_OPEN_TYPE_PROXY. Не используйте пустую строку, так как функция InternetOpen в таком случае будет использовать ее как имя прокси-сервера. Фукнции WinINet распознают только зафиксированные CERN типы прокси (только HTTP) и TIS FTP шлюзы (только FTP). Если в системе инсталлирован Microsoft Internet Explorer, эти функции, кроме того, поддерживают SOCKS - прокси. Запросы к FTP и Gopher могут быть выполнены через определенные CERN типы либо путем изменения их в запрос HTTP или путем использования функции InternetOpenUrl. Если параметр dwAccessType не установлен в значение INTERNET_OPEN_TYPE_PROXY, то этот параметр игнорируется и должен быть установлен в NULL.
@lpcProxyBypass
Указатель на строку с нуль-терминатором CHR(0), который определяет необязательный список имен хостов или IP адресов, или тех и других, запросы к которым не должны отправляться через прокси для случая, когда значение параметра nAccessType установлено в INTERNET_OPEN_TYPE_PROXY. Список может содержать модификаторы в виде звездочки. Не используйте пустую строку в качестве параметра, так как InternetOpen будет использовать ее как список обхода прокси-серверов. Если этот параметр указан как макро "<local>" в виде единственного члена списка, функция будет обходить любые имена хостов, которые не имеют в своем имени точки. Если же значение параметра nAccessType не установлено в INTERNET_OPEN_TYPE_PROXY, то этот параметр будет игнорирован и и его значение должно быть установлено в NULL.
nFlags
Опции. Этот параметр может представлять собой комбинацию значений, приведенных ниже в таблице.
Символьная константа |
Dec-значение |
Описание |
INTERNET_FLAG_ASYNC |
1 |
Выполняет только асинхронные запросы на дескрипторах по убывающей от дескриптора возвращенного этой функцией. |
INTERNET_FLAG_FROM_CACHE |
2 |
Не выполняет сетевых запросов. Все сущности возвращаются из кэша. Если запрашиваемый элемент не находится в кэше, то возвращается соответствующая подходящая ошибка, такая как ERROR_FILE_NOT_FOUND. |
INTERNET_FLAG_OFFLINE |
2 |
Идентично INTERNET_FLAG_FROM_CACHE. Не выполняет сетевых запросов. Все сущности возвращаются из кэша. Если запрашиваемый элемент не находится в кэше, то возвращается соответствующая подходящая ошибка, такая как ERROR_FILE_NOT_FOUND. |
Смысл вызова этой функции - получить дескриптор соединения с Интернет и затем использовать его для вызова других функций, которым он требуется в качестве одного из параметров. Но прежде чем изменить нашу простенькую программку, посмотрим еще на одну функцию, которая также необходима в приложении. Это функция InternetCloseHandle. Назначение этой функции - закрыть дескриптор соединения с Интернет или дескприптор сессии, установленной ддя конкретного сайта. Ее декларация проста:
Declare Integer InternetCloseHandle In WinInet Integer nHandle
и требует передачи ей при вызове всего одного параметра - дескриптора соединия, который должен быть закрыт.
Изменим нашу простенькую программку так, как показано ниже. При этом мы не будем ипсользовать ни прокси-серверы, ни их обходов, ни флагов. Но укажем функции, что она должна использовать предустановки из регистра Windows, которые определены вами в диалоговом окне Internet Options панели управления.
Clear
#Define FLAG_ICC_FORCE_CONNECTION 0x00000001
#Define INTERNET_OPEN_TYPE_PRECONFIG 0
Declare Integer GetLastError In kernel32
Declare Integer InternetAttemptConnect In WinInet
Declare Integer InternetCheckConnection In wininet;
STRING lpcUrl,;
INTEGER nFlags,;
INTEGER nReserved
Declare Integer InternetOpen In WinInet ;
String @lpcAgent, ;
Integer nAccessType, ;
String @lpcProxyName, ;
String @lpcProxyBypass, ;
Integer nFlags
Declare Integer InternetCloseHandle In WinInet Integer nHandle
If InternetAttemptConnect() !=0
=Messagebox(;
"На данном компьютере не определены настройки для соединения с Интернет",;
16,;
"Warning!Connection to Internet cannot be established!";
)
Return
Endif
Local llCanConnect2Host, lnError, lcHost2Check,;
lpcAgent, lpcProxyName, lpcProxyBypass, lnFlags, lhInternet
lcHost2Check="http://kodu.neti.ee/~juri4"+Chr(0)
lpcAgent="Visual FoxPro Application"+Chr(0)
lpcProxyName=Chr(0)
lpcProxyBypass=Chr(0)
lnFlags=0
? "Checking http://kodu.neti.ee/~juri4... "
lcHost2Check="http://kodu.neti.ee/~juri4"+Chr(0)
llCanConnect2Host=;
InternetCheckConnection(;
lcHost2Check,;
FLAG_ICC_FORCE_CONNECTION,;
0;
)
?? Iif(;
llCanConnect2Host=0,;
"Can't connect to host!",;
"Connection may be successfully established!";
)
lnError=GetLastError()
If lnError !=0
? "An error occurs on function call! Error number is:"
?? lnError
Endif
lhInternet=InternetOpen(;
@lpcAgent, ;
INTERNET_OPEN_TYPE_PRECONFIG,;
@lpcProxyName,;
@lpcProxyBypass,;
lnFlags;
)
If lhInternet<>0
? "We have handle of the Internet connection, that is "
?? lhInternet
=InternetCloseHandle(lhInternet)
Else
lnError=GetLastError()
If lnError !=0
? "An error occurs on function call! Error number is:"
?? lnError
Endif
Endif
В результате исполнения этой программы на своем компьютере я получил приведенный на рисунке результат.
Итак чему мы научились в этой статье? Трем вещам:
- как подготовиться к открытию соединения с Интернет,
- как открыть соединение и получить его дескриптор и
- как закрыть соединение с Интерент.
Для чего все это нужно? Об этом в следующей статье, в которой мы начнем
создавать базовый класс-обертку для работы с Интернет.
|