Приложение ConsoleHTTP
В разделе “Приложение Console FTP“ мы привели приложение ConsoleFTP, которое соединяется с заданным сервером FTP. Для этого в нем сначала создается объект класса CInternetSession, представляющий сеанс работы с WinInet, а затем с помощью метода GetFtpConnection предпринимается попытка соединиться с сервером по заданному адресу. Если установить соединение не удается, например, из - за того, что адрес с таким адресом не существует, то метод GetFtpConnection вызывает исключение CInternetException:
// Инициализируем сеанс работы с WinInet
CInternetSession* m_InternetSession = NULL;
m_InternetSession = new CInternetSession("Connecter");
try
{
// Пытаемся соединиться с FTP - сервером sServer
CFtpConnection* m_FtpConnection = NULL;
m_FtpConnection =
m_InternetSession -> GetFtpConnection( sServer );
. . .
}
catch (CInternetException* pEx)
{
// Обрабатываем исключение CInternetException
. . .
}
Таким образом, о существовании FTP сервера sServer можно судить по тому, вызвал ли метод GetFtpConnection исключение CInternetException. Если исключение не появилось и метод GetFtpConnection вернул не нулевое значение, значит сервер FTP существует и доступен. А если исключение все же было вызвано, значит, скорее всего, сервера с заданным именем просто не существует.
Как вы знаете, класс CInternetSession содержит в себе три метода для соединения с серверами FTP, WWW и Gopher. Это методы GetFtpConnection, GetHttpConnection и GetGopherConnection. Казалось бы достаточно заменить в исходных текстах приложения FtpConnection вызов метода GetFtpConnection на GetHttpConnection и вы сможете использовать это же приложения для поиска серверов WWW.
Проведите небольшой эксперимент и внесите в исходные тексты проекта FtpConnection соответствующие изменения:
// Инициализируем сеанс работы с WinInet
CInternetSession* m_InternetSession = NULL;
m_InternetSession = new CInternetSession("Connecter");
try
{
// Пытаемся соединиться с WWW - сервером sServer
CHttpConnection* m_HttpConnection = NULL;
m_HttpConnection =
m_InternetSession -> GetHttpConnection( sServer );
. . .
}
catch (CInternetException* pEx)
{
// Обрабатываем исключение CInternetException
. . .
}
Постройте проект и запустите полученное приложение. Попытайтесь соединиться с помощью приложения с различными серверами WWW. Очень скоро вы обнаружите что соединение выполняется “успешно” даже с несуществующими серверами.
Чтобы быть уверенным, что сервер WWW по данному адресу не существует или недоступен, вы можете попытаться связаться с ним при помощи любой программы навигатора, например с помощью Microsoft Internet Explorer или Netscape Navigator.
Так, если вы запустите навигатор Microsoft Internet Explorer и попробуете просмотреть с его помощью сервер FTP по адресу http://home.frolov.com/, то скорее всего, получите предупреждающее сообщение, показанное нами на рисунке 3.1. Увы, пока сервера FTP с таким именем не существует.

