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

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

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

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

Приложение ConsoleFtp

Создайте новый проект. Выберите из меню File строку New. На экране появится диалоговая панель New. Выберите из списка, расположенного в этой панели строку Project Workspace и нажмите кнопку OK. Откроется диалоговая панель New Project Workspace. В качестве типа создаваемого приложения укажите Console Application и введите в поле Name имя проекта - ConsoleFtp. Затем нажмите кнопку Create. Microsoft Visual C++ создаст новый проект.

Мы будем использовать для нашего приложения классы библиотеки MFC. Чтобы настроить проект соответствующим образом, вы должны выбрать из меню Build строку Settings. На экране откроется диалоговая панель Project Settings, содержащая различные настройки проекта. Откройте на этой диалоговой панели страницу General, выберите из списка Microsoft Foundations Classes строку Use MFC in a Shared DLL и нажмите кнопку OK.

По умолчанию, новый проект не содержит ни одного файла. Создайте новый текстовый файл. Для этого еще раз выберите из меню File строку New и в открывшейся панели New укажите тип текстового файла - Text File. Нажмите кнопку OK. Откроется окно текстового редактора. Наберите в нем текст приложения, представленный нами в листинге 2.1. Сохраните набранный текст в файле под именем ConsoleFtp.cpp, записав его в каталог проекта.

Затем выберите из меню Insert строку Files into Project. На экране появится диалоговая панель Insert Files into Project. Выберите из списка файлов в этой панели файл ConsoleFtp.cpp и нажмите кнопку Add. Файл ConsoleFtp.cpp будет добавлен к проекту.

Листинг 2.1. Файл ConsoleFtp.cpp


//============================================================
// Приложение ConsoleFtp. Выполняет соединение с заданным 
// сервером FTP
//
// (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 FTP" << endl << endl;
      return -1;
   }

   // Записываем параметр, указанный при вызове приложения в 
   // текстовую строку sUrlAdress. Он должен содержать URL 
   // адрес сервера FTP 
   CString sUrlAdress;
   sUrlAdress = argv[1];
   
   // Отображаем адрес сервера FTP на экране
   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 
   // серверу FTP. Для этого тип сервиса должен быть ftp://
   if(dwServiceType != AFX_INET_SERVICE_FTP)
   {
      // Если адрес не соответствует серверу FTP выводим 
      // соответствующее предупреждение и завершаем приложение
      cout << "URL Address not FTP server" << endl;
         
      return -1;
   }

   // Указатель на объект класса CInternetSession
   CInternetSession* m_InternetSession = NULL;

   // Инициализируем сеанс работы с WinInet - создаем объект 
   // класса CInternetSession catch
   m_InternetSession = new CInternetSession("Connecter");   
      
   // Исключения, вызванные в этом блоке try обрабатываются 
   // следующим блоком catch
   try
   {
      // Определяем указатель на объект класса CFtpConnection
      CFtpConnection*  m_FtpConnection = NULL;
         
      // Пытаемся соединииться с сервером sServer
      m_FtpConnection = 
         m_InternetSession -> GetFtpConnection( sServer );

      // Выводим сообщение об успешном соединении
      cout << "Connect to FTP server established" << endl;

      // Закрываем соединение с сервером FTP 
      m_FtpConnection -> Close();

      // Удаляем объект m_FtpConnection
      delete( m_FtpConnection );
   }

   // Так как исключение в блоке try может быть вызвано только 
   // методом GetFtpConnection, достаточно определить 
   // обработчик исключения класса CInternetException
   catch (CInternetException* pEx)
   {
      // Обрабатываем исключение CInternetException
      TCHAR szErr[1024];  // временный буфер для сообщения

      // Выводим сообщение об ошибке
      if (pEx->GetErrorMessage(szErr, 1024))
         cout << "Error: " << szErr << endl << endl;

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

   // Завершаем сеанс связи
   m_InternetSession -> Close();
   // Удаляем объект m_InternetSession
   delete(m_InternetSession);

   return 0;
}

