Введение
В связи с все большим вниманием, которое
привлекает к себе Интернет, все больше людей
становятся заинтересованы в сетевых технологиях.
Данная статья посвящена программированию на 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;
|
Далее - скачивание указанной странички в
указанный файл.
Пример 2. Скачивание указанной URL в
заданный файл
|
{... Здесь идет заголовок
файла и определение формы TForm1 и ее экземпляра Form1}
{В форму нужно поместить кнопку TButton и
три поля TEdit. При нажатии на кнопку вызывается
обработчик события OnClick - Button1Click. Перед этим в
первый TEdit нужно ввести адрес URL, во второй - имя
файла для заголовка, а в третий - имя файла для
тела странички (html).
НЕ ЗАБУДЬТЕ ПОМЕСТИТЬ В ФОРМУ КОМПОНЕНТ TNMHTTP!}
procedure Button1Click(Sender: TObject);
begin
{Пытаемся получить http-документ}
{Результат надо записать в
файлы}
NMHTTP1.InputFileMode := True;
{А здесь указываем в какие
именно файлы}
NMHTTP1.Header := Edit2.Text;
NMHTTP1.Body := Edit3.Text;
NMHTTP1.Get(Edit1.Text);
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.
Эпилог
В этой статье отображены основные приемы
работы с компонентом TNMHTTP в Дельфи. Если у Вас
есть вопросы - скидывайте их мне на E-mail: snick@mailru.com, а еще лучше - пишите
в конференции этого сайта (Delphi. Общие вопросы),
чтобы и другие пользователи смогли увидеть Ваш
вопрос и попытаться на него ответить!
Замечу, что TNMHTTP - не единственный компонент,
релизующий доступ по протоколу HTTP. Есть и его
аналоги с более расширенными возможностями,
например, набор компонентов ICS (Internet Component Suite), в
состав которого входит даже компонент FTPServer,
позволяющий легко запрограммировать свой
собственный сервер FTP для Windows. Этот набор можно
скачать на сайте Delphi Super Page.
Карих Николай. Московская область, г.Жуковский
|