Рис. 3.1. Сервер http://home.frolov.com/ не найден
Изменим теперь приложение ConsoleFtp так, чтобы оно не только соединялось с сервером WWW, но и запрашивало с него информацию об определенном файле. Создайте новый проект ConsoleHttp таким же образом, как вы создавали проект ConsoleFtp. Укажите что приложение будет использовать библиотеку классов MFC.
Затем создайте новый текстовый файл ConsoleHttp.cpp, наберите в нем программный код, представленный в листинге 3.2 и включите его в проект. Чтобы ускорить набор файла ConsoleHttp.cpp за его основу вы можете взять файл ConsoleFtp.cpp из проекта ConsoleFtp.
Листинг 3.2. Файл ConsoleHttp.cpp
//============================================================
// Приложение ConsoleFtp. Выполняет соединение с заданным
// сервером WWW
//
// (C) Фролов Г.В., 1997
// E-mail: frolov@glas.apc.org
// WWW: http://www.glasnet.ru/~frolov
// или
// http://www.dials.ccas.ru/frolov
//============================================================
// Включаемый файл для библиотеки MFC
#include <afx.h>
// Включаемый файл для классов WinInet
#include <afxinet.h>
// Включаемый файл для консольного ввода/вывода
#include <iostream.h>
// Включаемый файл для стандартных функций
#include <stdlib.h>
//============================================================
// Главная функция приложения
//============================================================
int main(int argc, char* argv[])
{
// Если приложение запущено без параметра, отображаем на
// экране формат вызова приложения
if (argc != 2)
{
cout << "Programm format: ConsoleFtp <URL>" << endl;
cout << " <URL> - URL address of WWW" << endl << endl;
return -1;
}
// Записываем параметр, указанный при вызове приложения в
// текстовую строку sUrlAdress. Он должен содержать URL
// адрес сервера WWW
CString sUrlAdress;
sUrlAdress = argv[1];
// Отображаем адрес URL на экране
cout << "URL address: " << sUrlAdress << endl << endl;
// Определяем переменные, в которые будут записаны
// отдельные компоненты адреса, указанного пользователем.
// Имя сервера
CString sServer;
// Имя объекта на который указывает адрес URL
CString sObject;
// Номер порта
INTERNET_PORT nPort;
// Тип сервиса или тип протокола
DWORD dwServiceType;
// Разбираем адрес URL, записанный в строке sUrlAdress
if (!AfxParseURL(sUrlAdress, dwServiceType, sServer,
sObject, nPort))
{
// В случае ошибки выводим сообщение и завершаем
// работу приложения
cout << "AfxParseURL Error" << endl;
return -1;
}
// Проверяем, соответствует ли указанный адрес URL
// серверу WWW. Для этого тип сервиса должен быть http://
if(dwServiceType != AFX_INET_SERVICE_HTTP)
{
cout << " URL Address not WWW server" << endl;
return -2;
}
// Указатель на объект класса CInternetSession
CInternetSession* m_InternetSession = NULL;
// Инициализируем сеанс работы с WinInet - создаем объект
// класса CInternetSession
m_InternetSession = new CInternetSession("Connecter");
// Запрос для сервера WWW
CHttpFile* pFile=NULL;
// Определяем указатель на объект класса CFtpConnection
CHttpConnection* m_HttpConnection = NULL;
// Исключения, вызванные в этом блоке try обрабатываются
// следующим блоком catch
try
{
// Пытаемся соединииться с сервером sServer
m_HttpConnection =
m_InternetSession -> GetHttpConnection( sServer );
// Формируем запрос
pFile =
m_HttpConnection -> OpenRequest(
CHttpConnection::HTTP_VERB_HEAD,
sObject
);
// Дополнительный заголовок запроса HTTP
CString headerInfo(_T(
"Accept: text/*\r\nUser-Agent: HTTP Example\r\n"));
// Добавляем к запросу дополнительный заголовок
if(pFile->AddRequestHeaders(headerInfo))
{
// Передаем запрос на сервер
if(pFile->SendRequest())
{
DWORD dwReturnCode;
// Определяем код завершения запроса
if(pFile->QueryInfoStatusCode(dwReturnCode))
{
// Отображаем код завершения запроса на экране
CString sMessage;
sMessage.Format("%d",dwReturnCode);
cout << "SendRequest: " << sMessage <<
endl << endl;
}
else
{
cout << "Request Error" << endl << endl;
}
}
}
}
// Обрабатываем исключение CInternetException
catch (CInternetException* pEx)
{
// Временный буфер для сообщения
TCHAR szErr[1024];
// Выводим сообщение об ошибке
if (pEx->GetErrorMessage(szErr, 1024))
cout << "Error: " << szErr <<endl <<endl;
// Удаляем иссключение
pEx->Delete();
}
// Закрываем запрос
pFile -> Close();
// Удаляем объект pFile из памяти
if(pFile)
delete pFile;
// Закрываем соединение с сервером WWW
m_HttpConnection -> Close();
// Удаляем объект m_FtpConnection
delete( m_HttpConnection );
// Завершаем сеанс связи
m_InternetSession -> Close();
// Удаляем объект m_InternetSession
delete(m_InternetSession);
return 0;
}
Постройте только что созданный проект и запустите приложение, указав ему в качестве параметра адрес WWW страницы. Адрес должен быть полным - он должен определять метод доступа (в данном случае http://), имя сервера на котором страница расположена и полный путь к файлу страницы WWW.
Приложение соединится с сервером, на котором эта страница расположена и запросит о ней информацию. Результаты запроса будут выведены на экран. На рисунке 3.3 мы показали работу приложения ConsoleHttp, запросив с сервера http://dials.ccas.ru/ страницу с именем frolov.htm.

Рис. 3.2. Приложение ConsoleHttp запрашивает страницы http://www.frolov.ru/~frolov и http://www.glasnet.ru/~frolov