У зв'язку з усе більшою увагою, яке привертає до себе Інтернет, все більше людей стають зацікавлені в мережевих технологіях. Дана стаття присвячена програмуванню на 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 In, Post і Trace). Значення True - дані для відправки містяться у файлах, зазначених при виклику цих методів, а False - в самих аргументах цих методів. Тип: Boolean;
Далі деякі властивості, успадковані від TPowerSock:
BytesRecvd, BytesSent, BytesTotal - кількість відправлених, прийнятих і загальна кількість байтів відповідно. Тип: LongInt;
Connected - показує, встановленого в даний момент з'єднання. Тип: Boolean;
BeenCanceled - показує, чи було перервано з'єднання з сервером. Тип: Boolean;
Host - рядок, що містить хост-ім'я віддаленого комп'ютера. Заповнювати не треба, оскільки це властивість встановлюється автоматично при виклику методів Get, Put In, 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.
Непоганий приклад роботи з процесами можна знайти в папці DemosThreads папки, куди Ви встановили Delphi.
Зауваження по алгоритмах типових завдань
Якщо Ви збираєтеся створити скачівалку сайтів, то Вам необхідно враховувати наступне (вирішити наступні проблеми):
Потрібно завантажувати не тільки саму сторінку в форматі HTML, але і всі вхідні в неї малюнки (gif, jpg, і т.д.);
в деяких випадках зручно завантажувати не одну сторінку, а кілька сторінок, посилання на які знаходяться на першій після завантаження сторінок. При цьому потрібно враховувати, що на сторінці можуть знаходитися і посилання на інші сайти, тому необхідно аналізувати завантажувані посилання (щоб випадково не завантажити весь Інтернет). Для вирішення завдання зі скачуванням декількох сторінок потрібно використовувати рекурсію;
необхідно якісно інформувати користувача про хід закачування. Тобто показувати загальне і викачане кількість інформації;
після скачування потрібно замінити Інтернетівські посилання на локальні, щоб можна було переглядати сторінки в режимі offline.