Internet-компоненты в Delphi 4
В данном обзоре мы познакомимся с компонентами Delphi 4, которые расположены в палитре компонентов на странице (вкладке) с названием Internet. На этой странице собраны компоненты Delphi, которые или обеспечивают коммуникацию по протоколу TCP/IP — протоколу обмена данными, или используются для обработки данных, передаваемых через конкретный порт. Для более детального понимания работы этих компонентов необходимо кратко ознакомиться с механизмом передачи данных по протоколу TCP/IP.
Механизм передачи данных по протоколу TCP/IP
Компоненты, поддерживающие передачу данных
Компоненты ServerSocket и ClientSocket
Компоненты NMStrm и NMStrmServ
Компоненты Powersock и NMGeneralServer
Компоненты, работающие с данными
Механизм передачи данных по протоколу TCP/IP
Каждый компьютер, поддерживающий протокол TCP/IP, имеет свой IP-адрес, например 192.168.0.3. В компонентах, которые содержатся в Delphi, этот адрес определяется либо в свойстве Host, либо в свойстве Address. Иногда вместо IP-адреса используется имя компьютера, например www.torry.ru. При использовании имени первоначально происходит обращение к серверу имен, который возвращает IP-адрес для данного имени.
Перед тем, как передавать данные по протоколу TCP/IP, необходимо установить связь между двумя компьютерами. Компьютер, который инициализирует эту связь, будем называть клиентом, а компьютер, который должен откликнуться на инициализацию связи для обмена данными, — сервером. Соответственно компоненты Delphi, которые обеспечивают коммуникацию по протоколу TCP/IP, разбиваются на две группы — клиентские (используемые для реализации клиентских приложений) и серверные (для реализации приложений на сервере).
В компонентах Delphi клиент инициализирует связь либо вызовом конкретного метода (например, Connect в компоненте NMFTP), либо, чаще всего, при вызове метода клиента передачи данных (например, Get в компоненте NMHTTP, PostIt в компоненте NMStrm) клиент проверяет, была ли установлена связь с сервером с указанным IP-адресом, и, если нет — инициализирует связь. Что касается компонентов, размещаемых на сервере, то они не имеют методов инициализации связи. Приложение сервера должно постоянно работать, и первоначальная его задача — проверить, не хочет ли какой-либо клиент установить с ним связь. Поэтому сервер постоянно опрашивает тот или иной порт, чтобы установить, не появились ли на нем какие-либо данные. Компоненты, размещаемые на сервере, имеют методы, позволяющие начать или прекратить опрос соответствующего порта — например, изменение свойства Active компонента ServerSocket стартует или прекращает опрос соответствующего порта.
После установки связи между клиентом и сервером можно начинать передачу данных. Данные упаковываются в пакеты (обсуждение их формата выходит за рамки данной публикации). Достаточно знать, что каждый пакет содержит IP-адреса клиента и сервера, а также указание на порт.
Порт в протоколе TCP/IP играет двойную роль. Прежде всего одновременно может работать несколько приложений, обеспечивающих обмен данными через разные порты, и при этом они не будут захватывать данные друг у друга. Формально это соответствует многоканальной коммуникации — как будто компьютер имеет несколько сетевых карт и каждое из приложений работает со своей картой. Во-вторых, номер порта несет в себе информацию о типе передаваемых данных. Например, если данные поступили на 80-й порт, то их следует обрабатывать как гипертекст, если на 21-й порт — то как данные протокола обмена файлами. Впрочем, легко можно создать пару приложений (клиентское и серверное), которые через 80 порт будут осуществлять обмен данными в собственном формате. В компонентах Delphi порт обычно задается в свойстве Port, причем это свойство имеется как у клиентских компонентов, так и у серверных. Следует специально отметить, что после установки связи инициировать отправку данных может как клиент, так и сервер. Но в наиболее популярных протоколах обмена данными (HTTP, FTP) инициатором всегда выступает клиент.
Протокол TCP/IP стал частью операционной системы, причем не только в большинстве версий UNIX, но и в Windows. Этот факт делает его чрезвычайно удобным для создания сетевых приложений: разработчику не надо, например, убеждать своих потенциальных клиентов о необходимости установки на своих рабочих местах программного обеспечения фирмы Novell (клиентов NetWare) или какого-либо другого сетевого протокола. Поэтому компоненты со страницы Internet в последнее время широко используются не только для поддержки традиционных Интернет-приложений, но и для обмена приватными данными через TCP/IP-протокол.
Internet-компоненты
Большинство Internet-компонентов в Delphi 4 созданы фирмой NetMasters (http://www.netmastersllc.com). Поэтому имена этих компонентов начинаются с букв "NM". В некоторых из них имеются ошибки, но исходные коды к этим компонентам отсутствуют, поэтому о причине возникновения ошибки можно только догадываться.
На нашем CD-ROM вы найдете обновленные версии этих компоненентов для Delphi 4, а также для других продуктов фирмы Inprise. Помимо этого на CD-ROM находится и ActiveX-версия этих компонентов, которую можно использовать в таких продуктах, как, например, Visual Basic.
Приложения с использованием этих компонентов можно распространять свободно без выплаты вознаграждения NetMasters. Но в комплект поставки приложений обязательно должны быть включены DLL — NMFTPSN.DLL, NMOCOD.DLL, NMORDEU.DLL, NMORENU.DLL, NMORFRA.DLL, NMSCKN.DLL, NMW3VWN.DLL — при инсталляции Delphi они размещаются в каталоге Windows/System. Некоторые из этих DLL можно не включать в комплект поставки — например, если не используется компонент NMFTP, то можно убрать библиотеку NMFTPSN.DLL. Для определения списка DLL, которые необходимо включить в комплект поставки, надо запустить приложение из-под отладчика Delphi, обязательно обратиться к методам компонента фирмы NetMasters и проанализировать список модулей (View/Debug Windows/Modules).
В комплект поставки Delphi 4 входит значительное число примеров, демонстрирующих применение этих компонентов. Их можно найти в каталоге …\Delphi4\Demos\Internet. При обсуждении конкретных компонентов будет указываться местоположение примеров.
После этого введения рассмотрим применение отдельных компонентов со страницы Internet. Порядок их описания в данном обзоре в основном соответствует порядку их следования на странице. При описании компонентов используется следующее правило: если метод, свойство или событие идентичны для пары компонентов, то значение обьясняется только для одного из них. Как правило, расшифровка смысла приводится для того компонента, который описан раньше.
Компоненты, поддерживающие передачу данных
Компоненты ServerSocket и ClientSocket
Компоненты ServerSocket и ClientSocket реализуют коммуникацию двух компьютеров (клиента и сервера) через протокол TCP/IP. В принципе, большинство остальных Internet-компонентов являются модификациями данных компонентов, с конкретными портами и вспомогательными методами для обработки конкретных данных.
Из названий этих компонентов ясно, что один из них размещается на сервере, а другой — на клиенте. Для использования этих компонентов необходимо после установки компонента на форму изменить значение свойства Port. По умолчанию это свойство равно 0, и при этом значении компоненты работают некорректно. Можно определить, например, номер порта 1024. Оба компонента имеют свойство Active, но изменение этого свойства приводит к различной реакции ServerSocket и ClientSocket. Компонент ServerSocket начинает или прекращает проверку порта, указазанного в его свойстве Port на предмет появления на нем запроса от клиента. Вместо свойства Port можно указать свойство Service (и это рекомендуется делать для сервера — например, HTTP, FTP). Компонент ClientSocket старается соединиться (или прекращает соединение) с сервером, адрес которого указан в свойстве Address (например, 192.168.0.1), и через порт, указанный в свойстве Port. Вместо свойства Address в компоненте ClientSocket можно определить свойство Host (например, myserv.ipac.ac.ru). Так же, как и для сервера, вместо свойства Port можно изменять свойство Service.
Для тестирования необходимо сначала запустить сервер и присвоить его свойству Active значение True. После этого можно запускать клиент, указать ему адрес сервера и также выставить свойство Active в True. При установке связи будет вызван ряд событий как на сервере, так и на клиенте. На сервере будет вызвано событие OnClientConnect. В качестве параметра событию будет передана ссылка на переменную типа TCustomWinSocket, которая содержит в себе детальную информацию о клиенте. Например, можно обратиться к свойствам RemoteAddress или RemoteHost для определения адреса, откуда пришел запрос на соединение. Далее можно проанализировать адрес и, например, занести его в список текущих соединений или оборвать соединение, если адрес не содержится в определенном программистом списке разрешенных адресов. Сказанное можно проиллюстрировать кодом:
procedure TForm1.ServerSocket1ClientConnect(Sender: TObject; Socket: TCustomWinSocket); var S:string; begin S:=Socket.RemoteAddress; if (S='192.168.0.1') or (S='192.168.0.2') then ListBox1.Items.Add(S) { Добавить адрес в список } else Socket.Close; { Оборвать соединение } end;
Соответственно при прекращении клиентом связи с сервером будет вызываться событие OnClientDisconnect, которое для примера, приведенного выше следует использовать для удаления адреса из списка. В клиентском приложении, если сервер будет найден, будут вызваны три события: OnLookup — перед тем как начать поиск сервера; OnConnecting — немедленно после завершения поиска сервера и OnConnect — сразу же после установления связи с сервером. Если же сервер с указанным адресом не будет найден, то на клиенте будет вызвано событие OnError.
После успешного установления связи с сервером можно начать обмен данными между клиентом и сервером. Для этого следует использовать ключевые свойства этих компонентов с именем Socket типа TServerWinSocket для компонента ServerSocket и типа TClientWinSocket для компонента ClientSocket. Переменная TClientWinSocket содержит ряд методов, название которых начинается со слова Send. Вызов этих методов с соответствующим списком параметров — строка или поток — позволяет передать данные серверу. В свою очередь, переменная Socket. TServerWinSocket содержит список Connections, где находятся переменные типа TCustomWinSocket. В каждой из этих переменных хранится ссылка на соединенный клиент — с сервером одновременно могут работать несколько клиентов. Число соединенных клиентов хранится в свойстве Socket.ActiveConnections. Вызывая методы Connections[I].Sendххх, можно инициировать передачу данных I-му клиенту с сервера. Это, пожалуй, единственный серверный компонент страницы Internet, который может инициировать передачу данных клиенту — во всех остальных случаях клиент либо передает данные серверу, либо обращается к серверу с требованием предоставить данные.
Данные переданы — а как их теперь получить? Для этого необходимо создать обработчик события OnRead для ClientSocket (читает данные, посланные с сервера) и OnClientRead для ServerSocket (читает данные, отправленные клиентом). Списки параметров этих методов для ClientSocket и ServerSocket одинаковы, и если приложение использует оба этих компонента одновременно, то можно создать общий обработчик событий, например:
procedure TForm1.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); var S:string; begin S:='From:'+Socket.RemoteAddress+' - '+Socket.ReceiveText; ListBox2.Items.Add(S); end;
Данный обработчик события будет заносить в список текст сообщения и адрес, откуда оно было послано. Определение адреса важно для компонента ServerSocket: с ним может быть связано несколько клиентов. Следует отметить очень хорошую реализацию получения данных в ServerSocket при работе с несколькими клиентами — каждому клиенту выделяется собственный поток (Thread), и ServerSocket при приеме данных не блокирует порт и может одновременно работать с несколькими клиентами. ReceiveText — это не свойство, а метод. Если происходит обмен двоичными данными (вызов метода SendStream на сервере или клиенте), то следует воспользоваться методом ReceiveBuf(var Buf; Count: Integer) который копирует Count-байт в переменную Buf. Для определения размера полученных данных следует воспользоваться методом ReceiveLength.
Из других полезных обработчиков событий: OnWrite для ClientSocket и OnClientWrite для ServerSocket вызываются сразу же перед тем, как отправляются данные серверу или клиенту соответственно. OnError и OnClientError соответственно для ClientSocket и ServerSocket— при возникновении ошибки. В параметрах этих методов имеется переменная ErrorCode — если ей присвоить значение равное 0, то исключение не будет показано пользователю. Другой параметр — ErrorEvent — содержит информацию об ошибке (ошибка чтения, ошибка отправки данных, ошибка при попытке установления связи и т. д.). Компонент ServerSocket имеет также обработчик события OnAccept, которое вызывается сразу же после того, как клиент успешно связался с сервером.
В комплекте поставки Delphi 4 имеется демонстрационное приложение Chat, каталог ..\Chat. В этом приложении (оно является одновременно и клиентом и сервером) реализуется передача текстовых сообщений через протокол TCP/IP с использованием компонентов ClientSocket и ServerSocket. Недостаток проекта — ServerSocket может работать только с одним клиентом. Для его устранения при передачи данных необходимо учитывать число присоединенных клиентов посредством чтения свойства Socket.ActiveConnections и использовать массив Socket.Connections[I]. Кроме того, при закрытии этого приложения возникает исключение ESocketError. Исключение связано с тем, что для корректного обрыва связи через эти компоненты необходимо, чтобы некоторое время продолжался цикл выборки сообщений Windows в приложении. Это достигается явным прерыванием связи в обработчике события OnDestroy главной формы приложения:
procedure TForm1.FormDestroy(Sender: TObject); begin ClientSocket1.Active:=False; ServerSocket1.Active:=False; Application.ProcessMessages; end;
Пару компонентов — ClientSocket и ServerSocket — можно использовать для создания сетевых приложений с коммуникацией через протокол TCP/IP. Но при этом имеется ряд проблем, связанных с необходимостью оформления серверной части в виде полноценного сервера с возможностью его администрирования, работы в режиме LogOff для Windows NT, получения статистики и др. На мой взгляд, для создания сетевых приложений оптимально использовать другой компонент — NMHTTP. Речь о нем пойдет ниже.
Компоненты NMDayTime, NMTime
Оба этих компонента размещаются в клиентских приложениях и служат для запроса сервера о текущем времени (и дате для NMDayTime). Их различие: NMDayTime использует формат RFC 867, а NMTime — RFC 868. Обычно для передачи данных в таких форматах используют порты 13 и 37 соответственно, но разработчикам серверов никто не мешает экспонировать эти данные на других портах. Для получения данных о времени в компоненте NMTime необходимо прочитать значение свойства TimeStr, а в компоненте NMDayTime — значение свойства DayTimeStr. При чтении этого свойства оба компонента устанавливают связь с сервером, который определен в свойстве Host (это может быть имя или IP-адрес) и после успешной установки связи передают данные о времени (и дате для NMDayTime). Пример выдачи строк, содержащих информацию о дате и времени, следующий:
NMTime: 5:25:35 AM NMDayTime: 51257 99-03-20 13:39:40 66 0 0 646.3 UTC(NIST) *
При этом формат строки компонента NMTime зависит от текущей настройки клиентского компьютера — формат представления времени.
Из других свойств следует отметить свойство TimeOut — интервал в миллисекудах до получения ответа. О свойстве ReportLevel будет сказано чуть ниже, а каких-либо других ключевых свойств данные компоненты не имеют. На описанные ниже события следует обратить внимание — данные события имеются во всех компонентах фирмы NetMasters, и при обсуждении других компонентов они будут опускаться.
События OnHostResolved и OnInvalidHost вызываются, когда найден (или не найден) сервер, имя которого описано в свойстве Host. События OnConnect и OnConnectionFailed вызываются, когда была успешно (или неуспешно) установлена связь с сервером через порт, указанный в свойстве Port. OnDisconnect вызывается при прекращении связи с сервером. Интересно событие OnStatus — оно вызывается всякий раз, когда изменяется состояние компонентов, созданных фирмой NetMasters. При этом частота, с которой вызывается данное событие, зависит от свойства ReportLevel, которое может принимать следующие значения:
0 | OnStatus не вызывается |
2 | грубый отчет |
4 | детальный отчет |
8 | трассировка |
16 | отладка |
Пример значений переменной Status в обработчике событий OnStatus для свойства ReportLevel=8 (ReportLevel=16 — данные компоненты работают некорректно) приведен ниже:
Обработчик события OnStatus выглядит следующим образом:
procedure TForm1.NMTime1Status(Sender: TComponent; Status: String); begin if memo1<>nil then Memo1.Lines.Add(Status); end;
В файлах помощи события OnStatus говорится о необходимости проверки Memo1<>nil . Я не проводил такую проверку, и данные компоненты прекрасно работали.
В каталогах …\Time и \DayTime находятся проекты TimeDemo и DtmDemo, в которых приведены примеры использования компонентов NMTime и NMDayTime соответственно. Недостатки данных примеров: значение свойства TimeOut очень мало. (500 миллисекунд) — за это время практически невозможно добиться отклика от сервера. К достоинствам примеров следует отнести наличие адресов серверов, которые работают с портами 13 и 37 — большинство серверов не поддерживают просмотр этих портов.
Теперь следует рассмотреть, каким образом реализован в компонентах фирмы NetMasters обмен данными с сервером. Для наших примеров обмен данными инициализируется посредством чтения свойств TimeStr или DayTimeStr; в других компонентах это может быть вызов методов (Get или Post в NMHTT и др.). При обмене данными происходит поиск сервера, соединение с ним, формирование пакета данных и передача его по сети. Это занимает некоторое время — иногда существенное. Все время, пока не будет получен ответ от сервера, клиентское приложение ожидает и не выполняет дальнейший код. В слегка измененном стандартном примере TimeDemo:
procedure TForm1.Button1Click(Sender: TObject); begin NMTime1.Host := cbHost.Text; NMTime1.Port := StrToInt(Edit2.Text); Label3.Caption := StdCap+NMTime1.TimeStr; ShowMessage('Continue...'); end;
запрос к серверу осуществляется в выделенной строке. При этом никакого сообщения на экране (которое должно выводиться в следующем после выделенной строки операторе) не появится до тех пор, пока не будет получено значение текущего времени с сервера. Это разумно и существенно облегчает создание приложений работающим с Internet в Delphi 4. Тот, кто работал с компонентами Internet в Delphi 3, помнит, что после требования данных с сервера код продолжал выполняться дальше — данные с сервера поступали асинхронно, и это значительно усложняло код приложения. В Delphi 4 синхронизирован процесс обмена данными с сервером и дальнейшее выполнение кода. Но имеется небольшая деталь — общая для всех компонентов фирмы NetMasters: хотя выполнение кода не происходит, продолжается процесс выборки сообщений приложением! Выборку сообщений необходимо выполнять для того, чтобы «заметить», что клиентом получены данные с сервера, и считать их с порта. Но при этом пользователь может повторно нажать кнопку GetTime в данном проекте. Windows разрешает повторный вызов методов — то есть, если выполнение метода не кончилось и происходит его повторный вызов, то процессор начинает выполнять код заново. В данном примере это приведет к тому, что, не дожидаясь прихода сообщения с сервера, компонент NMTime попытается обратиться с новым сообщением (может быть, к другому серверу). В лучшем случае пользователь получит «ужасное», с его точки зрения, сообщение:
Но часто попытка повторного обращения к серверу приводит к зависанию приложения — например, к отсутствию реакции на кнопку Close и другим неприятным эффектам. Поэтому нельзя допускать повторного обращения к серверу до того, как будут получены данные (или произойдет исключение ETimeOut). Наиболее простой способ блокировки повторного входа в процедуру — сделать команду недоступной до тех пор, пока не будет получено сообщение с сервера:
procedure TForm1.Button1Click(Sender: TObject); begin try Button1.Enabled:=False; NMTime1.Host := cbHost.Text; NMTime1.Port := StrToInt(Edit2.Text); Label3.Caption := StdCap+NMTime1.TimeStr; finally Button1.Enabled:=True; end; end;
Защищенный блок try…finally…end; необходим здесь потому, что может произойти исключение по истечению времени TimeOut.
Сказанное выше верно для всех компонентов, созданных в фирме NetMasters. Ни один из демонстрационных проектов Internet, поставляемых вместе с Delphi 4, не содержит защиты от повторного обращения к серверу. Программистам, которые используют демонстрационные проекты как основу для создания собственных приложений, следует учитывать этот факт.
Компонент NMEcho
Компонент NMEcho используется для связи с сервером отклика — сервер отклика должен повторить то же самое сообщение, которое ему было послано. Компонент размещается в клиентском приложении. Обычно отклик размещают на 7-м порте. Далеко не все серверы поддерживают отклик — в примере EchoDemo, который можно найти в каталоге …\Echo, имеется адрес сервера, поддерживающего отклик. Из особенностей использования NMEcho: первоначально необходимо вызвать метод этого компонента Connect, который соединится с сервером Host и портом Port. После этого можно вызвать метод Echo, который в качестве параметра принимает какую-либо строку. Сервер отклика обязан возвратить ту же самую строку, ее можно прочитать в возвращаемом параметре этого метода:
EchoFromServer:=NMEcho1.Echo(Edit1.Text);
После возврата строки с сервера можно сравнить ее с посланным текстом, и, если они не совпадают, значит, существуют какие-либо проблемы с линией связи. Кроме того, можно прочитать свойство ElapsedTime — в нем содержится время, которое было затрачено для отправки и получения отклика. Когда нет необходимости продолжать работу с сервером отклика, следует вызвать метод Disconnect.
Компонент NMFinger
Компонент NMFinger используется для получения информации о пользователе с поискового сервера Internet. Компонент размещается в клиентском приложении. Обычно используется порт 79, но конкретный сервер может проверять и другие порты. В качестве исходных параметров помимо адреса сервера и порта принимается имя пользователя — свойство User. После этого следует прочитать свойство FingerStr. При чтении этого свойства будет получена информация об интересующем пользователе, она выводится в контроль UserInformation на рисунке ниже:
Пример использования NMFinger можно найти в проекте FngrDemo в каталоге …\Finger.
Компонент NMFTP
Компонент NMFTP обеспечивает передачу файлов через протокол FTP. Данный компонент размещается в клиентских приложениях и поддерживает следующие возможности: просмотр каталогов на выбранном FTP-сервере, создание новых и удаление имеющихся каталогов, просмотр списка файлов в отдельном каталоге, создание новых файлов и удаление имеющихся, пересылка локального файла на сервер (upload), копирование файла с сервера на локальный компьютер (download), восстановление прерванных процессов по пересылке файлов. Обычно используется порт 21 для протокола FTP, но отдельные FTP-серверы могут использовать другие порты. При размещении этого компонента в форме необходимо изменить свойство UserID — имя пользователя и Password. С пустыми значениями этих свойств (по умолчанию) компонент не работает. Имя пользователя и пароль можно узнать у владельца FTP-сервера, с которым необходимо организовать передачу данных. Большинство FTP-серверов поддерживают анонимный доступ, по крайней мере, к части данных. При этом имя пользователя (UserID) должно быть Anonymous, а пароль (Password) — FTP.
Сеанс FTP начинается с вызова его метода Connect. При этом устанавливается связь с сервером, чей адрес определен в свойстве Host, используются значения свойств UserID и Password. При этом поочередно вызываются события: OnHostResolved (или OnInvalidHost), OnConnect (или OnConnectionFailed). Смысл этих сообщений обсуждался в этой статье выше.
Если имя пользователя или пароль является нелегальным, то вызывается событие OnAuthenticationFailed. В этом событии можно изменить имя пользователя и/или пароль. Если после этого поставить значение переменной Handled в True, то новые имя пользователя и пароль будут переданы FTP-серверу. Если же имя пользователя и пароль являются пустыми, то вызывается событие OnAuthenticationNeeded, обработчик которого следует выполнить так же, как и описанный выше обработчик OnAuthenticationFailed.
После успешной установки связи с сервером можно приступать к работе с файловой системой сервера, которая заключается в вызове методов компонента NMFTP. После успешного соединения с сервером пользователь попадает в корневой каталог FTP-сервера. Для получения списка файлов (и подкаталогов) используется один из двух методов: List, который извлекает полную информацию о файлах и подкаталогах — имя, дату создания, тип файла, доступ к файлу для данного пользователя, или NList, который извлекает информацию только об имени файла.
Для каждого нового файла вызывается событие OnListItem, параметром которого является имя файла и сопутствующая информация. После того, как список исчерпан, вызывается событие OnSuccess или, если произошел сбой, — OnFailure. Если свойство ParseList установлено в True, то в событии OnSuccess становится доступным список-структура FTPDirectoryList, в котором содержится полная информация о файлах. Этот список заполняется с использованием свойства Vendor — тип файловой системы сервера. Желательно сохранять значение этого параметра по умолчанию (2411) — в этом случае автоматически определяется операционная система сервера и, следовательно, тип файловой системы.
Далее возможно перемещение по каталогам с помощью метода ChangeDir. В качестве параметра передается имя подкаталога. Не допускается передача цепочки каталогов — например: Work\MyData\User. Для смены каталогов по цепочке необходимо вызывать несколько раз метод ChangeDir. Имя текущего подкаталога сохраняется в свойстве CurrentDir. Подняться вверх по дереву каталогов невозможно, но можно переместиться в корневой каталог вызовом метода ChangeDir c пустой строкой в качестве параметра. Для каждого вновь выбранного каталога можно получить список файлов и подкаталогов, как это было описано выше. При помощи метода MakeDirectory можно создать новую поддиректорию в текущей.
После выбора текущего подкаталога можно приступать к переносу файлов между клиентом и сервером. Перед началом пересылки данных следует обратиться к методу Mode, в котором следует указать тип переносимых файлов — текстовые или двоичные. Если будет указан параметр MODE_IMAGE (двоичные файлы), то будут переноситься файлы любого типа, в том числе и текстовые (но потребуется больше времени). При значении этого параметра MODE_ASCII двоичные файлы передавать нельзя.
Используются следующие методы компонента NMFTP: Download — копирование существующего на сервере файла на клиентский компьютер; Upload — копирование клиентского файла на сервер; UploadAppend — добавление содержимого клиентского файла к имеющемуся на сервере файлу; UploadUnique — копирование клиентского файла на сервер, причем файл запоминается под уникальным именем на сервере. Процесс передачи файлов может занять существенное время. Во время передачи данных периодически вызывается событие OnPacketRecvd (при загрузки файла с сервера) или OnPacketSent (при передачи файла на сервер). В этих событиях определены свойства BytesRecvd или BytesSent соответственно. Сравнивая их со свойством BytesTotal, можно определить, какой процент команды выполнен, и визуально показать это клиенту с помощью, например, компонента ProgressBar. После успешного переноса файла вызывается событие OnSuccess, иначе — OnFailure. Если сбой произошел из-за плохого качества телефонной связи, то часто можно восстановить процесс передачи файлов с помощью команд DownloadRestore и UploadRestore. Команда Delete удаляет файл — удаление подкаталога в протоколе FTP не предусмотрено. Команда Rename изменяет имя файла.
Команду Reinitialize следует использовать, если необходимо войти под другим именем и паролем, например, для расширения своих прав. Метод DoCommand используется для нестандартных FTP-серверов — он должен выполнить команду, имя которой указано в качестве параметра этого метода.
Если для доступа к FTP-серверу используется прокси-сервер, то его имя указывается в свойстве Proxy, а номер порта — в свойстве ProxyPort. LocalIP — содержит адрес клиентского компьютера. Используя это свойство компонента NMFTP (так же, как и описанного ниже компонента NMHTTP), можно определить адрес клиента, что желательно, например, производить в некоторых инсталляционных приложениях. IP-адрес сервера, который содержится в свойстве RemoteIP, менее актуален — в URL он уже содержится. Свойство WSAInfo содержит информацию о текущей версии WinSock. Пример содержимого этого свойства:
Version= 1.1 High Version= 2.2 Description= Microsoft wsock32.dll, ver2.2, 32bit of Apr 28 1998, at 19:33:24. System= On Win95. Max Sockets= 32767 Max Udp pack size= 65467
На Web-сайтах, содержащих компоненты Delphi, имеются серверы FTP, выполненные в виде компонентов (см., например, TFTPServer (автор — Francoise Piete) на сервере http:// www.torry.ru в разделе Internet#3)
Компонент NMHTTP
Компонент NMHTTP использует HTTP-протокол (гипертекст) для обмена данными, и работает с Web-серверами. Обычно данные экспонируются на 80-м порте сервера. Используя этот компонент, можно обращаться за HTML-страницами к Web-серверу, который предоставляет требуемую страницу. При этом Web-сервер может обратиться за запросом текста страницы к ISAPI-приложению, CGI-приложению, которые помимо предоставления данных могут выполнить какой-либо код. Это чрезвычайно важный момент: другие компоненты страницы Internet, кроме пары ServerSocket/ClientSocket, не могут запустить выполнение приложения на удаленном компьютере. Но NMHTTP запускает приложения через Web-сервер, который уже имеет все необходимые инструменты администрирования. Поэтому я отдаю предпочтение NMHTTP-компоненту. Архитектуру сетевого приложения с использованием данного компонента можно представить следующим образом:
Сразу же возникает вопрос о передаче данных — в файлах помощи сказано, что NMHTTP используется для передачи гипертекста. Реально же может передаваться абсолютно любой текст. Для двоичных данных можно использовать процедуру перекодировки в разрешенные символы с последующим декодированием полученного пакета.
Еще одно преимущество данной архитектуры заключается в том, что Web-сервер поддерживает многопоточный (multi-threading) режим обращений. Это избавляет программиста от необходимости создавать приложения, работающие с несколькими потоками. Более того, на одном клиенте можно разместить, например, два компонента NMHTTP. Пока один из них занят осуществлением длительного запроса, другой может быть использован для импорта данных.
Клиент с данной архитектурой можно поместить в активной форме. При этом созданный ActiveX-компонент станет доступным для работы на Web-странице. Не требуется никаких доработок в механизме коммуникации с сервером: если клиент получил HTML-страницу и сумел загрузить ActiveX-компонент, то у него установлен работающий протокол TCP/IP. В свою очередь, сервер, который передал ActiveX-компонент, поддерживает протокол обмена данными HTTP, который необходим для успешного функционирования компонента NMHTTP.
Теперь о работе компонента NMHTTP. Имеются два базовых метода обращения к Web- серверу: Get и Post. Перед вызовом этих методов не требуется устанавливать связь с сервером — она будет установлена автоматически и оборвана после получения отклика от сервера. Оба этих метода в качестве параметра принимают URL, например: HTTP://192.168.0.1/MyISAPI.dll. Если свойство Port отличается от 80, то к данной строке автоматически добавляется номер порта. Если в качестве URL использовать пустую строку, то метод обратится к серверу с адресом, указанным в свойстве Host компонента NMHTTP. Метод Get требует данные у сервера, метод Post — передает данные серверу. Поэтому метод Post содержит второй параметр — строку данных, которые должны быть переданы серверу. В этой строке должны быть только символы, легальные для гипертекста. Если свойство OutputFileMode установлено в True, то второй параметр метода Post обязан содержать путь и имя файла, содержимое которого следует передать на сервер. Оба этих метода возвращают данные от сервера. Для их получения следует создать обработчик события OnSuccess. В этом событии легальным становятся свойства NMHTTP Body и Header, в которых содержатся данные, полученные от сервера. Если свойство InputFileMode установлено в True, то Body содержит имя файла, в котором запомнен отклик сервера. При невозможности получить отклик с сервера вызывается событие OnFailure. Из других методов следует отметить Head — получение заголовка документа, указанного в URL.
NMHTTP имеет ряд методов для работы с Web-сервером: Copy — копирует документ с одного URL на другой; Delete — удаляет документ с указанным URL; Link — связывает документ с ресурсами; Move — перемещает документ с одного URL на другой, и ряд других. Но большинство Web-серверов не поддерживают данные команды и возвращают код ошибки, который можно найти в свойстве ReplyNumber. Текстовое описание ошибки содержится в свойстве TransactionReply.
Из незнакомых нам событий следует отметить OnRedirect, которое вызывается, если Web-сервер перенаправляет запрос на другой сервер.
Свойство HeaderInfo должно заполняться в том случае, если обращение к заданному URL требует аутентификации клиента. Обязательные поля для заполнения этой структуры — UserID — имя пользователя и Password. Как правило, после аутентификации Web-сервер обязан сгенерировать cookie, которые становятся доступными в свойстве CookieIn в обработчике события OnSuccess. При последующих обращениях к Web-серверу вместо имени пользователя и пароля следует пересылать обратно cookie:
HeaderInfo.Cookie:=CookieIn;
Cвойство LastErrorNo содержит код ошибки WinSock32.dll, которая используется для протокола HTTP.
В каталоге …\Http содержится пример HTTPDemo, использующий базовые методы Get, Post и Head, и приводится пример заполнения структуры HeaderInfo.
Компоненты NMMsgServ и NMMsg
Компоненты NMMsgServ и NMMsg используются для передачи простых текстовых сообщений от клиента к серверу. Из названий этих компонентов ясно, какой из них размещается на клиенте, а какой на сервере. Передача текстовых строк не является стандартной, поэтому эти компоненты работают в паре. Стандарты на используемые порты отсутствуют, поэтому для них надо выбирать большие значения (чтобы случайно в будущем порт не совпал с каким-либо новым стандартом). Базовый метод компонента NMMsg - PostIt, в качестве параметра используется текст, который необходимо передать на сервер. При вызове этого метода автоматически устанавливается связь с сервером Host, и данные помещаются в порт Port. Прервать отправку сообщения можно, вызвав метод Abort. Помимо текста серверу передается также значение свойства FromName, которое, по замыслу авторов этого компонента, должно содержать данные, позволяющие идентифицировать отправителя.
Для приема сообщения клиента NMMsgServ должен иметь обработчик события OnMSG, в список параметров которого включены текст сообщения и идентификатор клиента. Из других событий NMMsgServ имеет только OnClientContact, которое вызывается в момент установления связи с клиентом. Интересно, что NMMsgServ экспонирует в Object Inspector свойство Host. Для компонента размещаемого на сервере, абсолютно непонятен смысл этого свойства. Согласно файлам справки Delphi4 такого свойства у NMMsgServ просто нет.
В каталоге ..\Msg имеется пример MsgDemo, иллюстрирующий сказанное выше.
Компонент NMNNTP
Компонент NMNNTP поддерживает обмен данными с сервером новостей. Сервер новостей обычно проверяет порт 119. Сессия начинается с вызова метода Connect. Помимо обычных параметров — Host и Port, в методе Connect используются также имя пользователя и пароль. В отличие от описанного выше компонента NMFTP для некоммерческих серверов новостей можно не заполнять свойства UserID и Password. Однако при этом запрещается помещение собственных статей на сервер новостей. В принципе, владелец сервера новостей может разрешить анонимное размещение статей, но я не знаю ни одного такого сервера. Кроме того, компонент NMNNTP осуществляет кэширование данных. Перед вызовом метода Connect необходимо изменить свойство CacheMode, которое может быть локальным, удаленным или промежуточным.
При выборе локального или промежуточного кэширования необходимо указать также каталог на локальном компьютере, куда помещаются кэшируемые данные, например:
NMNNTP1.NewsDir:='C:\TEMP';
После успешного соединения с сервером новостей следует выбрать рабочую группу (NewsGroup). Как правило, один сервер новостей имеет несколько рабочих групп. Полный список экспонируемых рабочих групп можно получить, вызвав метод NMNNTP.GetGroupList. При обращении к этому методу сразу же вызывается событие OnGroupListUpdate, после чего для каждой группы вызывается сообщение OnGroupListCacheUpdate. Вызов этого сообщения происходит многократно, в его параметрах можно найти не только текстовое название группы новостей, но и номера статей (от — до), относящихся к данной группе, а также информацию о том, разрешается ли пользователю с данным именем и паролем помещать свои статьи в данную группу новостей. Если сервер экспонирует большое число групп (несколько десятков), то список групп новостей передаются порциями по 10-20 наименований. При этом перед передачей каждого нового пакета имен групп вызывается событие OnGroupListUpdate.
Следующий этап работы с сервером новостей — выбор конкретной рабочей группы. Для этого вызывается метод SetGroup, который в качестве параметра принимает имя группы, например:
NMNNTP1.SetGroup('borland.public.delphi.internet');
При этом вызывается нотификационное сообщение OnGroupSelect. Только после этого можно получить список статей, экспонируемых в данной группе, содержание выбранных статей и, если есть разрешение на загрузку статей, поместить свои публикации в группу новостей. Если попытаться сделать это без выбора группы, то будет вызвано событие OnGroupSelectRequired, в котором можно запросить пользователя об имени группы и при успешном вызове метода SetGroup изменить значение переменной Handled в True.
Список опубликованных статей для выбранной группы можно получить путем вызова метода GetArticleList — изменяя параметры этого метода можно получить либо список всех статей, либо одну из них с конкретным номером. При этом вызывается одно из событий — OnHeaderList (если используется удаленное кэширование) или OnHeaderListCacheUpdate (при локальном кэшировании). В обоих случаях информация о статье помещается в структуру HeaderRecord. Поле PrID этой структкры содержит целочисленный идентификатор, который в дальнейшем потребуется для получения содержания статьи; поле PrFromAddress — имя автора публикации; поле PrSubject — тему статьи; PrReplyTo — e-mail автора публикации.
После получения идентификатора статьи (поле HeaderRecord.PrID) можно извлечь ее содержимое. Для этого вызывается метод NMNNTP.GetArticle, в качестве параметра он принимает идентификатор статьи. Как было описано в предыдущем абзаце, вызывается событие OnArticle или OnArticleCacheUpdate — и при отсутствии или наличии локального кэширования соответственно. При получении этого сообщения становятся определенными структуры NMNNTP: Header — заголовок статьи; Body — текст статьи; Attachments — список присоединенных файлов. Если же статья с данным идентификатором отсутствует, то вызывается событие OnInvalidArticle. Для уменьшения траффика сети вместо метода NMNNTP.GetArticle можно вызывать методы GetArticleBody или GetArticleHeader — для получения только содержания либо только заголовков статьи — присоединенные файлы при этом не загружаются. При этом необходимо описывать обработчики событий OnBody (OnBodyCacheUpdate) или OnHeader (OnHeaderCacheUpdate) соответственно.
Присоединенные файлы автоматически загружаются при получении статьи и помещаются в каталог, имя которого определяется в свойстве AttachFilePath.
Для помещения собственной публикации на сервере необходимо при вызове метода Connect корректно определить имя пользователя и пароль. Они доступны от владельца сервера, обычно после регистрации. Далее необходимо заполнить структуру PostRecord, в которой определены поля: группа новостей, тема публикации, адрес электронной почты отправителя публикации и адрес для отправки обратных сообщений (Reply). Кроме того, определяется список PostBody — содержание публикации и список Attachments — присоединенных файлов. После этого вызывается метод PostArticle. При успешной передаче статьи и присоединенных файлов будет вызвано событие OnPosted, а при сбое — OnPostFailed.
В каталоге …\Nntp имеется проект NntpDemo, в котором реализованы все описанные выше методы и обработчики событий. Этот проект ссылается на полезный сервер новостей forums.borland.com.
Компонент NMPOP3
Компонент NMPOP3 используется для получения электронной почты с POP3-почтового сервера. Для обращения к почтовому серверу используется порт 110. Перед вызовом метода Connect необходимо заполнить свойства Host, UserID и Password. После успешного соединения становится значимым свойство MailCount — число сообщений на сервере, и если они имеются, то можно обращаться за сообщениями. Как правило, работа с POP3-сервером начинается с команды List. Эта команда обращается к серверу и возвращает списки номеров сообщений и их размер. При вызове этой команды необходимо сделать обработчик события OnList. Этот обработчик будет вызываться для каждого сообщения, имеющегося для клиента UserID; в списке его параметров имеется размер сообщения и его номер.
Зная номера сообщений, можно получить их с сервера. Для этого используется вызов двух методов — GetMailMessage и GetSummary. В качестве параметров оба метода принимают номер сообщения, информацию о котором следует передать в клиентское приложение. В процессе выполнения этих методов вызываются события OnRetrieveStart и OnRetrieveEnd. По окончании выполнения метода GetSummary заполняется структура Summary, в которой содержится информация о теме сообщения, о том, кто отправил сообщение, его размер, идентификатор и заголовок. После окончания работы метода GetMailMessage заполняется структура MailMessage. Свойство MailMessage содержит информацию: текст сообщения, список присоединенных файлов, адрес отправителя, тему, заголовок и идентификатор сообщения. Кроме того, если сообщение содержало присоединенные файлы и свойство NMPOP3.AttachFilePath ссылается на существующий каталог, то присоединенные файлы будут перенесены в этот каталог.
Если свойство DeleteOnRead компонента NMPOP3 равно True, то после успешного прочтения сообщение будет удалено с сервера. Удалить сообщение с сервера можно и с помощью команды DeleteMailMessage. В качестве параметра эта команда принимает номер сообщения, которое требуется удалить. При удалении сообщения с POP3-сервера не происходит его физического удаления до тех пор, пока клиент не отсоединится от сервера. Поэтому все удаленные сообщения до окончания сессии можно восстановить при помощи команды Reset.
В каталоге …\Pop3 имеется проект Pop3Demo, в котором реализованы все описанные выше методы, за исключением восстановления удаленных сообщений на сервере.
Компонент NMSMTP
Компонент NMSMTP используют для отправки электронной почты через почтовый сервер Internet. Обычно сервер электронной почты проверяет порт 25. Перед началом работы необходимо вызвать метод Connect; для его вызова помимо адреса SMTP-сервера и порта необходимо указать имя пользователя в свойстве UserID. Перед отправкой почтового сообщения необходимо заполнить структуру PostMessage c обязательными полями: кому адресовано сообщение (свойство ToAddress, может быть, список адресов), адрес отправителя (свойство FromAddress) и текст сообщения (свойство Body, список). Желательно также заполнить поля: тема (Subject), имя отправителя (свойство FromName), организация (Organization), ToCC, ToBCC. При необходимости отправить присоединенные файлы, их имена и пути следует поместить в список PostMessage.Attachments. Далее следует вызвать метод SendMail. При этом если ряд параметров имеет некорректные значения, то вызываются следующие обработчики событий: OnHeaderUncomplete — если отсутствует значение свойств структуры PostMessage ToAddress или FromAddress; OnRecipientNotFound — неверно указан ToAddress; OnAttachmentNotFound — не найдены файлы, указанные в списке Attachments. Если определены присоединенные файлы, то они перекодируются либо в MIME-, либо в UUEncode-форматы в зависимости от значения свойства NMSMTP. EncodeType — при этом вызываются события OnEncodeStart и OnEncodeEnd. Перед началом отправки почты вызывается событие OnSendStart. Если передача информации была завершена успешно, то вызывается событие OnSuccess, в противном случае вызывается событие OnFailure.
Из других методов следует отметить Verify, который в качестве параметра принимает строку-имя пользователя и возвращает логическую переменную: True, если данный пользователь зарегистрирован на SMTP-сервере, и False — в противном случае. Также имеется метод ExpandList, который в качестве параметра принимает имя пользователя. Если данный пользователь зарегистрирован на SMTP-сервере, то будет вызван обработчик события OnMailListReturn, в котором будет определен электронный адрес интересующего пользователя, например:
250 Trepalin S.V. IFAV <trep@ism.ac.ru>.
В каталоге ..\Smtp имеется проект SmtpDemo, в котором реализованы описанные выше методы компонента NMSMTP. К недостаткам проекта следует отнести возможность только однократного вызова метода ExpandList: повторный вызов этого метода не приводит ни к каким результатам, и, чтобы получить информацию о новом пользователе, требуется повторный запуск приложения.
Компоненты NMStrm и NMStrmServ
Компоненты NMStrm и NMStrmServ передают двоичные данные, записанные в поток, через протокол TCP/IP. Компоненты работают в паре — один из них размещается на сервере, другой — на клиенте. Поскольку механизм передачи данных не является стандартным, для номера порта следует использовать большие числа. Базовый метод компонента NMStrm — PostIt, в качестве параметра используется ссылка на поток. При вызове этого метода автоматически устанавливается соединение с компьютером Host. В компоненте NMStrmServ необходимо создать обработчик события OnMSG, который будет вызываться всякий раз при получении потока от клиента. Так же, как и для обсуждаемых выше компонентов NMMsg и NMMsgServ, серверу может быть передано свойство клиента FromName. Аналогично, бессмысленное свойство Host экспонируется на серверном компоненте NMStrmServ.
В каталоге ..\Strm имеется проект StrmDemo, который демонстрирует возможности данных компонентов. Однако проект имеет ошибку — достаточно часто после пересылки данных и появления сообщения «Stream Send» не происходит отсоединение от сервера. Визуально это приводит к зависанию клиентского приложения и к отсутствию реакции на кнопку Close. О причинах ошибки можно только догадываться — исходных кодов нет, и проанализировать их невозможно. И еще одна ошибка данного компонента — картинка, которая пересылается на сервер, искажается. Скорее всего это связано с перекодировкой данных.
Компонент NMUDP
Компонент NMUDP — это компонент, который совмещает сервер и клиент в одном. Он осуществляет пересылку данных с использованием протокола UDP (User Datagram Protocol). Порт для этого протокола не стандартизован, и поэтому свойствам LocalPort и RemotePort следует присваивать большие значения. Если данный компонент устанавливается на сервере, то ему достаточно указать свойство LocalPort и создать обработчик события OnDataReceived. Если же компонент будет находиться на клиентском компьютере, то необходимо присвоить значения свойствам RemotePort и RemoteHost. При необходимости послать данные на сервер вызывается либо метод SendStream, в качестве параметра которого передается ссылка на поток, либо метод SendBuffer.
Компонент работает некорректно: при попытке передать потоки больших размеров генерируется исключение в момент вызова метода SendStream. Максимально допустимый размер потока я не устанавливал — исключение стабильно генерируется при размере потока 234 Kбайт.
В каталоге ..\Udp имеется пример UDPDemo, который работает стабильно, по-видимому вследствие небольшого размера пересылаемых данных.
Компоненты Powersock и NMGeneralServer
Данные компоненты объединяет то, что их ни в коем случае нельзя использовать в приложениях! Они представляют собой инкапсулированные в виде компонентов классы, которые являются базовыми для написания собственных клиентов (Powersock) и серверов (NMGeneralServer). Абстрактных методов эти компоненты не содержат, но часть виртуальных методов просто ничего не делает — их рекомендуется переписать программисту.
Понятно, что примеры с их использованием отсутствуют. В файлах помощи рекомендуется приобрести исходные коды этих компонентов в фирме NetMasters (http://www.netmastersllc.com).
Компоненты, работающие с данными
Компонент NMUUProcessor
Компонент NMUUProcessor осуществляет перекодировку двоичных файлов в MIME- или UUENCODE-формат в зависимости от его свойства Method. Также этот компонент осуществляет декодирование — генерирует двоичный файл из MIME- или UUENCODE-содержимого. Для перекодировки данных в MIME или UUENCODE необходимо создать два потока (Stream) — входной (обычно это бывает TFileStream, который содержит файл, подлежащий перекодировке) и выходной (обычно это TMemoryStream — результат помещается в память компьютера). Соответственно ссылка на первый поток присваивается свойству InputStream, а на второй поток — OutputStream. Затем вызывается метод Encode. При необходимости декодировать MIME- или UUENCODE-содержимое поступают также, но вызывают метод Decode. При вызове методов Encode первоначально вызывается событие OnBeginEncode, и по окончании перекодировки вызывается событие OnEndEncode. Соответственно пара событий OnBeginDecode и OnEndDecode вызывается при обращении к методу Decode.
Назначение этого компонента просто и очевидно — через Internet разрешается пересылать не все 256 символов ASCII-таблицы. Поэтому двоичные файлы перекодируются в данные, которые можно пересылать через Internet. Примеры с использованием этого компонента отсутствуют.
Компонент NMURL
Компонент NMURL перекодирует строки в формат HTML и осуществляет обратную перекодировку. Необходимость подобной перекодировки очевидна — предположим, клиенту необходимо показать строку: "X <H5>Y". Если такую строку непосредственно поместить в HTML-страницу, то любой браузер попытается интерпретировать <H5> как команду. NMURL конвертирует такого типа строки в такие, которые будут восприняты браузерами как текстовое содержимое. Для перекодировки в HTML-формат строка, которая подлежит перекодированию, помещается в свойство InputString. Затем следует прочитать значение свойства Encode — оно имеет тип String и доступно только во время выполнения. В вышеприведенном примере возвращаемый результат будет "X+%3CH5%3EY". Если эту последовательность символов поместить на HTML-странице, то при ее показе в браузере будет виден первоначальный текст.
Данный компонент осуществляет и обратную перекодировку — используя HTML-строку, он генерирует строку, которую будет видеть пользователь при показе HTML-страницы в Web-браузере. Опять же такую строку помещают в свойство InputString, но затем следует прочитать свойство Decode. Примеры с использованием данного компонента отсутствуют в стандартной поставке Delphi 4, но он достаточно прост.
Компонент HTML
Компонент HTML — единственный визуальный Internet-компонент в Delphi 4. Он предназначен для получения и показа HTML-страниц и, по сути дела, является Web-браузером. Этот компонент представляет собой ActiveX-компонент, и при поставке приложений с его участием необходимо поставлять файл HTML.ocx. Этот браузер качественно показывает HTML-страницы — текст и графику в форматах GIF, JPEG, BMP, XBM; работает с гиперссылками; показывает элементы формы; таблицы. Но он не работает со скриптовыми программами и не показывает компоненты ActiveX. Компонент достаточно сложный, но к нему существует детальный файл помощи, поэтому здесь будут описаны только ключевые методы и свойства.
Для начала навигации необходимо вызвать метод RequestDoc, который в качестве параметра принимает URL. Если этот параметр — пустая строка, то используется значение свойства RequestURL. При вызове этого метода вызываются события: OnDoRequestDoc и затем OnBeginRetrieval. Далее документ помещается в компонент и становится доступным пользователю для просмотра. Затем можно использовать гиперссылки или формы для получения новых документов. В любой момент можно вновь обратиться к методу RequestDoc. Для прекращения загрузки документа следует использовать метод Cancel.
Компонент имеет более 40 свойств, причем около 30 из них относится к визуальному оформлению документа — можно определить все шрифты, цвета, подчеркивания и т.д. Пользоваться этими свойствами не составляет труда. Имеется также ряд методов для вывода документа на печать. К сожалению, отсутствуют принятые в стандартных браузерах методы: Next, Previous, Home, Search.
Данный компонент можно использовать как парсер HTML-документов. Для этого его свойство ElemNotification устанавливается в True, при этом, как только встретится новый элемент HTML-страницы, будет вызываться сообщение OnDoNewElement. В этом сообщении в качестве параметров приводятся элементы и их содержимое.
Я не советую использовать данный компонент для показа HTML-документов в форме. Вместо него рекомендуется использовать ActiveX-компонент WebBrowser, который можно вставить в палитру компонентов при импорте ActiveX-компонента из библиотеки Microsoft Internet Control Type Library. Преимущества компонента WebBrowser — следующие в нем работают активные элементы, и он имеет методы Next, Previous, Home, Search. Фактически этот компонент полностью инкапсулирует все возможности Microsoft Internet Explorer. Кроме того, Internet Control Library входит в стандартную поставку Windows начиная с версии Windows 95 OSR2, а в Windows NT — начиная с Service Pack 3. Поэтому при его использовании нет необходимости поставлять дополнительно *.ocx-файлы. Так же, как и компонент HTML, WebBrowser можно использовать в качестве парсера — для этого в текущий проект необходимо импортировать библиотеку типов, экспонируемую MSHTML.DLL (она должна быть не ниже 2-й версии!).
Заключение
Помимо рассмотренных в данном обзоре стандартных компонентов имеется достаточно большое число компонентов, разработанных другими фирмами или частными лицами. Некоторые из них описаны в публикуемой в данном номере статье Н. Елмановой «Полезные компоненты для пользователей Delphi и С++ Builder: кое-что для Internet». Надеюсь, что создание приложений для работы с Интернетом доставит вам удовольствие.
КомпьютерПресс 5'1999