Постройте проект. Вы получите исполнимый файл приложения ConsoleFtp.exe. Запустите его на выполнение из командной строки MS-DOS Prompt (закрывать Windows не надо). В качестве параметра укажите URL адрес сервера FTP с которым вы желаете соединиться. Чтобы приложение правильно восприняло этот адрес, на забудьте указать в нем тип сервиса ftp.

Например, в ответ на следующую команду, приложение ConsoleFtp будет пытаться выполнить соединение с сервером FTP корпорации Microsoft:

ConsoleFtp.exe ftp://ftp.microsoft.com

Если указанный сервер FTP доступен, приложение выведет на экран сообщение об успешном соединении и завершит свою работу. Ниже мы привели сообщение приложения ConsoleFtp о соединении с сервером ftp.microsoft.com:

URL address: ftp://ftp.microsoft.com Connect to FTP server established

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


URL address: ftp://failer

Error: The server name or address could not be resolved

В данном случае мы попытались установить соединение с сервером FTP по адресу ftp://failer, но такой сервер не был обнаружен.

Если вы желаете запустить приложение ConsoleFtp непосредственно из среды Microsoft Visual C++ или под отладкой, вы должны указать параметры для него в диалоговой панели Project Settings. Чтобы открыть эту панель выберите из меню Build строку Settings. Выберите в панели Project Settings страницу Debug (рис. 2.1), а затем из списка Category строку General.

Рис. 2.1. Диалоговая панель Project Settings, страница Debug

Теперь вы можете ввести аргументы для приложения в строке Program arguments. Когда вы запустите приложение из среды Microsoft Visual C++, ему будут переданы именно эти параметры.

Устройство приложения ConsoleFtp

Для приложения ConsoleFtp мы использовали операторы потокового ввода/вывода << и >>, а также функции new и free. Поэтому нам понадобилось включить файлы iostream.h и stdlib.h:


#include <iostream.h>
#include <stdlib.h>

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


#include <afx.h>
#include <afxinet.h>

Определяя главную функцию приложения, мы указали для нее параметры argc и argv. Они позволяют получить параметры, указанные при запуске приложения в командной строке:


int main(int argc, char* argv[])
{
}

¨     Напомним, что через argc передается количество параметров указанных приложению, а через argv - список указателей на эти параметры

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


if (argc != 2)
{
   cout << "Programm format: ConsoleFtp <URL>" << endl;
   cout << "  <URL> - URL address of FTP" << endl << endl;
   return -1;
}

Параметр, указанный при вызове приложения, записываем в текстовую строку sUrlAdress. Если параметр задан правильно он должен содержать URL адрес сервера FTP:


CString sUrlAdress;
sUrlAdress = argv[1];

Отображаем адрес сервера FTP на экране, чтобы быть уверенным в том что он задан правильно:


cout << "URL address: " << sUrlAdress << endl << endl;

Далее мы объявляем временные переменные, которые будут использоваться при разборе адреса URL. Целью такого разбора будет выделение из адреса URL имени сервера FTP:


// Имя сервера
CString sServer;    
// Имя объекта на который указывает адрес URL 
CString sObject;
// Номер порта
INTERNET_PORT nPort;
// Тип сервиса или тип протокола
DWORD dwServiceType;

Сам разбор адреса URL, записанного в строке sUrlAdress, выполняется с помощью функции AfxParseURL. Заметим, что это пожалуй единственная функция библиотеки MFC, относящаяся к WinInet, которая не требует предварительно создать сеанс связи - объект класса CInternetSession.

Исходный адрес URL передается функции AfxParseURL через параметр sUrlAdress, а результат записывается в переменные dwServiceType, sServer, sObject, nPort. Нас будут интересовать только две переменные dwServiceType и sServer. В переменную dwServiceType функция AfxParseURL записывает тип сервиса, указанный в адресе sUrlAdress, а в строку sServer - имя сервера:


