В связи с все большим вниманием, которое привлекает к себе Интернет, все
больше людей становятся заинтересованы в сетевых технологиях. Данная статья
посвящена программированию на Borland Delphi с использованием одного из самых
популярных Интернет-протоколов - HTTP.
А именно, здесь мы рассмотрим компонент TNMHTTP (NetMasters HTTP), который
можно обнаружить на вкладке FastNet палитры компонентов Дельфи.
Начнем с теории. Если Вы уже знаете, что такое HTTP и зачем он нужен, то
пропустите следующий раздел.
Зачем нужен HTTP
Итак, где же используется HTTP? Если Вы хотя бы чуть-чуть заглядывали на
Интернет-странички и встречались с термином Web, то наверняка обратили
внимание на то, что адреса страничек, как правило, начинаются с http://.
Протокол HTTP (HyperText Transfer Protocol) позволяет принимать и
посылать не только гипертекстовые документы (типа html), но и любые другие
(тексты (txt), изображения (gif, jpg), и т.д.). Ниже приведены типовые задачи,
для выполнения которых необходимо использовать HTTP:
- Браузеры - программы, позволяющие просматривать
Интернет-странички;
- Скачивальщики - программы, позволяющие скачивать из Интернета
странички, рисунки и другие документы;
- Чаты - программы, позволяющие общаться по сети. Часто документы
HTTP используются для хранения сообщений (как, например, в конференциях).
- Это лишь список некоторых из стандартных направлений программирования с
использованием HTTP. Вы можете применять этот протокол для любых своих целей.
Например, автоматические системы обновления данных, посылка запросов в
Интернетовские базы, и еще множество всяческих других возможностей!
Краткое описание свойств, методов и событий
Ниже приведена таблица, содержащая наиболее краткое описание основных
свойств, методов и событий компонента TNMHTTP:
Свойства |
Body -
строка, содержащая либо путь к файлу, в который будет записано тело
http-документа (если св-во InputFileMode равно True), либо
непосредственно само тело (если св-во InputFileMode равно
False). Тип: string;
Header - строка, содержащая либо путь к файлу, в который
будет записан заголовок http-документа (если св-во InputFileMode
равно True), либо непосредственно сам заголовок (если св-во
InputFileMode равно False). Тип: string;
HeaderInfo - структура, содержащая различную информацию
о http-документе (подробней см. в help-файле). Тип: THeaderInfo;
InputFileMode - тип записи результата. Значение True
- запись в файлы, указанные в свойствах Body и Header,
False - запись в сами эти свойства. Тип: Boolean;
OutputFileMode - тип отсылаемых данных (методами Put,
Post и Trace). Значение True - данные для отправки
содержатся в файлах, указанных при вызове этих методов, а False -
в самих аргументах этих методов. Тип: Boolean;
Далее некоторые свойства, унаследованные от TPowerSock:
BytesRecvd, BytesSent, BytesTotal
- количество отправленных, принятых и общее количество байтов
соотвественно. Тип: LongInt;
Connected - показывает, установленно ли в данный момент
соединение. Тип: Boolean;
BeenCanceled - показывает, было ли прервано соединение с
сервером. Тип: Boolean;
Host - строка, содержащая хост-имя удаленного
компьютера. Заполнять не надо, так как это свойство устанавливается
автоматически при вызове методов Get, Put, Post и
т.д. Тип: string. Port - Integer, содержащий
порт удаленного компьютера (заполняется тоже автоматически);
TimeOut - таймаут в миллисекундах. Тип: Integer;
Еще есть множество свойств, но я пока остановлюсь на уже
перечисленных. За дополнительной информацией обращайтесь к help-у по
Дельфи.
|
Методы |
Get(URL:
string) - посылает запрос на указанный URL. Данные после выполнения
этого запроса записываются в файлы или в сами свойства Body и
Header (в зависимости от значения свойства InputFileMode);
Head(URL: string) - посылает запрос на указанный URL.
Данные после выполнения этого запроса записываются в файл или в само
свойство Header (в зависимости от значения свойства
InputFileMode). В отличие от метода Get, при вызове Head
запрос отсылается только на заголовок http-документа;
Post(URL, PostData: string) - посылает запрос на
изменение http-документа (с адресом URL) на данные, содержащиеся в
параметре PostData. Если OutputFileMode равен True, то в
PostData должен содержаться путь к файлу, содержащему нужные данные.
Put(URL, PutData: string) - посылает запрос на создание
http-документа (с адресом URL), содержащего данные, переданные в
параметре PutData. Если OutputFileMode равен True, то в
PostData должен содержаться путь к файлу, содержащему нужные данные.
Trace(URL, TraceData: string) - посылает запрос на
получение отладочных данных (для отладки соединения с HTTP-сервером).
Данные для запроса нужно указать в параметре TraceData. Если
OutputFileMode равен True, то в TraceData должен содержаться
путь к файлу, содержащему нужные данные.
Delete(URL: string) - посылает запрос на удаление
http-документа (с адресом URL).
Далее некоторые методы, унаследованные от TPowerSock:
Abort и Cancel - прерывают соединение и
обмен данными;
Disconnect - отсоединение от HTTP-сервера;
|
События |
OnAuthenticationNeeded
- возникает, когда сервер требует указания имени пользователя и пароля.
В обработчике этого события (если оно возникнет) Вы должны ответить
серверу, запонив нужными значениями соответствующие переменные.
Примечание: Перед установлением соединения можно сразу заполнить
поля UserID и Password в свойстве HeaderInfo;
OnAboutToSend - возникает, когда компонент TNMHTTP
собирается отправлять данные (запрос). В обработчике этого события можно
заполнить дополнительной информацией свойство SendHeader;
OnFailure - возникает, когда текущая операция
завершилась неудачно, т.е. произошла ошибка;
OnRedirect - возникает, сервер переадресовал ссылку с
указанной URL на другую ссылку. Установив параметр handled в
значение True можно запретить переадресацию и остановиться на
запрошенной URL. Значение по умолчанию - False;
OnSuccess - возникает, когда текущая операция
завершилась успешно, т.е. запрос был выполнен без ошибок;
Далее некоторые методы, унаследованные от TPowerSock:
OnConnect - возникает, когда соединение с сервером
успешно установлено;
OnDisconnect - возникает, когда соединение с сервером
завершено;
OnConnectionFailed - возникает, когда соединение с
сервером установить не удалось;
OnError - возникает, когда последняя операция была
завершена с ошибкой;
OnHostResolved - возникает, когда от DNS получен
IP-адрес указанного хоста;
OnInvalidHost - возникает, когда DNS вернул ошибку при
попытке определить IP-адрес указанного хоста;
OnPacketRecvd - возникает, когда значения свойств
BytesRecvd и BytesTotal изменены, т.е. была принята новая
порция данных от сервера;
OnPacketSent - возникает, когда значения свойств
BytesSent и BytesTotal изменены, т.е. была отправлена новая
порция данных на сервер;
OnStatus - возникает, когда статус компонента был
изменен (для обновления визуального оповещения пользователя);
|
Практика и примеры
Ну а теперь приступим к самому главному методу изучения - на примерах.
И самый первый пример - программа, позволяющая определить, существует ли
заданный URL:
Пример 1. Проверка существования указанной URL
{... Здесь идет заголовок файла и определение формы TForm1 и ее экземпляра Form1}
{В форму нужно поместить кнопку TButton и одно поле TEdit. При нажатии на
кнопку вызывается обработчик события OnClick - Button1Click. Перед этим в
TEdit нужно ввести адрес URL. НЕ ЗАБУДЬТЕ ПОМЕСТИТЬ В ФОРМУ КОМПОНЕНТ TNMHTTP!}
procedure Button1Click(Sender: TObject);
begin
{Пытаемя получить заголовок}
NMHTTP1.Head(Edit1.Text);
{Если URL неверный, то здесь выскочит ошибка}
end;
Следующий пример - скачивание сразу нескольких URL одновременно. Надо
заметить, что многие программисты пренебрегают многозадачностью Windows
(неважно, как она реализована, речь сейчас не об этом). В Дельфи очень легко
создавать отдельные, подчиненные Вашей программе процессы (а точнее - потоки) с
помощью базового класса TThread. Но об этом мы поговорим в другой раз (в
другой статье).
Пример 3. Одновременное скачивание указанных URL в
заданный каталог
// Здесь идет заголовок файла и определение формы TForm1 и ее экземпляра Form1
// Описание класса отдельного процесса
type
THTTPThread = class(TThread)
private
{Для каждого процесса - создаем свой компонент TNMHTTP}
FHTTP: TNMHTTP;
protected
// Execute вызывается при запуске процесса; override - заменяем
// существующую процедуру базового класса TThread
procedure Execute; override;
// DoWork - созданная нами функция, выполнение которой синхронизируется в Execute
procedure DoWork;
public
// URL - созданная нами строка, указывающая процессу, какой URL ему нужно скачать
URL: string;
end;
// В форму нужно поместить три кнопки TButton, одно поле TEdit и один список
// TListBox. При нажатии на кнопку Button1 вызывается обработчик события
// OnClick - Button1Click. Перед этим в TEdit нужно ввести путь к каталогу, в
// котором будут храниться скачанные файлы, а ListBox1 нужно заполнить списком
// URL-ов для скачивания (с помощью кнопок Add (Button2) и Delete (Button3)).
procedure TForm1.Button3Click(Sender: TObject);
begin
{Удаление выделенного URL из списка}
if ListBox1.ItemIndex >= 0 then
ListBox1.Items.Delete(ListBox1.ItemIndex);
end;
procedure TForm1.Button2Click(Sender: TObject);
var s: string;
begin
{Добавление URL в список}
s := InputBox('Добавить','Введите URL:','');
if s <> '' then
ListBox1.Items.Add(s);
end;
procedure TForm1.Button1Click(Sender: TObject);
var i: Integer;
begin
{Проверка на существование каталога}
if Length(Edit1.Text) > 0 then
if not DirectoryExists(Edit1.Text) then
MkDir(Edit1.Text);
{Далее идет создание для каждого URL в списке своего процесса}
for i := 0 to ListBox1.Items.Count-1 do begin
with THTTPThread.Create(True) do begin
{Создаем приостановленную задачу, указываем ей ее URL и запускаем ее}
URL := ListBox1.Items[i];
Resume;
end;
end;
end;
// Операторы процесса THTTPThread
procedure THTTPThread.Execute;
begin
// Делаем так, чтобы каждый процесс выполнялся одновременно с другими (синхронизация)}
Synchronize(DoWork);
end;
procedure THTTPThread.DoWork;
var i: Integer;
begin
{Создаем компонент TNMHTTP}
FHTTP := TNMHTTP.Create(Form1);
{Результат надо записывать в файлы}
FHTTP.InputFileMode := True;
{Подбираем имена для файлов}
i := 1;
while FileExists(Form1.Edit1.Text+'\page'+IntToStr(i)+'.htm') do
Inc(i);
{Указываем, в какие именно файлы класть результат}
FHTTP.Body := Form1.Edit1.Text+'\body'+IntToStr(i)+'.htm';
FHTTP.Header := Form1.Edit1.Text+'\header'+IntToStr(i)+'.txt';
{Пытаемся послать запрос}
FHTTP.Get(URL);
{Перед завершением процесса не забываем освободить память из-под компонента}
FHTTP.Free;
end;
ПРИМЕЧАНИЕ: Чтобы завершить некоторый процесс (Thread), нужно
вызвать метод Terminate класса этого процесса. Приостановить процесс
можно оператором Suspend, а продолжить выполнение - Resume. Также
можно настроить приоритет каждого отдельного процесса через свойство Priority.
Неплохой пример работы с процессами можно найти в подпапке Demos\Threads
папки, куда Вы установили Delphi.
Замечания по алгоритмам типовых задач
Если Вы собираетесь создать скачивалку сайтов, то Вам необходимо учитывать
следующее (решить следующие проблемы):
- Нужно скачивать не только саму страничку в формате HTML, но и все
входящие в нее рисунки (gif, jpg, и т.д.);
- в некоторых случаях удобно скачивать не одну страничку, а несколько
страниц, ссылки на которые находятся на первой из скачиваемых страничек. При
этом нужно учитывать, что на страничке могут находиться и ссылки на другие
сайты, поэтому необходимо анализировать скачиваемые ссылки (чтобы случайно
не скачать весь Интернет). Для решения задачи со скачиванием нескольких
страничек нужно использовать рекурсию;
- необходимо качественно информировать пользователя о ходе закачки. Т.е.
показывать общее и скачанное количество информации;
- после скачивания нужно заменить Интернетовские ссылки на локальные,
чтобы можно было просматривать странички в режиме offline.
|