if (!AfxParseURL(sUrlAdress, dwServiceType, sServer, 
                 sObject, nPort))
{
   cout << "AfxParseURL Error" << endl;
   return -1;
}

if(dwServiceType != AFX_INET_SERVICE_FTP)
{
   cout << "URL Address not FTP server" << endl;
   return -1;
}

Если вы указали неправильный адрес URL или тип сервиса, не соответствующий серверу FTP, то на экран выводится предупреждающее сообщение и работа приложения завершается. Если адрес сервера указан верно, приложение создает сеанс связи с Internet. Для этого мы объявляем указатель на объект класса CInternetSession, а затем создаем сам объект, используя функцию new:


// Указатель на объект класса CInternetSession
CInternetSession* m_InternetSession = NULL;

// Инициализируем сеанс работы с WinInet - создаем объект 
// класса CInternetSession catch
m_InternetSession = new CInternetSession("Connecter");   

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

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

Теперь можно попытаться соединиться с сервером FTP. Для этого следует вызвать метод GetFtpConnection класса CInternetSession только что созданного объекта m_InternetSession. В случае ошибки этот метод может вызвать исключение CInternetException. Поэтому вызов метода GetFtpConnection мы помещаем в блок try и определяем для него соответствующий блок catch, обрабатывающий исключение CInternetException:


// Исключения, вызванные в этом блоке try обрабатываются 
// следующим блоком catch
try
{
   // . . .
}
catch (CInternetException* pEx)
{
   // . . .
}

Обработчик исключения CInternetException вызывает метод GetErrorMessage для полученного исключения. Он записывает во временный буфер szErr причину вызова исключения. Если текстовое описание исключения доступно, метод GetErrorMessage возвращает ненулевое значение. В этом случае мы отображаем полученный текст на экране:


// Обрабатываем исключение CInternetException
TCHAR szErr[1024];  // временный буфер для сообщения

// Выводим сообщение об ошибке
if (pEx->GetErrorMessage(szErr, 1024))
   cout << "Error: " << szErr << endl << endl;

Затем завершаем обработку исключения, вызывая для него метод Delete. Он удаляет объект, представляющий исключение, из оперативной памяти:


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

Вернемся к блоку try. В нем приложение исполняет свою главную задачу - пытается установить соединение с сервером FTP. Адрес сервера FTP передается методу GetFtpConnection класса CInternetSession. Если соединение с сервером будет установлено, то этот метод вернет указатель на объект класса CFtpConnection и мы запишем его во временную переменную m_FtpConnection:


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

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

В случае успешного соединения с сервером FTP, приложение отображает на экране соответствующее сообщение:


// Выводим сообщение об успешном соединении
cout << "Connect to FTP server established" << endl;

Больше приложение ConsoleFtp ничего не делает с сервером, поэтому закрываем соединение с сервером и удаляем соответствующий объект m_FtpConnection из памяти (этот объект создается методом GetFtpConnection):


// Закрываем соединение с сервером FTP 
m_FtpConnection -> Close();
// Удаляем объект m_FtpConnection
delete( m_FtpConnection );

Перед окончанием работы приложения, завершаем сеанс связи, вызывая метод Close класса CInternetSession, а затем удаляем соответствующий объект из памяти, вызывая оператор delete:


// Завершаем сеанс связи
m_InternetSession -> Close();
// Удаляем объект m_InternetSession
delete(m_InternetSession);

Конечно, приложение ConsoleFtp демонстрирует только самые основные принципы использования классов WinInet. В следующем разделе мы приведем еще одно приложение для работы с серверами FTP. Приложение FtpView значительно сложнее чем ConsoleFtp. Оно позволяет пользователю просматривать структуру каталогов сервера FTP и названия записанных в них файлов. Несколько позже мы модифицируем приложение FtpView так, чтобы его можно было использовать для загрузки файлов и будем вносить в него небольшие изменения для демонстрации различных приемов работы с серверами FTP.

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