Книга
Книга
САМОУЧИТЕЛЬ IСАМОУЧИТЕЛЬ IОсновыОсновыСтатические HTML-страницыСтатические HTML-страницыCGI-программирование с применением языка PHPCGI-программирование с применением языка PHPТехнология создания активных серверных страниц ASPТехнология создания активных серверных страниц ASP
САМОУЧИТЕЛЬ I
САМОУЧИТЕЛЬ I
Основы
Основы
Статические HTML-страницы
Статические HTML-страницы
CGI-программирование с применением языка PHP
CGI-программирование с применением языка PHP
Технология создания активных серверных страниц ASP
Технология создания активных серверных страниц ASP
Вадим Будилов
п d о пда м м и jр ва н и я „л. Интернета
Разработка динамических страниц с помощью JavaScript
Программирование для Интернета -требование жизни
Вадим Будилов
Основы программирования ««»Интернета
Санкт-Петербург«БХВ-Петербург>2003
УДК ББКУДК ББК681.3.06
УДК ББК
УДК ББК
32.973.202
Б90
Будилов В. А.
Б90 Основы программирования для Интернета. — СПб.: БХВ-Петербург, 2003. — 736 с.: ил.
ISBN 5-94157-254-9
Книга адресована тем, кто хочет научиться профессионально программировать для Интернета. В сжатой форме на примерах показаны основные методы создания приложений для глобальной сети, начиная от простейших HTML-страничек и заканчивая основными принципами построения распределенных многоуровневых систем. Даются основы CGI-программирования с использованием языка PHP. Рассмотрено создание полноценных распределенных CGI-приложений на основе языков общего назначения, таких как C++ или Java. Отдельно представлены возможности платформенно-независимых технологий Java и CORBA.
Для интернет-программистов
УДК 681.3.06
ББК 32.973.202
Группа подготовки издания:
Главный редакторЗам главного редактора Зав. редакцией Редактор Компьютерная верстка Корректор Дизайн обложки Зав. производствомГлавный редакторЗам главного редактора Зав. редакцией Редактор Компьютерная верстка Корректор Дизайн обложки Зав. производствомЕкатерина Кондукова Евгений Рыбаков Анна Кузьмина Эльвира Максунова Натальи Караваевой Виктория Пиотровская Игоря Цырульникова Николай ТверскихЕкатерина Кондукова Евгений Рыбаков Анна Кузьмина Эльвира Максунова Натальи Караваевой Виктория Пиотровская Игоря Цырульникова Николай Тверских
Главный редактор
Зам главного редактора Зав. редакцией Редактор Компьютерная верстка Корректор Дизайн обложки Зав. производством
Главный редактор
Зам главного редактора Зав. редакцией Редактор Компьютерная верстка Корректор Дизайн обложки Зав. производством
Екатерина Кондукова Евгений Рыбаков Анна Кузьмина Эльвира Максунова Натальи Караваевой Виктория Пиотровская Игоря Цырульникова Николай Тверских
Екатерина Кондукова Евгений Рыбаков Анна Кузьмина Эльвира Максунова Натальи Караваевой Виктория Пиотровская Игоря Цырульникова Николай Тверских
Лицензия ИД Ne 02429 от 24.07.00. Подписано в печать 21.01.03.
Формат 70x100V16. Печать офсетная. Усл. печ. л. 59,34
Тираж 3000 экз. Заказ Ne 691"БХВ-Петербург", 198005, Санкт-Петербург, Измайловский пр., 29.
Гигиеническое заключение на продукцию, товар Ne 77.99 02.953.Д.001537.03.02от 13.03.2002 г. выдано Департаментом ГСЭН Минздрава России.
Отпечатано с готовых диапозитивовв Академической типографии "Наука" РАН199034, Санкт-Петербург, 9 линия, 12.
ISBN 5-94157-254-9ISBN 5-94157-254-9© Будилов В А, 2003
ISBN 5-94157-254-9
ISBN 5-94157-254-9
© Оформление, издательство "БХВ-Петербург", 2003
Содержание
Введение1
Глава 1. Интернет сегодня3
Что такое Интернет?3
Как появился Интернет?3
Что такое WWW?4
Немного статистики5
Время пользования Интернетом5
Половые различия6
Статистика в таблицах6
Общая статистика пользователей Интернета6
Коммерческое использование Интернета9
Цифры, факты и выводы9
Интернет и коммерция10
Глава 2. HTML — язык гипертекстовой разметки13
Знакомство с HTML15
Текст24
Свойства элементов26
Цвет27
Шрифт29
Средства HTML-форматирования32
Простая таблица32
Вложенные таблицы35
Свойства элемента <table>36
Объединение ячеек в таблице37
Ссылки37
Текстовая ссылка37
Адрес ссылки39
Ссылки и рисунки41
Фон страницы43
Свойства рисунков44
Форматирование изображений с использованием таблиц48
Ссылки и изображения50
Изображения-карты52
Редактирование HTML-документов54
Универсальный редактор SlickEdit54
Фреймы59
Создание и использование фреймов59
Формы60
Пример формы61
Элементы, составляющие тело формы61
Атрибуты свойства type62
Тип Checkbox62
Тип File62
Тип Password63
Тип Radio65
Глава 3. Динамические HTML-страницы67
Основы JavaScript68
События69
Функции72
Фреймы и JavaScript72
Меню навигации74
Документы, создаваемые "налету"76
Создание новых окон76
Закрытие окна78
Создание документов по ходу работы79
Строка состояния81
Создание временных задержек83
Движущийся текст84
Объекты JavaScript85
Объект Date86
Объект массива Array88
Объект Math88
Картинки и JavaScript88
Предварительная загрузка картинок, используемых на страничке88
Изменение картинок в ответ на действия пользователя89
Объектная модель в JavaScript90
Языки, основанные на классах, и языки, использующие структуру объектов-прототипов90
Определение класса91
Наследование и подклассы91
Вставка и удаление свойств92
Обзор различий92
Пример иерархии объектов93
Задание иерархии объектов94
Свойства объекта97
Наследование свойств97
Добавление новых свойств99
Конструкторы. Более гибкие инструменты100
Наследование свойств105
Локальные и унаследованные значения105
Взаимосвязь экземпляров объектов107
Конструкторы и глобальная информация108
Множественное наследование109
Глава 4. Активные страницы111
Устанавливаем сервер Sambar112
Простейший ASP-скрипт115
Вопросы безопасности116
Сравниваем С и CScript116
Различия между CScript и С118
Различия в синтаксисе118
Различия в операторах118
Различия в переменных119
Различия в структуре119
ASP от Microsoft119
Первый файл с ASP120
Примеры ASP-страниц121
Обработка информации, полученной из HTML-форм121
Работа с ASP-компонентами125
Резюме134
Глава 5. Создание серверных приложений на языке PHP135
Устанавливаем Web-сервер136
Устанавливаем интерпретатор PHP139
Работаем с PHP143
Обработка HTML-форм143
Отправка писем с помощью PHP146
Работа с базами данных150
Работаем с MySQL157
Выбор отдельного ряда157
Выбор столбца162
Сортировка строк результата164
Использование нескольких таблиц одновременно169
Получаем информацию о базах данных и таблицах172
Некоторые классические примеры175
Выбор максимального значения176
Работа с сетью180
Работа с изображениями181
Передача файла серверу186
Группы функций языка PHP187
PHP и ASP190
Глава 6. Самостоятельные Java-приложения193
Апплеты193
Первый апплет194
Как построен апплет196
Методы для прорисовки и для обработки событий196
Графические элементы199
Компоненты пользовательского интерфейса в апплетах199
Метод add199
Метод remove199
Метод setLayout.199
Возможности апплетов201
Работа с апплетами202
Отображение документов в браузере202
Пересылка сообщений от одного апплета другому207
Метод getApplet — находим апплет по имени208
Звук в апплетах216
Метод getAudioCUp (вариант 1)217
Метод getAudioCUp (вариант 2)217
Как получить из апплета системные свойства217
Работа с потоками в апплетах221
Сеть и апплеты224
Примеры апплетов234
График234
Часы244
Простой график249
Легковесная таблица, заполняемая пользователем в браузере251
Сервлеты273
Структура API для создания сервлетов с использованием JSDK276
Пакет javax.sei-vlet.http276
Интерфейсы276
Классы277
Пакет javax.servlet277
Интерфейсы277
Классы278
Иерархия интерфейсов278
Иерархия классовТ19
Как создавать апплет279
Работа с Cookeis280
Чтение НТТР-заголовков283
Общая информация284
Глава 7. CGI-приложения на языке С4-4-289
Первое приложение289
Последовательность создания CGI-приложения на С4-4-294
Что такое CGI?307
Как работает CGI?307
Переменные окружения в CGI308
Командная строка309
CGI-ввод309
Пример309
CGI-вывод309
Анализируемые заголовки309
Статус-коды310
Категория Success 2хх310
Категория ошибок Error 4хх, 5хх310
Коды перенаправления Redirection Зхх311
Примеры с анализируемыми заголовками312
CGI-заголовки. Метаинформация о документах и объектах316
Allowed: Method317
Public: Method.317
Content-Length: int317
Библиотека cgic317
Вывод заголовка318
Ввод текста318
Вывод318
Обработка полей для установки флажка318
Числовой ввод319
Обработка альтернативного выбора319
Обработка множественного выбора320
Работа с изображениями322
Отладка CGI-приложений323
Описание некоторых функций библиотеки cgic323
Протокол HTTP326
Некоторые обозначения327
Параметры протокола327
Версия HTTP327
Универсальный идентификатор ресурса URI328
Сообщения HTTP328
Заголовки сообщений329
Основные поля заголовка329
Запросы330
Строка запроса Request-Line330
Методы330
Запрашиваемый URI Request-URI330
Поля заголовка запроса Request-Header331
Ответ331
Строка состояния Status-Line331
Код статуса Status-Code и пояснение Reason-Phrase331
Заголовки ответа332
Сущность сообщения Entity332
Заголовок Entity-Header.332
Тело сущности Entity-Body333
Типы Туре333
Методы333
Глава 8. Работаем с J2EE335
Обзор возможностей современного интернет-программирования на языке Java336
Сервисы и контейнеры J2EE337
Клиентские приложения343
Web-клиент343
Апплет343
Клиент-приложения343
Web-компоненты344
Работа сервера J2EE344
Бизнес-компоненты345
Уровень информационной системы предприятия346
Технология вызова удаленных методов RMI346
Удаленные интерфейсы, объекты и методы347
Создание приложений с использованием RMI348
Разработка компонентов348
Компиляция и создание классов Stub348
Регистрация классов348
Запуск приложения349
Java и сокеты349
"Бешеный" клиент355
Пример с компонентами EJB•.358
Установка и конфигурирование сервера358
Запуск сервера358
Первое 32ЕЕ-приложение с компонентами EJB361
Код удаленного интерфейса364
Код домашнего интерфейса364
Код класса компонента EJB365
Компилируем код366
Упаковка компонента EJB367
Создаем приложение-клиент371
Создаем экземпляр компонента EJB373
Вызываем методы компонента EJB373
Создаем Web-клиент376
Задаем ссылки382
Задание имен JNDI382
Размещаем приложение на сервере384
Запускаем приложение387
Пример с JSP — серверными страницами Java389
Структура программного интерфейса J2EE391
Пакеты392
Глава 9. Работаем с CORBA395
О технологии CORBA395
Об архитектуре CORBA396
Что такое Java IDE?397
Разработка приложений на основе Java IDE397
Задание удаленного интерфейса397
Компиляция классов удаленного интерфейса398
Имплементация сервера398
Имплементация клиента398
Запуск приложения398
Первый пример с Java IDE398
Программа-сервер YabServer.java400
Приложение Servant с именем YabServant401
Программа-клиент YabClient.java402
Запуск приложения404
Запуск сервера YabServer.class404
Запуск клиента YabClient.class406
Компилятор idlj406
Файл _YabImplBase.java406
Файл _YabStub.java408
Файл Yab.java410
Файл YabHelper.java410
Файл YabHolder.java412
Файл YabOperations.java413
C++ CORBA и Visibroker413
Первый пример415
Что происходит в программе client.с?420
Что происходит в программе-сервере server.c?420
Получение ссылки на базовый РОА424
Создание дочернего РОА424
Имплементация методов Servant425
Активизируем РОА426
Активизация объектов427
Ожидание клиентских запросов427
РОА430
Поэтапное создание и использование РОА432
Политики для РОА433
Создание РОА435
Соглашение о названиях для РОА435
Получаем базовый rootPOA436
Задание свойств РОА436
Создание и активация РОА436
Активация объектов437
Использование объектов Servant и менеджеров объектов Servant442
Активаторы объектов Servant444
Локатор объектов Servant447
Управление РОА с помощью менеджера РОА450
Состояние ожидания451
Активное состояние451
Состояние отклонения запросов451
Неактивное состояние452
Свойства приема и перенаправления452
Задаем свойства серверных движков453
Свойства менеджеров серверных соединений454
Свойства менеджера454
Свойства прослушивателя454
Свойства диспетчера455
Обработка запросов457
Язык IDL458
Что получается после компиляции458
Файлы, содержащие классы Stub-клиентов, сгенерированные компилятором462
Задание типа указателя462
Автоматическое управление памятью. Класс interface name>_var462
Методы скелетонов, сгенерированные компилятором IDL466
Шаблон класса, создаваемый компилятором IDL466
Задание атрибутов интерфейса в IDL467
Однонаправленные операции, не возвращающие значений468
Описание интерфейса, наследованного от другого интерфейса468
Клиентская часть469
Инициализация брокера ORB469
Связь с объектами469
Что происходит во время связи с объектом470
Вызов операций на сервере470
Работа со ссылкой на объект470
Является ли ссылка на объект равной nil471
Получение ссылки nil471
Копирование ссылки на объект471
Высвобождение ссылки на объект471
Получение количества ссылок на объект472
Преобразование ссылки в строку472
Определение имен объектов и интерфейсов473
Определение положения объекта473
Несуществующий объект474
Сужение ссылки на объект474
Расширение ссылки474
Резюме474
Глава 10. Примеры интернет-приложений475
Интернет-аукцион475
Структура базы данных482
Таблица event482
Таблица user482
Таблица item483
Функционирование сайта483
Регистрация новых пользователей483
Продажа товаров489
Покупка товаров507
Транспортная интернет-биржа526
Сервер eMap527
Серверные скрипты528
Приложение 1. Элементы HTML545
Элементы формирования структуры HTML-документа545
<HTML>545
<HEAD>545
<BASE>546
<1S1NDEX>546
<META>546
<L1NK>547
<SCR1PT>548
<STYLE>549
<T1TLE>549
<BODY>550
Элементы форматирования текста551
<В>551
<BASEFONT>551
<BIG>551
<FONT>552
</>552
<5>, <STRIKE>552
<SMALL>552
<SUB>553
<SUP>553
<TT>553
<U>554
Элементы форматирования фраз554
<ACRONYM>554
<ADDRESS>554
<CITE>555
<CODE>555
<DEL>555
<DFN>555
<EM>556
<INS>556
<KBD>556
<Q>557
<SAMP>557
<STRONG>557
<VAR>557
Блочные элементы форматирования558
<BLOCKQUOTE>558
<BR>558
<CENTER>559
<DIV>559
<HR>559
<HI>...<H6>560
<P>560
<PRE>561
<SPAN>561
Элементы для работы co списками562
<L1>562
<DIR>562
<DL>563
<DT>563
<DD>564
<MENU>564
<OL>565
<UL>565
Элементы гиперссылок566
<А>566
Рисунки и карты ссылок567
<IMG>567
<МАР>568
<AREA>568
Элементы таблицы569
<TABLE>569
<CAPTION>570
<THEAD>570
<TFOOT>571
<TBODY>572
<COLGROUP>573
<COL>574
<TR>575
<TD>, <TH>576
Элементы формы577
<FORM>577
<INPUT>577
<SELECT>579
<OPTION>579
<TEXTAREA>580
<BUTTON>580
<LABEL>581
<FIELDSET>581
<LEGEND>582
Элементы фрейма582
<FRAMESET>582
<FRAME>583
<NOFRAMES>584
<IFRAME>584
Элементы выполняемых программ585
<APPLET>585
<PARAM>586
<OBJECT>587
Приложение 2. Основные встроенные объекты
Microsoft ASP IIS589
Объект Application589
Коллекции589
Методы589
События590
Объект ObjectContext590
Методы590
События590
Объект Request590
Коллекции590
Свойства591
Методы591
Коллекция Form591
Коллекция QueryString593
Коллекция ServerVariables594
Коллекция Cookies597
Объект Response598
Коллекции598
Свойства598
Методы598
Метод Write599
Объект Server599
Свойства599
Методы599
Объект Session600
Коллекции600
Свойства600
Методы600
События601
Метод Contents.Remove601
Приложение 3. Функции в языке PHP. Краткая справка603
Функции для работы с сервером Apache603
Функции для работы с массивами603
Математические функции BCMath для работы с числами произвольной точности611
Функции для работы с календарем612
Функции даты и времени614
Функции для работы с каталогами619
Функции для работы с файловой системой620
Почтовые функции632
Математические функции633
Функции для работы с базами данных MySQL639
Функции для работы с сетью647
Функции для работы с графическим форматом PDF650
Функции вызова внешних программ659
Функции для работы со строками660
Функции для работы с URL673
Функции для работы с переменными674
Приложение 4. Основные объекты JavaScript679
Объект Anchor679
Свойства679
Методы680
Объект Applet680
Свойства680
Методы680
Объект Area680
Объект Array680
Параметры680
Свойства681
Методы681
Объект Boolean683
Параметры683
Описание683
Свойства684
Методы684
Объект Button685
Описание685
Свойства685
Методы686
Объект Checkbox686
Функции обработки событий686
Описание686
Свойства687
Методы687
Объект Date687
Параметры688
Описание688
Свойства688
Методы688
Объект Document690
Свойства691
Методы692
Объект Event694
Свойства695
Объект FileUpload696
События696
Свойства696
Методы697
Объект Form697
События697
Свойства697
Методы698
Объект Frame698
Объект Function699
Параметры699
Свойства700
Методы701
Объект Hidden701
Свойства702
Объект History703
Свойства703
Методы703
Объект Image704
Параметры704
События705
Свойства705
Методы706
Объект Java706
Объект JavaArray706
Свойства707
Объект JavaClass707
Объект JavaObject707
Параметры707
Объект Layer708
События708
Свойства708
Методы710
Объект Link710
События710
Свойства711
Методы711
Объе кт Location712
Свойства713
Методы713
Объект Math713
Свойства714
Методы714
Предметный указатель715
Введение
Эта книга содержит материал, детальное изложение которого заняло бы несколько томов. Она научит новичка не только основам создания Web- сайтов, различным техникам создания интерактивных Web-страниц, расскажет об основах Web-программирования, но и приподнимет завесу секретов профессионального программирования, используемых при создании распределенных приложений, предложит примеры с протоколами уровня приложений при работе в сети. В первой главе представлен общий обзор Интернета, глава поможет узнать, для чего и как пользоваться сетью Интернет. Вторая глава посвящена рассмотрению основ и технике создания базовых HTML- страниц. При создании Web-страниц вручную, с использованием языка HTML, большую помощь может оказать профессиональный многоцелевой редактор SlickEdit. Способы создания динамических страниц рассмотрены в третьей главе. Особое внимание уделено созданию динамических страниц с использованием языка JavaScript.
В книге отводится достойное место способам создания серверных сценариев. Четвертая глава рассказывает об основах создания активных серверных страниц для Web-сервера Sambar, уделено внимание рассмотрению технологии ASP от компании Microsoft. Пятая глава дает сведения об основах CGI программирования с применением языка PHP. В ней приведены базовые примеры, наиболее часто используемые при решении реальных задач. Особое внимание уделено рассмотрению примеров работы с базами данных. Шестая глава содержит примеры создания интернет-приложений с использованием языка Java. Здесь представлены технологии создания Java- апплетов и Java-сервлетов. В седьмой главе рассказывается о том, как создаются самостоятельные приложения на языке C++ с использованием CGI- библиотек. В восьмой главе внимание сконцентрировано на создании серверных компонентов с применением технологий, воплощенных создателями пакета J2EE. Рассмотрены примеры создания компонентов EJB и серверных
страниц JSP. Анализу основ технологии CORBA посвящена девятая глава. Вступительная часть главы содержит примеры создания клиент-серверных приложений на уровне сокетов.
Книга может быть полезна как начинающим программистам, студентам, так и всем, кто хочет быстро включиться в работу и освоить современные методы программирования в сжатые сроки. В десятой главе рассмотрены учебные и практические примеры, содержатся листинги работающих коммерческих приложений. В конце книги в приложениях приведены справочные материалы.
Интернет сегодняИнтернет сегодня
Интернет сегодня
Интернет сегодня
Глава 1
Что такое Интернет?
Интернет — это компьютерная сеть, которую объединяет общий протокол TCP/IP, с помощью которого различные компьютеры общаются друг с другом, обмениваясь информацией. Интернет объединяет различные компьютеры независимо от платформы, т. е. от аппаратного и программного обеспечения. Мультиплатформенность делает Интернет мощным средством, стремительный рост сети продолжается по настоящее время. Сеть Интернет — это не столько способ, который соединяет компьютеры друг с другом, сколько способ объединения компьютеров в одно общее целое, объединения тысяч и сотен тысяч компьютеров в общую сеть. Термином "сеть" люди пользуются каждый день, но лишь немногие по-настоящему понимают, что за этим стоит.
Как появился Интернет?
Многие считают, что Интернет возник совсем недавно, скажем, лет десять назад, но действительность такова, что датой его рождения разумнее было бы считать шестидесятые годы 20-го века. Именно в те годы возникла сеть ARPAnet (Advanced Research Projects Agency Network), которую финансировал департамент обороны США. Затем появилась идея использовать сеть для нужд работников правительства, ученых и исследователей. От их взаимодействия зависела эффективность работы, не нужно было заново изобретать колесо, вновь повторять то, что уже было сделано другими. Люди могли получать информацию из сети, исчезла необходимость обращаться за нужными материалами по почте или вновь повторять уже проведенные исследования. Все, что было необходимо сделать, — это соединиться с удаленным компьютером и получить требуемую информацию.
В 80-е годы прошлого века сеть ARPAnet получила новый толчок в своем развитии. Была использована более новая по тому времени архитектура сети, позволившая повысить ее быстродействие. Нововведение было осуществлено благодаря национальному фонду поддержки науки NSF (National Science Foundation). Обновленная сеть получила название Интернет, она объединила правительственные суперкомпьютеры, компьютеры учебных заведений и исследовательских центров. Первоначально Интернет был призван осуществлять четыре основные функции: передавать электронную почту, поддерживать группы новостей, использовать удаленный доступ по протоколу telnet и передачу файлов по протоколу ftp. Глобальной сети-паутины тогда еще не было. Электронная почта предоставляет возможность пользователям напрямую обмениваться сообщениями. Группы новостей — это своеобразные доски объявлений, помещаемые туда сообщения доступны для обзора всем желающим. Любой может разместить там свое объявление. Протокол telnet позволяет пользоваться удаленным компьютером на расстоянии, ftp (File Transfer Protocol) дает возможность передавать файлы с одного компьютера на другой. Сейчас Интернет представляет собой международную сеть, объединяющую миллионы людей во всем мире. Менее десяти лет назад пользователи сети представляли собой группу избранных, элиту. Даже после того, как большинство американских университетов освоили Интернет и предоставили доступ к сети всем студентам, все равно оставался некоторый вакуум, отделявший "сетевиков" от "обычных людей". Почти каждый, имевший в то время дело с сетью, был достаточно хорошо знаком с системой UNIX, а дружественный пользователю интерфейс воспринимался с долей иронии. Интернет долгое время продолжал оставаться клубом избранных. Предполагалось сделать его открытой системой, доступной для всех, ожидалось экспоненциальное развитие Интернета. Возникали проблемы. Даже профессионалы использовали Интернет не только в профессиональных и образовательных целях, но и для общения. К клубу избранных присоединялось все большее и большее число людей, причем безо всякого приглашения.
Что такое WWW?
WWW — это World Wide Web, всемирная паутина. WWW основан на использовании ряда протоколов передачи информации, спецификаций отображения информации и языков программирования для использования в сети Интернет. Для паутины можно указать один основной протокол, это протокол HTTP (HyperText Transfer Protocol) — протокол передачи гипертекста. Web — это не единая физическая сущность, паутина скорее напоминает телефонную сеть. Интернет — это физическая сеть, a WWW — это один из способов использования этой сети. Гипертекст — это система, которая позволяет программисту создавать простые тексты и делать их интерактивными. В текстах могут использоваться ссылки, по которым пользователь может
автоматически делать переход, если у него появляется такое желание. Идея создания WWW состоит в том, чтобы предоставить удобный способ доступа к огромным ресурсам Интернета. Но для этого необходимо создавать специальные страницы, в которых используется язык гипертекстовой разметки HTML (HyperText Markup Language).
Web — не единственный способ использования Интернета. Современное программирование обладает арсеналом мощных средств программирования с использованием протокола TCP/IP и других протоколов, нашедших широкое применение в сети. Многие системы программирования реализуют современные возможности доступа к удаленным и распределенным объектным кодам, причем сетевые детали, включая детали протоколов, скрыты от глаз пользователей для удобства и за отсутствием надобности. Сетевые средства программирования более низкого уровня, в том числе сокеты, по- прежнему при необходимости доступны программисту.
Немного статистики
Статистка порой может служить неплохим оружием: за цифрами может скрыть истинный смысл, исказив его. Но нередко статистика, особенно, если она "добросовестная" и сделана не в рекламных или политических целях, может оказаться весьма полезной. Вот ответы пользователей Интернет, которые пользовались им не позднее трех месяцев до опроса. Если участник опроса пользовался Интернетом в течение последних 24 часов, то просили указать, в каком месте он это делал:
66% опрошенных последний раз пользовались Интернетом на работе;
44% пользовались сетью у себя дома;
О 8% воспользовались им из школы.
Те, кто пользовался Интернетом в последние 24 часа перед опросом, в среднем указали по 1,2 места, откуда они входили в сеть. Несмотря на то, что наибольший процент опрошенных пользуются Интернетом у себя дома, более длительное время в сети проводят пользователи со своего рабочего места. При этом отметим, что опрос поводился в августе, когда большинство студентов находится на каникулах и не пользуется Интернетом так, как в течение учебного года.
Время пользования Интернетом
Оказывается, что время, проведенное в Интернете, у тех, кто пользовался сетью в последние три месяца, весьма значительно. В среднем в неделю пользователь проводит в сети Интернет примерно пять с половиной часов. Это для тех, кто пользовался сетью, плюс два с половиной часа в неделю на прочие услуги онлайн. Если пересчитать это время на все население страны,
то, например, для США и Канады это составило бы по 35 минут Интернета в неделю на каждого взрослого старше 16 лет. Прочие услуги онлайн уступают этой величине более чем в два раза. Чтобы представить нагляднее, что значит эта цифра, заметим, что 35 минут в неделю — это среднее время на одного человека, затрачиваемое на просмотр видеокассет, взятых напрокат.
Половые различия
В основном пользователи Интернета — это мужчины. Мужчины составляют 66% от общего количества пользователей Интернета. Более того, мужчины пользуются сетью Интернет чаще и продолжительнее, чем женщины.
Статистика в таблицах
Среди тех, кто прибегал к услугам Интернета в течение последних 24 часов, большее количество людей пользовалось WWW и меньшее — для того, чтобы получить или послать электронную почту. Статистические данные для пользователей, кто входил в Интернет за последние три месяца, показаны в табл. 1.1.
Таблица 1.1. Распределение предпочтений в использовании служб Интернета
Цель использования сети Интернет
Процент пользователей
Доступ к WWW-ресурсам
72
Электронная почта
65
Скачивание программных продуктов
31
Участие в интерактивных дискуссиях
21
Участие в неинтерактивных обсуждениях
36
С целью использования удаленного компьютера
31
Для прослушивания аудио или просмотра видео в реальном времени
19
Общая статистика пользователей Интернета
Вот интересные статистические данные, которые показывают, кто является постоянным пользователем Интернета. Данные касаются жителей США и Канады:
25% пользователей имеют доход на семью, превышающий 80 тысяч долларов в год. Такой доход имеют лишь 10% семей;
50% являются либо высококвалифицированными профессионалами, либо занимают управленческие должности. В США и Канаде профессионалы и менеджеры составляют 27% всех работников;
45% пользователей Интернета закончили, по крайней мере, колледж. Процент закончивших колледж, по отношению ко всему населению, составляет 29%.
Табл. 1.2-1.5 содержат данные по возрастному распределению пользователей сети Интернет, по уровню образования, профессии и по доходу.
Таблица 1.2. Распределение пользователей Интернета по возрасту
Возраст, лет
Пользователи WWW
Процент от всего населения
16-24
22%
18%
25-34
30%
21%
35-44
26%
22%
45-54
17%
16%
55 и старше
5%
21%
Таблица 1.3. Распределение пользователей Интернета по уровню образования
Уровень образования
Пользователи WWW
Процент от всего населения
Незаконченная школа
4%
11%
Школа
8%
33%
Училище
1%
3%
Незаконченное высшее
24%
24%
Университет
29%
17%
Аспирантура
9%
3%
Ученая степень
26%
8%
Таблица 1.4. Распределение пользователей Интернета по профессиям
Профессия
Пользователи WWW
Процент от всего населения
Высококвалифицированные профессионалы
37%
18%
Технические специальности
12%
6%
Администраторы и менеджеры
14%
9%
Служащие
3%
6%
Таблица 1.4 (окончание)
Профессия
Пользователи WWW
।Процент от
всего населения
Продавцы
5%
5%
Рабочие сферы обслуживания2%
4%
Разнорабочие
2%
7%
Рабочие
1%
3%
Строители
1%
11%
Военнослужащие
2%
1%
Студенты (дневная мы обучения)
и вечерняя фор-16%
8%
Пенсионеры и неработающие2%
17%
Таблица 1.5. Распределение пользователей Интернета по уровню дохода в месяц
Доход на семью
Пользователи WWWПроцент от всего населения
Менее $1 ОК
1%
7%
$10—19.9К
4%
9%
$20—29.9К
7%
12%
$30-39.9К
10%
14%
$40—49.9К
10%
11%
$50-59.9К
11%
9%
$60—69.9К
9%
6%
$70—79.9К
10%
4%
$80—89.9К
7%
3%
$90—99.9К
4%
2%
$100К и более
14%
5%
Не указали
14%
17%
В табл. 1.6. приведен обзор предпочтений пользователей сети среди тех, кто хотя бы один раз использовал Интернет в тех или иных целях.
Таблица 1.6. Распределение предпочтений пользователей сети
Цель использования
Процент
Поиск информации о товаре, продукте, услуге
55%
Поиск информации о компании или организации
60%
Поиск прочей информации
73%
Покупка товара или услуги
14%
Путешествие по сети Интернет
90%
Коммерческое использование Интернета
Примерно половина людей старше 16 лет пользовалась Интернетом по работе или в бизнесе. В табл. 1.7 приведена статистика использования Интернета в деловых целях.
Таблица 1.7. Использование Интернета в деловых целях
Цели использования
Процент WWW-пользователей
Сотрудничество с коллегами
54%
Информация по публикациям
33%
Сбор информации
77%
Исследования
46%
Продажа товаров или услуг
13%
Покупка товаров или услуг
23%
Услуги для покупателей и поддержка пользователей
38%
Внутренняя связь
44%
Техническая поддержка и информация
50%
Цифры, факты и выводы
Подведем итоги:
порядка 100 млн. человек старше 16 лет, проживающих в США и Канаде, имеют доступ к сети Интернет;
примерно треть из них регулярно прибегают к услугам Интернета;
примерно четвертая часть из всех, имеющих доступ к сети, пользуются WWW;
пользователи WWW — основная группа потребителей коммерческих приложений;
практически все потребители услуг сети Интернет — это высокообразованные люди, как правило, профессионалы;
количество людей, сделавших покупки через Интернет, составляет несколько миллионов;
основные пользователи Интернета — это мужчины;
часто Интернетом пользуются с рабочего места;
□ пользователь сети проводит в среднем пять — семь часов в неделю в Интернете;
□ время пользования Интернетом примерно равно времени просмотра видеокассет, взятых напрокат;
□ опросы, проведенные в Интернете, не отражают мнение населения в целом.
Теперь у нас есть некоторое представление о том, что такое Интернет и кто им пользуется.
Интернет и коммерция
Программирование для Интернета тесно связано с созданием новых коммерческих услуг. По каким причинам коммерческое предприятие станет выводить свой бизнес в Интернет? Существует несколько таких причин.
□ Представить себя в сети. Во всем мире существует более сотни миллионов людей, имеющих доступ к сети. Неразумно было бы упускать столь значительный сегмент рынка. Уже сейчас дать свой адрес в сети Интернет примерно так же естественно, как оставить свой номер телефона. Это справедливо как для больших, так и для малых компаний.
□ Использование возможностей сети. Информацию о своей компании можно связать со ссылками, которые могут быть полезны клиентам. Покупатель или клиент сможет получить полный пакет необходимых услуг сразу и без затруднений.
□ Размещение рекламы. Вряд ли стоит сомневаться в том, что наиболее часто используемым ресурсом являются Желтые Страницы. Это неплохой способ рекламы.
□ Уменьшить расходы на традиционную рекламу. Реклама в Интернете обойдется гораздо дешевле, чем обычная реклама. Причем реклама в Интернете может быть интерактивной, рекламная страница может содержать ссылку, по которой можно послать ответ или любую необходимую информацию о пользователе, "зашедшем" на страницу.
Поддержка клиентов. Интернет предоставляет удобный способ оказания быстрой помощи покупателям, заказчикам, клиентам.
Публичный имидж. Средства информации становятся наиболее продвинутой сферой применения профессий, связанных с электронной коммуникацией, поскольку их главный продукт — информация, а информация может быть передана наиболее быстрым способом именно через средства электронной связи. Это и быстро, и дешево и удобно. Чем быстрее ваше пресс-заявление достигнет получателя, тем в более выгодной ситуации вы окажетесь.
Создание международных рыночных инетрнет-площадей. WWW предоставляет богатые возможности международного коммерческого сотрудничества как для крупных фирм, так и для мелкого и индивидуального бизнеса.
Доступ 24 часа в сутки и 7 дней в неделю без обеда и выходных. Интернет позволяет работать 24 часа в сутки. Доступ к вашим ресурсам не будет ограничен временем и пространством, разделяющим вас и вашего покупателя. Не будет ни временных, ни пространственных границ. Если покупатель находится, скажем, в Токио, в три часа ночи по московскому времени ему захотелось приобрести ваш товар, но у него нет о нем полной информации, то поможет Интернет. Там покупатель получит исчерпывающую информацию о товаре и прямо через Интернет поместит свой заказ.
Глава 2
HTML — язык гипертекстовой разметки
Любой пользователь компьютера знает: для того, чтобы "войти в Интернет", необходимо запустить на своем компьютере программу-браузер, например, Internet Explorer (рис. 2.1) или Netscape Navigator (рис. 2.2). Браузер — это программа-клиент, т. е. программа, которая формирует запросы, направляет их серверу, получает от сервера ответы на свои запросы. Полученные ответы обрабатываются клиентской программой. Браузер "общается" с Web-серверами, общение это происходит по сетям с использованием различных протоколов. После того, как ответ от сервера получен, браузер обрабатывает полученную информацию и отображает в окне в удобном для пользователя виде.
Как правило, браузер может быть физически расположен на компьютере, удаленном от сервера на многие сотни и тысячи километров. Расстояния здесь не помеха. Чтобы сервер и клиент "понимали" друг друга, необходимо задать правила, по которым они будут общаться. Одним из основных правил, существующих в Интернете, является то, что общение между членами сети осуществляется в соответствии с теми или иными протоколами, т. е. в соответствии со строго установленными стандартами. Один из основных протоколов в Интернете — это протокол TCP/IP. Средства программирования позволяют нам использовать возможности этого способа общения достаточно легко. Дело в том, что во многих языках программирования существуют особые классы, созданные для работы с сокетами. Открывая сокет, мы создаем соединение между клиентом и сервером, которое будет использовать именно протокол TCP.
Протокол TCP позволяет передавать информацию в различном виде. Посредством этого протокола можно передавать сообщения, сформатирован- ные с использованием протоколов более высокого уровня, например, почту по протоколам SMTP или POP, в том числе он позволяет передавать Web- информацию по протоколу HTTP. Протокол HTTP — это основной протокол
передачи информации сервером браузеру. Аббревиатура HTTP обозначает Hyper Text Transfer Protocol, т. e. протокол передачи гипертекста. Мы вернемся к этому протоколу в дальнейшем и рассмотрим его более подробно в главах, посвященных CGI-программированию. Сейчас нам важно то, что с использованием протокола HTTP происходит обмен информацией между Web-серверами и Web-клиентами (в частности, браузерами). Основным форматом документов, которые передают Web-сервера браузерам, до сих пор остается формат гипертекстовой разметки. Основные файлы, получаемые браузерами, — это HTML-файлы.
Рис. 2.1. Microsoft Internet ExplorerРис. 2.1. Microsoft Internet ExplorerI ffi The Phone Company (TPC1NT1 Homepage - Microsoft Internet Explorer - [Working Ofili... М1и1 HI ffi The Phone Company (TPC1NT1 Homepage - Microsoft Internet Explorer - [Working Ofili... М1и1 HFile Edit View Favorites Tools HelpFile Edit View Favorites Tools HelpThe Phone Company's Remote Printing ServiceThe Phone Company's Remote Printing Service4^4^TPC FAX —Welcome to the TPC home page. The TPC service is a collection of FAX servers you may use to send a fax to many locations around the world.TPC FAX —Welcome to the TPC home page. The TPC service is a collection of FAX servers you may use to send a fax to many locations around the world.Send A FaxSend A FaxOther languages: English. Italian. German Send a fax from your web browser Send a fax from your e-mail softwareOther languages: English. Italian. German Send a fax from your web browser Send a fax from your e-mail software® Check Coverage® Check CoverageBefore you send a fax verify tire fax number is covered by one of our cells.A complete coverage listing is also available.Before you send a fax verify tire fax number is covered by one of our cells.A complete coverage listing is also available.Рис. 2.2. Netscape NavigatorРис. 2.2. Netscape Navigator
Рис. 2.1. Microsoft Internet Explorer
Рис. 2.1. Microsoft Internet Explorer
I ffi The Phone Company (TPC1NT1 Homepage - Microsoft Internet Explorer - [Working Ofili... М1и1 H
I ffi The Phone Company (TPC1NT1 Homepage - Microsoft Internet Explorer - [Working Ofili... М1и1 H
File Edit View Favorites Tools Help
File Edit View Favorites Tools Help
The Phone Company's Remote Printing Service
The Phone Company's Remote Printing Service
4^
4^
TPC FAX —
Welcome to the TPC home page. The TPC service is a collection of FAX servers you may use to send a fax to many locations around the world.
TPC FAX —
Welcome to the TPC home page. The TPC service is a collection of FAX servers you may use to send a fax to many locations around the world.
Send A Fax
Send A Fax
Other languages: English. Italian. German Send a fax from your web browser Send a fax from your e-mail software
Other languages: English. Italian. German Send a fax from your web browser Send a fax from your e-mail software
® Check Coverage
® Check Coverage
Before you send a fax verify tire fax number is covered by one of our cells.
A complete coverage listing is also available.
Before you send a fax verify tire fax number is covered by one of our cells.
A complete coverage listing is also available.
Рис. 2.2. Netscape Navigator
Рис. 2.2. Netscape Navigator
Браузер получает HTML-файл, который содержит текст, ссылки на другие ресурсы (программы, рисунки, звук и т. д.), ссылки на другие HTML-файлы, анализирует (парсирует) полученный HTML-код, затем, в соответствии с полученной информацией, выводит текст и изображение на экран компьютера и, при необходимости, на другие периферийные устройства (музыку — в динамики, печатаемый текст — на принтер и т. п.). То, каким именно способом будет представлена полученная информация, зависит от программы-клиента. Различные браузеры могут по-разному отображать один и тот же HTML-файл. Язык HTML предоставляет средства для создания Web-страниц.
Знакомство с HTML
HTML-файл имеет расширение htm или html. Браузер определяет тип файла именно по его расширению. HTML-файл должен подчиняться определенным правилам, описанным в стандарте HTML. Рассмотрим в качестве примера произвольный HTML-файл. Это будет простой HTML-файл, однако на его примере можно рассмотреть некоторые важные элементы языка HTML. Как этот файл будет выглядеть в окне браузера, показано на рис. 2.2. CDOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<HTML>
<head>
<meta http-equiv="Content~Type"
content="text/HTML; charset=iso-8859-l">
<meta name="FORMATTER" content="Microsoft Frontpage 2.0">
<meta name="GENERATOR" content="Microsoft Frontpage 2.0">
<title>The Phone Company (TPC.INT) Homepage</title>
</head>
<body bgcolor="#FFFFFF">
<p align="left"><script language="JavaScript"> <!-- var usedynamic=false;
if ("3" <= navigator.appVersion.charAt(0)) { usedynamic=true;
tag_sendafax=new Image(150,55);
tag_sendafax.src="images/tag-sendafax.gif";
tag_sendafax_h=new Image(150,55);
tag_sendafax_h.src="images/tag-sendafax-h.gif";
tag_coveragetag_coverage= new Image(150,55);= new Image(150,55);
tag_coverage
tag_coverage
= new Image(150,55);
= new Image(150,55);
tag_coverage.src :
tag_coverage_h;
tag_coverage_h.src ■
= "images/tag-coverage.gif";
= new Image(150,55);
= "images/tag-coverage-h.gif";
tag_faqhow = tag_faqhow.src = tag_faqhow_h = tag_faqhow_h.src =
new Image(150,55);
"images/tag-faqhow.gif";
new Image(150,55);
"images/tag-faqhow-h.gif";
tag_client = tag_client.src = tag_client_h = tag_client_h.src =
new Image(150,55); "images/tag-client.gif"; new Image(150,55);
"images/tag-client-h.gif";
tag_server = tag_server.src = tag_server_h = tag_server_h.src =
new Image(150,55);
"images/tag-server.gif";
new Image(150,55);
"images/tag-server-h.gif";
/ / —>
</script>
<а name="top"x/a></p>
<div align="left">
<table border="0" cellpadding="0" cellspacing="O" width="100%">
<tr>
<td valign="top" width="100%"xdiv align="left”>
<table border="0" cellpadding="O" cellspacing="O" width="100%" <tr>
<td valign="top" width="100%"xh2xfont color="#0000FF">T</font><font color="#000000"> he </fontxfont color="#0000FF">P</font>
<font color="#000000">hone
</fontXfont color="#0000FF">C</font>
<font color="#000000">ompany's Remote Printing
Service</fontx/h2>
<pxfont size="3">Welcome to the TPC home page. The TPC service is a collection of FAX servers you may use to send a fax to many locations around the world. </font></p>
</td>
</tr>
<tr>
<td align="right" valign="top" width="100%">
<font size="2">0ther languages: </font>
<a href="tpc_home.html">
<font size="2 ">English</fontx/a>
<font size="2">, </font>
<a href="tpc_home_it.html">
<font size="2">ltalian</fontx/axfont size="2">, </font>
<a href="tpc_home_gr.html">
<font size="2">German</fontx/ax/td>
</tr>
</table>
</div></td>
<td valign="top" width="80">
<img src="images/horn80x80.gif" alt="TPC Logo" width="80" height="80"x/td>
</tr>
</table>
</div><div align="left">
<table border="0" cellpadding="O" cellspacing="O" width="100%">
<tr>
<td width="175"xa href="sendfax.html" onmouseover="if (usedynamic)
{ tag_sendafax_slot.src = tag_sendafax_h.src; }" onmouseout="if (usedynamic)
{ tag_sendafax_slot. src = tag_sendafax. src; } "ximg src="images/tag-sendafax.gif" alt="Send a FAX" border="0" width="175" height="55" name="tag_sendafax_slot"x/ax/td> <td width="100%"Xul>
<lixa href="sendfax.html">Send a fax from your Web browse r</ax/li>
<lixa href="faxbyemail.html">Send a fax from your e-mail software</a></li>
</ul>
</td>
</tr>
<tr>
<td width="175"xa href="verify.html" onmouseover="if (usedynamic)
{ tag_coverage_slot.src = tag_coverage_h.src; }" onmouseout="if (usedynamic)
{ tag_coverage_slot.src = tag_coverage.src; }"><img src="images/tag-coverage.gif" alt="Check Coverage" border="0" width="175" height="55" name="tag_coverage_slot"x/ax/td>
<td width="100%"Xul>
<li>Before you send a fax <a href="verify.html">verify the fax number </a>is covered by one of our cells. </li>
<li>A <a href="fax_cover_auto.html">complete coverage listing</a> is also available.</li>
</ul>
</td>
</tr>
<tr>
<td width="175"xa href="faq/index.html" onmouseover="if (usedynamic)
{ tag_faqhow_slot.src = tag_faqhow_h.src;}" onmouseout="if (usedynamic)
{ tag_faqhow_slot.src = tag_faqhow.src; } "ximg src="images/tag-faqhow.gif" alt="Questions & Answers" border="0" width="175" height="55" name="tag_faqhow_slot"X/a></td>
<td width="100%"xul>
<li>Read the <a href="faq/index.html">TPC FAQ</a> for answers to frequent questions.</li>
<li>What to do <a href="faq/failureadvice.html">when Remote Printing Services doesn't work</a>.</li>
<li>Email from the <a href="faq/maillist.html">TPC-RP mailing list</a> is also archived for you to read</li> </ul>
</td>
</tr>
<tr>
<td width="175"xa href="clients/index.html"
onmouseover="if (usedynamic)
{ tag_client_slot.src = tag_client_h.src; }" onmouseout="if (usedynamic)
( tag_client_slot.src = tag_client.src; } ">
<img src="images/tag-client.gif" alt="Client Software" border="0" width="175" height="55" name="tag_client_slot"x/ax/td>
<td width="100%"xul>
<li>Download <a href="clients/index.html">software for your computer</a> to help you compose and send a FAX. </li>
<li>Tips for using <a href="clients/eudorawinhelp.html">Eudora for
.Windows</a> or for the <a
href="clients/eudoramachelp.html">Mac</ax/li>
</ul>
</td>
</tr>
<tr>
<td width="175"xa href="servers/index.html" onmouseover="if (usedynamic)
( tag_server_slot.src = tag_server_h.src; }" onmouseout="if (usedynamic)
( tag_server_slot.src = tag_server.src; } ">
<img src="images/tag-server.gif" alt="Server Software" border="0" width="175" height="55" name="tag_server_slot"x/ax/td>
<td width="100%"xul>
<li>TPC is a volunteer organization that needs your help. <a href="servers/index.html">Software</a> is provided here to set up a fax server (Cell) and provide fax coverage in your local area. </li>
<lixstrong>Ask your ISP to read our </strong><a href="servers/salespitch.html"xstrong>Sales Pitch</strongx/axstrong> and join the project !</strongx/li> </ul>'
</td>
</tr>
</table>
</div>
<p> </р>
<div align="left”>
<table border="0" cellpadding="O" cellspacing="O" width="100%">
<tr>
<td valign="top">Listing of <a
href="alternateservices,html">other FAX services</a> on
the internet.<p>Listing of <a href="index.html">TPC
Mirror Sites</a> around the world.</p>
</td>
<td valign="top"> </td>
</tr>.
</table>
</div>
<P>The TPC network, is powered by <a href="http://www.hylafax.org/" target="_blank">
HylaFAX</a>, the world's most powerful freely available enterprise-class fax software.
</P>
<hr>'
<div align="left">■
<table border="0" cellpadding="O" cellspacing="O" width="100%">
<tr>
<td valign="top" width="12%"Xa href="tpc_home.html#top">Top
<img src="images/q_scrollup.gif" align="top" border="0"
width=" 9" height="ll"x/a></td>
<td valign="top" width="12%"><a href="tpc_home.html">Home
<img src="images/q_home.gif" align="top" border="0" width="10" height="10"x/a> </td>
<td valign="top" width="12%">
<script language="JavaScript">
function ShowCredits()
{alert("\nSpecial thanks to Stephen Herzog of Secure Design
for Web page content and layout."+
"\n\nThese pages inspired, and in part based on the pioneering work of Peter Shipley (shipley@dis.org)");
// —>
</script>
<a href="tpc_home.html#credits" name="credits" onclick="ShowCredits(); return false;">Credits <img src="images/q_note.gif" align="top" border="0" width="ll" height="ll”x/ax/td>
<td valign="top" width="12%"xa href="sitemap.html">Site map</a>
<a href="sitemap.html">
<img src="images/q_search.gif" align="top" border="0"
width="ll" heigh t="ll"x/ax/td>
<td valign="top" width="12%">
<a href="faq/contactus.html">Email
<img src="images/q_mailto.gif" align="top" border="0"
width="14" height="10"x/ax/td>
<td valign="top" width="12%">
<a href="sponsors/index.html">Sponsors
<img src="images/q_money.gif" align="top" border="0"
width="14" height="10"x/a> </td>
<td align="right" valign="top" width="25%">
<script language="JavaScript">
if (Date.parse(document.lastModified) != 0)
document.write ('<font size="l"xl>Last modified: '
+ document.lastModified
+ '</fontx/SMALL>') ;
// —>
</script>
</td>
</tr>
</table>"
</div>
</body>
</HTML>.
Не будем углубляться в детали, сейчас для нас важным является то, что всякий HTML-файл состоит из элементов. Элемент начинается с ярлыка. Что такое ярлык HTML? Ярлык — это слово, помещенное в угловые скобки. Наличие угловых скобок вокруг слова или набора слов — признак того, что эти слова являются ярлыком. Ярлыки бывают открывающими и закрывающими. Закрывающий ярлык отличается от открывающего тем, что он начинается с символа косая черта / сразу после угловой скобки. Существует конечный набор HTML-ярлыков, которые могут использоваться внутри HTML-файла довольно свободно. Некоторые HTML-элементы могут быть вложены друг в друга. Вот пример ярлыка: <titie>. Соответствующий ему закрывающий ярлык выглядит как </titie>. Ярлык — смысловой аналог английского слова tag. Ярлык — это этикетка, которая прикрепляется к элементу. Каждый HTML-элемент начинается с открывающего ярлыка и заканчивается закрывающим ярлыком. HTML элемент состоит из открывающего ярлыка, тела HTML элемента и закрывающего ярлыка. Не каждый элемент HTML с необходимостью должен включать в себя все указанные компоненты, но открывающий ярлык должен присутствовать всегда. Открывающий ярлык может иметь атрибуты. Эти атрибуты описывают свойства элемента, к которому относится открывающий ярлык. Ярлык и элемент — это не одно и то же. Так, например, с помощью ярлыка <script> описывается HTML-элемент, в котором записана программа-сценарий. Программа-сценарий — это не ярлык, но элемент. Этот элемент описан при помощи ярлыков <script> и </script>. Иногда может возникать неоднозначность в употреблении слов атрибут и свойство, которые могут относиться как к ярлыку, так и к элементу. Такая неоднозначность не может привести к существенной двусмысленности, так как все свойства элемента HTML описываются в виде значений атрибутов ярлыка, а все атрибуты ярлыка имеют значения, которые определяют те или иные свойства элемента HTML.
Различные элементы HTML могут иметь разную структуру. Это могут быть и текст, и ссылки на рисунки, и программы, и вставляемые элементы. Подробное описание HTML-элементов можно найти в документации. Сейчас! для нас важно, что всякий HTML-файл должен содержать в себе элемент <html>... </html>. Этот элемент включает в себя всю информацию, содержащуюся в HTML-файле. Файл начинается с ярлыка <html> и заканчивается ярлыком </нтмь>. В вышеописанном примере мы видим строку cdoctype html public "-//ietf//dtd html//en">. Это описание типа документа. Оно также может присутствовать в HTML-файле. Описание типа документа сообщает о том, что данный документ является HTML- документом. Дело в том, что помимо HTML-документов в Интернете используются и другие форматы, в частности, документы на расширенном языке разметки XML. Этот язык (скорее, метаязык) предусматривает возможность конкретизации значений определенных ярлыков (а сами ярлыки могут быть произвольными), для этого используется описание типа
документа (DTD). В целях унификации, HTML-файлы также могут содержать в себе описание типа документа. В этом случае типом документа будет HTML. В некотором смысле (но не вполне) HTML является частным случаем XML, однако, это не совсем верно хотя бы потому, что элементы HTML не всегда должны быть строго вложены друг в друга, тогда как стандарт XML допускает только строгое вложение, т. е. если вложенный элемент объявляется после того, как появился открывающий ярлык родительского элемента, то закрывающий ярлык вложенного элемента должен появиться до того, как будет записан закрывающий ярлык родительского элемента.
HTML-страничка может быть создана при помощи простейшего текстового редактора. Откроем Блокнот (Notepad) и напишем:
<HTML> Это простая HTML-страница.</HTML>
Запомним файл под именем first.htm и загрузим файл в браузер.
Как правило, в HTML-страницах помимо ярлыка <html> используется несколько других обязательных ярлыков. Среди них ярлык <head> (и обязательный </head>) для написания заголовка HTML-странички. Здесь можно указать название странички. Название должно быть помещено между ярлыками <titie> и </titie>. В стандартных браузерах заголовок будет показан в верхней части главной рамки основного окна.
; Файл first1.htmj
<HTML>
<head>
<title>
На этой станице в HTML-файле содержатся все ярлыки
</title>
</head>
<body>
Все основные ярлыки присутствуют здесь.
</body>
</HTML>
В файле firstl.htm мы использовали заголовок, расположив его в верхней части файла между ярлыками <head> и </head>. В заголовке может быть указано название страницы с помощью ярлыков <titie> и </titie>. В блоке заголовка часто используется мета-комментарий <meta>...</meta>. После заголовка мы использовали другую пару ярлыков: <body> и </body>, между которыми располагается основной текст документа.
Текст
Главным компонентом содержимого HTML-страниц является текст. Для форматирования текста в HTML используются специальные ярлыки. Наличие пробелов, табуляций, переводов строки и других специальных символов в тексте документа не влияет на вид представления текста в окне браузера.
Рассмотрим файл text.htm.
j Файл text.htm
<HTML>
<head>
<title>
Простейший случай — неформатированный текст.
</title>
</head>
<body>
Неформатированный текст.
Что такое HTML?
Язык HTML не является языком программирования в том смысле, в каком мы привыкли представлять себе такие языки программирования, как С, C++, Java, Basic и другие. При помощи HTML мы не сможем написать полноценное приложение, которое бы работало в системе MS-DOS, Windows или какой-либо другой ОС. HTML предназначен для создания документов, размещаемых на Web- сервере, доступ к которому осуществляется по сети Интернет.
</body> И
</HTML>
Глава 1. Неформатированный текст. Что такое HTML? Язык HTML не является языком программирования в том смысле, в каком мы привыкли представлять себе такие языки программирования, как С, C++, Java, Basic и другие. При помощи HTML мы не сможем написать полноценное приложение, которое бы работало в системе MS-DOS, Windows или какой- либо другой ОС. HTML предназначен для создания документов, размещаемых на Web-сервере, доступ к которому осуществляется по сети Интернет.
Рис. 2.3. Неформатированный текст
В окне браузера мы увидим неформатированный сплошной текст (рис. 2.3), несмотря на то, что в HTML-файле текст разделен на абзацы и строки.
Сейчас, чтобы понять в чем суть происходящего, отформатируем этот текст. Для отделения одного параграфа от другого используется ярлык <р>. В начале каждого параграфа мы будем ставить ярлык <р>. Закрывающий ярлык </р> необязателен. Для оформления иерархии заголовков в HTML используются ярлыки <hi>, <h2>, <ьз> и т. д. Парные закрывающие ярлыки необходимо помещать сразу после окончания текста соответствующего заголовка. Теперь новый файл textl.htm имеет вид:
<HTML>■
<head>
<title>
Простой форматированный текст
</title>.
</head>
<body>
<р>
<Ы>Глава 1. Форматирование текста </hl>
<р>
<Ь2>Что такое HTML?</h2>
<р>
Язык HTML не является языком программирования в том смысле, в каком мы привыкли представлять себе такие языки программирования, как С, C++, Java, Basic и другие. При помощи HTML мы не сможем написать полноценное приложение, которое бы работало в системе MS-DOS, Windows или какой-либо другой ОС. HTML предназначен для создания документов, размещаемых на Web-сервере, доступ к которому осуществляется по сети Интернет.
</body>
</HTML>
Вновь сформатированный текст выглядит так, как показано на рис. 2.4.
3 Простой ф^4атировапнь1Й текст -" Microsoft Internet Explorer [Working Offline] ЙЙ Bl
1 hk г1*' ^'v Fi и t T< ob H-Ip
Глава 1. Форматирование текста
Что такое HTML?
Язык HTML не является языком программирования в том смысле, в каком мы привыкли представлять себе такие языки программирования, как С, C++, Java, Basic и другие. При помощи HTML мы не сможем написать полноценное приложение, которое бы работало в системе MS-DOS, Windows или какой-либо другой ОС. HTML предназначен для создания документов, размещаемых на Web-сервере, доступ к которому осуществляется по сети Интернет.
Рис. 2.4. Форматированный текст
Свойства элементов
В ярлыках можно указать значения свойств соответствующих элементов. Давайте выровним заголовки нашего текста по центру, а фрагмент основного текста выделим в отдельный абзац и выровним по правому краю. Для этого используется свойство align в ярлыках <ы> и <Ь2>, а также в ярлыке <р> в обычном тексте основного содержания параграфа (рис. 2.5.). Измененный файл text2.htm выглядит так, как показано в примере ниже.
i Файл text2.htm
L:
<HTML>
<head>
<title>
Заголовок страницы
</title>
</head>
<body bgcolor= "white">
<p>
<hl align= "сепРег">Глава 1. Название главы </hl>
<p>
<h2 align= "сепРег">Заголовок</Ь2>•
<p>
Текст как он есть. Язык HTML не является языком программирования в том смысле, в каком мы привыкли представлять себе такие языки программирования, как С, C++, Java, Basic и другие.
<р align= "right">npn помощи HTML мы не сможем написать полноценное приложение, которое бы работало в системе MS-DOS, Windows или какой-либо другой ОС. HTML предназначен для создания документов, размещаемых на Web-сервере, доступ к которому осуществляется по сети Интернет.
</body>
</HTML>
II51 Заголовок страницы - Microsoft Internet Explorer - [Working Offline]
-|П|х
File Edit View Favorites Tools Help
Глава 1. Название главы
Заголовок
Текст как он есть. Язык HTML не является языком программирования в том смысле, в каком мы привыкли представлять себе такие языки программирования, . как С, C++, Java, Basic и другие.
При помощи HTML мы не сможем написать полноценное приложение, которое бы работало в системе MS-DOS, Windows или какой-либо другой ОС. HTML предназначен для создания документов, размещаемых на Web-сервере, доступ к : которому осуществляется по сети Интернет.
Рис. 2.5. Выравнивание фрагментов текста
Существует множество различных свойств у многих ярлыков. Так, для ярлыка <body> мы можем задать цвет фона — свойство bgcolor. Цвет фона можно указать либо в виде стандартного слова, обозначающего цвет, например, white или yellow, либо в виде шестнадцатеричной величины RRGGBB, где параметры RR показывают интенсивность красного цвета, GG — интенсивность зеленого, ВВ — интенсивность синего цвета в аддитивной модели цветовосприятия. Белому цвету соответствует значение #FFFFFF = "White". В файле text2.htm задан белый цвет фона.
Цвет
Цвет является свойством многих текстовых элементов. Изменив свойство "цвет" для параграфа, мы легко можем выделить тот или иной фрагмент текста цветом. Произвольный цвет можно задать документу или другим
элементам. В качестве примера изменим вид нашей странички на "негатив". Для этого необязательно задавать цвет для каждого ярлыка по отдельности. Здесь можно использовать общий для всего фрагмента текста ярлык <font>, с помощью которого задаются параметры используемого шрифта, в том числе его цвет. Файл text3.htm выглядит следующим образом.
[ Файл text3.htm
<HTML>
<head>
<title>
Цвет и текст
</title>
</head>
<body bgcolor= "#000000">
<font color= "#FFFFFF">
<P>
<hl align= "сепбег">Глава 1. Название главы </hl>
<P>
<h2 align= "сепбег">3аголовок второго уровня
</h2>'
<P>
Язык HTML не является языком программирования в том смысле, в каком мы привыкли представлять себе такие языки программирования, как С, C++, Java, Basic и другие.
<р align= "right">npn помощи HTML мы не сможем написать полноценное приложение, которое бы работало в системе MS-DOS, Windows или какой-либо другой ОС. HTML предназначен для создания документов, размещаемых на Web-сервере, доступ к которому осуществляется по сети Интернет.•
</font>
</body>
</HTML>
Здесь в ярлыке <body> мы задали черный цвет (#000000) фона, а перед основным текстом поставили ярлык <font> с указанием свойства "цвет" color= "#FFFFFF" — это белый цвет. В конце текста мы поставили закрывающий ярлык </font>. На рис. 2.6 мы видим, как выглядит окно браузера с загруженным файлом text3.htm.
Д Цвет и текст - Microsoft Internet Explorer - [Working Offline] №B
Глава 1. Название главы
Заголовок второго уровня
Язык HTML не является языком программирования в том смысле, в каком мы привыкли представлять себе такие языки программирования, как С, C++, Java, Basic и другие.
При помощи HTML мы не сможем написать полноценное приложение, которое бы работало в системе MS-DOS, Windows или какой-либо другой ОС. HTML предназначен для создания документов, размещаемых на Web- сервере, доступ к которому осуществляется по сети Интернет.
Рис. 2.6. Измененные цвета
Шрифт
Чтобы задать свойства шрифта, полезно использовать ярлык <font>. Внутри угловых скобок ярлыка можно указать различные свойства шрифта: его цвет, размер, внешний вид. Обязательно использовать закрывающий ярлык </font>.
Изменим файл text2.htm так, чтобы каждый параграф выглядел по-своему, имел свой собственный цвет. В конце файла продемонстрируем, как можно изменять размер шрифта.
Измененный файл, назовем его text4.htm, выглядит так:
Файл text4.htm
<HTML>
<head>
<title>
Шрифты
</title>
</head>
cbody bgcolor="white">
<P>
<font color="blue">
<hl align= "сепЬег">Глава 1. Заголовок первого уровня </Ы>
</font>
<Р>
<font color="green">
<h2 align= "сепЬег">Заголовок второго уровня</Ь2>
</font>
<P>
<font color="maroon">
Язык HTML не является языком программирования в том смысле, в каком мы привыкли представлять себе такие языки программирования, как С, C++, Java, Basic и другие.
</font>
<р align= "right">npn помощи HTML мы не сможем написать полноценное приложение, которое бы работало в системе MS-DOS, Windows или какой-либо другой ОС. HTML предназначен для создания документов, размещаемых на Web-сервере, доступ к которому осуществляется по сети Интернет.
<Р>
Демонстрируем изменение размеров шрифта.
<р аИдп="сепЬег">Обычный шрифт (его величину можно указать в свойстве basefont.
<р align="center"xfont з!ге=+1>Указан размер size=+K/font>.
<р align="center"xfont з!ге=+2>Указан размер size=+2</font>.
<р align="center"xfont з!ге=+3>Указан размер size=+3</font>.
<р align="center"xfont з!ге=+4>Указан размер size=+4</font>.
</body>
</HTML>-
Отображенный на экране браузера файл text4.htm выглядит так, как показано на рис. 2.7.
Приведем в табл. 2.1 названия некоторых цветов и соответствующие им значения в терминах RGB.
Таблица 2.1. Цвета
Цвет
Значение
Black
"#000000"
Green
"#008000"
Silver
"#C0C0C0"
Lime
"#00FF00"
Gray Olive
"#808080"
"#808000"
White
"#FFFFFF"
Yellow
"#FFFF00"
Таблица 2.1 (окончание)
Цвет
Значение
Maroon
"#800000"
Navy Red
"#000080"
"#FF0000"
Blue
"#0000FF"
Purple Teal
"#800080"
"#008080"
Fuchsia
"#FF00FF"
Aqua
"#00FFFF"
Э Шрифты - Microsoft Internet Explorer (Working Offline)НИИ-
] File Edit View Favorites Tools' Help’I 1?
Глава 1. Заголовок первого уровня
Заголовок второго уровня
Язык HTML не является языком программирования в том смысле, в каком мы привыкли представлять себе такие языки программирования, как С, C++, Java, Basic и другие.
При помощи HTML мы не сможем написать полноценное приложение, которое бы работало в системе MS-DOS, Windows или какой-либо другой ОС. HTML предназначен для создания документов, размещаемых на Web-сервере, доступ к которому осуществляется по сети IlHiq3Her.
Демонстрируем изменение размеров шрифта.
Обьиный шрифт (его величину можно указать в свойстве basefont).
Указан размер size=+1.
Указан размер size=+2.
Указан размер sizc ^+3
Указан размер size—14 d
Рис. 2.7. Цвет и размер шрифта
В табл. 2.2 представлены названия шрифтов, которые соответствуют определенным ярлыкам.
Таблица 2.2. Шрифты
Ярлык
Соответствующий ярлыку шрифт
<тт>
Телеграфный шрифт
<1>
Курсив
<ь>
Полужирный шрифт
<big>
Крупный шрифт
<small>
Мелкий шрифт
<STRIKE> или <S>
Перечеркнутый шрифт
<u>
Подчеркнутый шрифт
Средства HTML-форматирования
Сейчас мы рассмотрим более сложные средства, используемые для форматирования текстовой (и не только) информации. И начнем мы рассмотрение с таблиц. Таблицы используются для организации пространства просматриваемой страницы в окне браузера. В таблицах можно размешать не только текстовую информацию. Поскольку HTML-файл не имеет возможности непосредственно определять фиксированный внешний вид выводимой в окне браузера HTML-страницы, то полезно было бы иметь хотя бы некоторые примерные ограничения на относительное местоположение элементов HTML-страницы. В этом нам помогают таблицы.
Простая таблица
Начнем с примера. Оформим табл. 2.2, которой мы завершили предыдущий раздел, в виде HTML-таблицы. На экране вновь созданная таблица выглядит так, как показано на рис. 2.8. Поскольку ваш браузер может быть настроен несколько иначе, конкретный вид таблицы, показанной на экране в окне браузера, может несколько отличаться, но относительное положение элементов, расположенных в таблице, останется неизменным.
II 3 Таблица - Microsoft Internet Explorer - [Working Offline]
нав|
File Edit View Favorites
Tools Help
~ ; ? |
Таблица. Простейшая таблица.
1Ярлык
^Соответствующий ярлыку шрифт
[<тт>
<b>
^Телеграфный шрифт
\Kypcue
ЖфньнТ щшфт
^big>^Кр'ттнып шрифт
J<small>
!Мелкий шрифт
j<STMKE> или <S>
Перечеркнутый шрифт
i<u>
Подчеркнутый шрифт
—J
—
Рис. 2.8. Простая таблица
Созданный нами для описания такой таблицы файл tablel.htm выглядит так.
| Файл table1.htm
<нтмь>
<head>■
<Р1Р1е>Таблица</Р1Р1е>
</head>
<body>
<р> Таблица. <1>Простейшая таблица</1>.</р>
<table border="l" width="100%">
<tr>
<td м!ЬЬЬ="30%">Ярлык </td>
<td м1ЬЬЬ="70%">Соответствующий ярлыку шрифт</ЬЬ>
</tr>
<tr>
<td width="30%"><TT></td>
<td width="70% "ХТТ>Телеграфный шрифт</ЬЬ> </td>
</tr>
<tr>
<td width="30%"><I></td>
<td width="70%"xi>KypcMB</ix/td>
</tr>
<tr>"
<td width="30%"><b></td>
<td м1ЬЬЬ="70%"хЬ>Жирный шpифт</B></td>
</tr>
<tr>
<td width="30%">slt;bigSgt;</td>
<td width="70%"xbig>KpynHbM шpифт</bigx/td>
</tr>
<tr>
<td width="30%">slt;small Sgt;</td>
<td width="70%"xsmall>Meлк^^й шpифт</smallxfont FACE="Times New Roman"> </fontx/td>
</tr>
<tr>
<td width="30%">Slt;STRIKEsgt; или Sit;Ssgt;</td>
<td width="70%"xs>nepe4epKHyTbJH шpифт<sx/td>
</tr>
<tr>
<td width="30%">slt;usgt;</td>
<td width="70%"><u>nofl4epKHyTbJH шрифт</их/ТЦ>
</tr>
</table>
</body>
</HTML>
Что нового мы видим с тексте этого файла? Появился ярлык <tabie>. Его присутствие говорит о том, что между этим открывающим ярлыком и соответствующим ему закрывающим ярлыком </tabie> располагается таблица. Таблица состоит из строк и столбцов. Каждая строка начинается ярлыком <tr> и заканчивается ярлыком </tr>. Каждый столбец описывается внутри строки с помощью открывающего ярлыка <td> и закрывающего ярлыка </td>. Вот и все основные компоненты таблицы.
В ярлыках <tabie>, <tr>, <td> можно указать свойства. В нашем случае мы задали параметр ширины таблицы в виде width= "100%". Это означает, что таблица займет всю ширину окна браузера. В параметрах столбцов мы также указываем ширину столбца в процентах от общей ширины таблицы. Если изменить значения ширины столбцов, внешний вид таблицы изменится.
Вложенные таблицы
Таблицы могут быть вложенными друг в друга. В качестве примера рассмотрим код файла table3.htm. Здесь мы в ячейку первой строки второго столбца первой объемлющей таблицы вставили другую таблицу. Для того чтобы одна таблица четче выделялась на фоне другой, мы задали разные значения параметров цвета фона для этих таблиц. Также мы установили параметр выравнивания второй таблицы по центру и задали ее относительную общую ширину, равную 70%, поэтому вложенная таблица занимает не всю ширину удочерившей ее ячейки. Как выглядят вложенные таблицы, показано на рис. 2.9.
f^r:
i Файл table3.htm{
<HTML>
<head>
<б!б1е>Таблица в тaблицe</title>
</head>
<body>
<р> Изучаем таблицы. Таблица в таблице.</р>
ctable border="l" bgcolor="#eeeeee" width="100%">
<tr>
<td width="30%">nepsaH таблица. Первая строка, первый столбец. </td>
<td width="70%">nepsaH таблица. Первая строка, второй столбец. В эту ячейку таблицы вложена вторая таблица.
<table border="l" bgcolor="#dddddd" align="center" width="70%">
<tr>
<td width="50%">BTopaH таблица.
Первая строка,
первый
столбец.
</td>
<td width="50%">Вторая таблица.
Первая строка,
второй
столбец.
</td>
</tr>
<tr>
<td width="50%">Вторая таблица.
Вторая строка,
первый
столбец.</td>
<td width="50%">BTOpaH таблица.
Вторая строка,
второй
столбец </td>
</tr>
</table></td>
</tr>
<tr>
<td м1ЬбЬ="30%">Первая таблица. Вторая строка, первый столбец.</td>
<td width="70%">nepBa4 таблица. Вторая строка, второй столбец </td>
</tr>
</table>
</body>
</HTML>
| -31 Таблица в таблице - Microsoft Internet Explorer - [Working Offline]
File Edit View Favorites Tools Help{f
Изучаем таблицы. Таблица в таблице.
Первая таблица. Первая строка второй столбец. В ! эту ячейку таблицы вложена вторая таблица. ■
Первая таблица. Первая строка, первый столбец.Первая таблица. Первая строка, первый столбец.Первая таблица. Вторая строка, первый столбец.Первая таблица. Вторая строка, первый столбец.Вторая таблица. [Вторая таблица. ;
Первая таблица. Первая строка, первый столбец.
Первая таблица. Первая строка, первый столбец.
Первая таблица. Вторая строка, первый столбец.
Первая таблица. Вторая строка, первый столбец.
Первая строка, Первая строка, первый столбец, [второй столбец.[
Вторая таблица. -Вторая таблица.■
Вторая строка, (Вторая строка, [ первый столбец. [второй столбец ;
Первая таблица. Вторая строка, второй столбец
Рис. 2.9. Вложенные таблицы
Вложенные таблицы позволяют со значительной степенью гибкости располагать элементы на страничке. Если установить параметр толщины рамки таблицы border, равным нулю, то рамки станут невидимы и пользователь не будет подозревать о том, что страница скомпонована при помощи таблиц.
Свойства элемента <table>
В ярлыке <table> можно задать значения свойств таблицы (табл. 2.3).
Таблица 2.3. Свойства ярлыка <table>
Атрибут
Назначение
align
Выравнивание, относительное положение таблицы внутри элемента, в котором она находится
bgcolor
Цвет фона таблицы
Таблица 2.3 (окончание)
Атрибут
Назначение
width
Ширина таблицы
cols
Количество столбцов в таблице
border
Толщина рамки таблицы
cellspacing
Пробел между ячейками
cellpadding
Пробел от границы ячейки до содержимого ячейки
Это лишь малая часть свойств элемента <tabie>. Подробная информация содержится в справочных системах и в документации по языку HTML.
Объединение ячеек в таблице
Если вам приходилось работать с текстовым процессором Word, то вы знаете, что в таблице несколько соседних ячеек можно объединить. HTML позволят производить такое объединение ячеек. Для объединения ячеек используются параметры rowspan и colspan. Им присваивается целое число, равное количеству объединенных ячеек. Эти параметры задаются в ярлыке <td>. Пример объединенных ячеек представлен в файле table4.htm. Параметры rowspan и colspan показывают количество строк и столбцов соответственно, которые "захвачены" данной ячейкой.
Ссылки
Наличие гиперссылок — одно из важных свойств HTML. Собственно механизм ссылок и делает язык HTML тем средством, которое необходимо для удобной работы в сети Интернет. Механизм ссылок может быть различным. Рассмотрим на примерах то, как работают простейшие ссылки.
Текстовая ссылка
С помощью HTML мы имеем возможность организовать ссылку из любой части документа. Для ссылки используется ярлык, называемый якорем, anchor. В HTML, вероятно по той причине, что ссылка — это один из наиболее важных элементов Web-страниц, используется максимально сокращенный вариант слова anchor, от этого слова осталась лишь начальная буква. Для создания ссылки используется открывающий ярлык <а> и закрывающий ярлык </а>.
Между ярлыками <а> и </а> расположен фрагмент HTML-странички, с которым связана ссылка. Это может быть текст, это может быть таблица, это
может быть рисунок. Самостоятельно поэкспериментируйте с различными элементами, располагая их между указанными ярлыками.
Для начала мы создадим простую текстовую ссылку. Откроем какой-либо текстовый редактор и введем текст:
<HTML>
<head>
<title>
Гиперссылки
</title>
</head>
<body bgcolor= "#FFFFFF">
<p>
<hl align= "center">Глава 1. Заголовок первого уровня. </hl>
<р>
<h2 align= "center" >3десь мы изучаем ссылки</Ь2>
<р>
Ссылки можно использовать в любом месте в теле HTML кода Web-страницы.
В этом параграфе сейчас мы вставим ссылку: <А href= "#fed" >3 Т О — ПЕРВАЯ ССЫЛКА </А>. Со словами "это — первая ссыпка" теперь можно связать адрес какого-либо произвольного документа или другого объекта.
<р align= "right" > Этот абзац остался из предыдущей главы как пример выравнивания по правому краю.<Ьг> При помощи HTML мы не сможем написать полноценное приложение, которое бы работало в системе MS-DOS, Windows или какой-либо другой ОС. HTML предназначен для создания документов, размещаемых на Web-сервере, доступ к которому осуществляется по сети Интернет.
</body>
</HTML>
Загрузим файл с именем ref.htm в браузер. Мы увидим, что на экране созданная нами ссылка выделена из общего текста особым образом: она подчеркнута и выделена красным цветом. Как правило, по умолчанию браузер выделяет ссылку подчеркиванием и изменением цвета текста, например, на красный. После того как однажды вы щелкните на ссылке, браузер запомнит это действие, и в случае, если вы вернетесь на страницу, содержащую ссылку, цвет ссылки изменится. Простая текстовая ссылка выглядит на экране так, как показано на рис. 2.10.
651 Гиперссылки - Microsoft Internet Explorer - [Working Offline]
«5*1212*1
File Edit View Favorites Tools Help
Здесь мы изучаем ссылки"^
Ссылки можно использовать в любом месте в теле html кода web-страницы. В этом параграфе сейчас мы вставим ссылку: Э Т 0 -- П Е Р В А Я ССЫЛКА. — Со словами "это - первая ссылка" теперь можно связать адрес какого-либо произвольного документа или другого объекта.
Рис. 2.10.Текстовая ссылка
Адрес ссылки
Ссылки создаются для того, чтобы при щелчке на ней можно было просмотреть документ, на который она указывает. Однако если в предыдущем примере мы щелкнем на ссылке, то ничего не произойдет. Дело в том, что в свойстве href для нашей ссылки указан несуществующий адрес. В свойстве href указывается адрес документа, на который указывает ссылка. Href — это hyper reference, гиперссылка. В прошлом примере мы указали в качестве адреса параметр #fed. Если параметр адреса начинается со знака #, это значит, что данная ссылка является ссылкой на фрагмент текущей HTML-страницы. На нашей странице нет фрагмента, который бы носил имя fed, и поэтому никаких действий после нажатия на ссылку не происходит.
Создадим фрагмент с именем fed специально для того, чтобы проверить работу ссылки. Для этого перед фрагментом поставим пару ярлыков <а name= "#fed"x/a>. Измененный файл ref2.htm будет выглядеть так:
<HTML>
<head>
<title>
Ссылки
</title>
</head>
cbody bgcolor= "#FFFFFF">
<P>
<hl align= "center">Глава. Заголовок первого уровня. </hl>
<Р>
<h2 align= "center" >3аголовок второго уровня</Ь2>
<Р>
Ссылки можно использовать в любом месте в теле HTML кода Web-страницы.
В этом параграфе сейчас мы вставим ссылку: <А href= "#fed" >Э Т О — ПЕРВАЯ ССЫЛКА </А>. Со словами "это — первая ссылка" теперь можно связать адрес какого-либо произвольного документа или другого объекта.
<р align= "right" > Этот абзац остался из предыдущей главы как пример выравнивания по правому краю.<Ьг> При помощи HTML мы не сможем написать полноценное приложение, которое бы работало в системе MS-DOS, Windows или какой-либо другой ОС. HTML предназначен для создания документов, размещаемых на Web-сервере, доступ к которому осуществляется по сети Интернет.
<р>
<а name="fed"x/a> На этот фрагмент текста указывает вышеуказанная ссылка.
</body>
</HTML>
Сейчас при нажатии на ссылку происходит переход на указанный в ссылке фрагмент. Результат показан на рис. 2.11.
1Ссылки - Microsoft Internet Explorer - [Working Offline]
-|D|x|
- - -—- -- J
На этот фрагмент текста указывает вышенаписанная ссыпка._j
Рис. 2.11. Ссылка внутри документа
В приведенном выше примере мы использовали ярлык <ы>. Это непарный ярлык, для него не требуется указания закрывающего ярлыка. Этот ярлык указывает на необходимость перехода к новой строке в месте расположения ярлыка. Далее в этой главе мы рассмотрим и другие ярлыки, с помощью которых происходит управление и форматирование текста. ■
Чтобы организовать ссылку на какой-либо документ, расположенный в сети Интернет, достаточно указать полный адрес этого документа в параметре href ССЫЛКИ. Так, ссылка <а href= "http://www.yahoo.com"> Это поисковая система Yahoo</a> указывает на главную страницу поисковой системы Yahoo. Нажав на такую ссылку (см. листинг файла ref3.htm), мы перейдем на поисковую страницу, как показано на рис. 2.12.
1-21 Ссылки - Microsoft Internet Explorer - [Working Offline]
■■■ljhlj
File Edit View Favorites Tools Help'
Глава Заголовок первого уровня.
Заголовок второго уровня
На этой странице расположена ссылка на поисковую систему Yahoo.
Это поисковая система Yahoo
Рис. 2.12. Переходим по ссылке
; Файл ref3.htm
<нтмь>
<head>
<title>■
Ссылки
</title>
</head>
<body bgcolor= "#FFFFFF">
<p>
hl align= "сепЬег">Глава Заголовок первого уровня. </hl>
<р>
h2 align= "center" >3аголовок второго уровня</Ь2>
р>На этой странице расположена ссыпка на поисковую систему
Yahoo. <brxbr><BR>
<р>
а href= "http://www.yahoo.com"> Это поисковая система Yahoo</a>
</body>
</HTML>
Ссылки и рисунки
Вначале научимся вставлять рисунок в HTML-файл. Внедрить файл с изображением в HTML-страницу несложно. Для этого используется ярлык <img>. Изображение — по-английски image (образ), сокращенный вариант
этого слова используется в качестве HTML-ярлыка. Простейший файл, в котором используется изображение, можно написать в следующем виде (пример файла picl.htm).
; Файл pid.htm
<HTML>
<head>
<title>
Рисунки
</title>■
</head>
<body bgcolor="white">
<img src="picl.jpg">
<p>
На странице есть рисунок.
</P>
</body>
</HTML>
Если загрузить этот файл в браузер, то в окне браузера мы увидим картинку, показанную на рис. 2.13.
В случае, если пользователь имеет очень медленную связь с Интернетом, он может отключить автоматическую загрузку изображений в браузер. Тогда вместо картинки мы можем показать пользователю текст. Для этого нужно в ярлык <img> вставить свойство alt, которому присваиваем текстовую строку. Именно эта строка будет показана в окне браузера вместо рисунка, если рисунок по тем или иным причинам не был загружен:
<img src="picl.jpg" а1Р="Текст, выводимый вместо изображения">
Окно браузера будет выглядеть примерно так, как показано на рис. 2.14.
Рис. 2.14. Альтернативный текст, выводимый вместо рисунка
Фон страницы
Рисунки можно использовать не только в качестве элементов, объектов страницы, документа, но и в виде фона, на котором будет расположена страница. Файл рисунка с фоном указывается в ярлыке <body>: cbody bgcolor="white" background="back.gif">
Теперь, когда мы установили свойство background в ярлыке <body>, наша страница будет выглядеть так, как показано на рис. 2.15.
Здесь мы видим, что если одной копии рисунка не хватает, чтобы покрыть весь фон документа, т. е. если размер окна браузера больше размера рисунка, то рисунок фона воспроизводится столько раз, сколько необходимо для того, чтобы покрыть все окно браузера.
Свойства рисунков
В ярлыке <img> можно задать значения свойств (атрибутов), указанных в табл. 2.4.
Таблица 2.4. Свойства элемента <img>
Свойство
Значение
src
URL-адрес файла, в котором хранится картинка; обязательное свойство
alt
Текст, который будет показан вместо картинки, если картина не загружена
align
Параметр выравнивания
height
Высота картинки в пикселах
Width
Ширина картинки в пикселах
Border
Ширина границы картинки
Hspace
Горизонтальный отступ картинки
Vspace
Вертикальный отступ картинки
usemap
URL-адрес карты ссылок
ismap
Указатель использования серверной карты ссылок
Назначение свойств src и alt нам уже известно.
Далее мы рассмотрим перечисленные здесь атрибуты более подробно.
Свойство align позволяет определить местоположение картинки в окне браузера. Данное свойство может принимать следующие значения:
bottom;
middle;
top;
left;
right.
Параметр bottom задает выравнивание по основной линии, т. е. нижний край рисунка будет располагаться по основной текущей линии (в тексте).
Параметр middle соответствует выравниванию центра рисунка по середине вертикали от текущей базовой линии. Значению top соответствует выравнивание по верхней границе рисунка с учетом верхней границы текущего текста. Ниже на рисунках представлены примеры с различным типом выравнивания изображений (рис. 2.16—2.18).
Рис. 2.16. Выравнивание по нижнему краю изображения
Рис. 2.18. Выравнивание по верхнему краю изображенияРис. 2.18. Выравнивание по верхнему краю изображения
Рис. 2.18. Выравнивание по верхнему краю изображения
Рис. 2.18. Выравнивание по верхнему краю изображения
033033Параметры left и right описывают плавающие рисунки. Здесь расположение текста и вставляемого рисунка в потоке HTML-кода не имеют значения. Рисунки являются плавающими элементами страницы, их взаимное расположение и расположение по отношению к тексту определяется параметрами left И right (рис. 2.19 И 2.20).
033
033
|Д Рисунки - Microsoft Internet Explorer - [Working Offline]
I File Edit View Favorites Tools Help
Риеуноквыравниванию центрарисунка>посередине по вертикали ->т текущей базовой’яйНИиЗначению top соответствует выравнивание _ яо верхней границе рисунках: учетом верхней границы текущего »< , е тенета Ниже науирунках представлены примеры с различным типом выравнивания изображений. На странице есть рисунок. ДляРиеуноквыравниванию центрарисунка>посередине по вертикали ->т текущей базовой’яйНИиЗначению top соответствует выравнивание _ яо верхней границе рисунках: учетом верхней границы текущего »< , е тенета Ниже науирунках представлены примеры с различным типом выравнивания изображений. На странице есть рисунок. ДляРис. 2.19. Выравнивание плавающих рисунков по левому краюРис. 2.19. Выравнивание плавающих рисунков по левому краю
Риеуноквыравниванию центрарисунка>посередине по вертикали ->т текущей базовой’яйНИиЗначению top соответствует выравнивание _ яо верхней границе рисунках: учетом верхней границы текущего »< , е тенета Ниже науирунках представлены примеры с различным типом выравнивания изображений. На странице есть рисунок. Для
Риеуноквыравниванию центрарисунка>посередине по вертикали ->т текущей базовой’яйНИиЗначению top соответствует выравнивание _ яо верхней границе рисунках: учетом верхней границы текущего »< , е тенета Ниже науирунках представлены примеры с различным типом выравнивания изображений. На странице есть рисунок. Для
Рис. 2.19. Выравнивание плавающих рисунков по левому краю
Рис. 2.19. Выравнивание плавающих рисунков по левому краю
^Рисунки - Microsoft Internet Explorer - [Working Offline]
авниванавниван:о в:о вFile Edit View Favorites Tools Help
авниван
авниван
:о в
:о в
тёкет'а. Ниже нтёкет'а. Ниже нцентр^ридунка/посередиу по вертикали о ун ау и ию, top q о отве тствуёт вы р ав н ивдйб >уунка^ учете м,верхней границы текущей? " ^и^унках представлены придан с различный типом выравнивания изображений. На странице есть рисунок. Для
тёкет'а. Ниже н
тёкет'а. Ниже н
пельзовпельзовсозлания-OTcrvnc-B
пельзов
пельзов
£>амк
использовать рамки Ширина рамки задается с помощью Wa^^r,^ ^оздаивд^туц^;^- можно использовать рамки. Ширина р^мки задается с помощью *1 тт
параметра Ьога^Ддя г
^озданитятмМДможно использовать рамки. Ширина р^мки Я задае/сй с пдмощьбэ параметра border: Ширинафамки задается с помощью параметра border:
Рис. 2.20. Выравнивание плавающих рисунков по правому краю
На этих рисунках мы видим, что текст "обтекает" изображения. Для создания отступов можно использовать рамки. Ширина рамки задается с помощью параметра border:
<img src="picl.jpg" align="left" border="5">
<img src="picl.jpg" align="right" border="25">
Отделить картинки от текста можно с указанием параметров горизонтального и вертикального отступов:
<img src="picl.jpg" align="left" vspace="15" hspace="5">
<img src="picl.jpg" align="right" cspace="5" hspace="15">
HTML позволяет менять размер картинок. Зададим новые значения размера рисунка в файле picsizel.htm (рис. 2.21):
<нтмь>
<head>
<title>
Задаем размеры рисунка — файл sizel.htm
</title>
</head>
cbody bgcolor="white">
<Н1>Задаем размеры для рисунков.</hl>
cimg src="picl.jpg" align="left" vspace="15" hspace="15" width="450">
cimg src="picl.jpg" align="left" vspace="15" hspace="15">
<img src="picl.jpg" align="left" vspace="15" hspace="15" width="150">
<P align="justify">Pa3Mep первого рисунка в полтора раза больше размера исходного рисунка.
Размер второго рисунка совпадает с размером исходного рисунка.
Размер третьего рисунка в два раза меньше размера исходного рисунка. Речь идет о линейных размерах.
</body>
</HTML>
51 Задаем размеры рисунка - файл sizeLhtm - Microsoft Internet Explorer - [Working Offline]вив
] Fite Edit View Favorites Tools Help
Задаем размеры для рисунков.
полтора раза больше размера исходного рисунка. Размер второго
рисунка совпадает с размером исходного рисунка. Размер третьего рисунка в два раза меньше размера исходного рисунка. Речь
идет о линейных размерах.
Рис. 2.21. Задаем размеры рисунка с помощью параметров height и width
Форматирование изображений с использованием таблиц
Механизм таблиц предоставляет удобный способ форматирования изображений и отделения их от текста наиболее легким способом. Создадим простой файл tablel.htm, в котором запишем HTML-код, содержащий текст
и изображение, относительное положение которых будет определено с помощью таблицы.
Файл table1a.htm
<HTML>
<head>
<title> Таблицы </title>
</head>
<body bgcolor="white">
<table border="l" width="100%">
<tr>
<td width="25%"ximg src="picl.jpg" width="200" height="248" alt="picl.jpg (13212 bytes)"></td>
<td width="75%"xp а11дп="сепЬег"><зЬгопд>Изображение c/strongx/p>
<p align="center"xfont color="#808000"xfont size="6"xbxtt>
Это простое изображение</ЬЬ></Ьх/ГопЬ>. </font></p>
<р>Это пример изображения, которое отформатировано с применением таблиц. Это позволяет разместить изображение на странице наиболее удобным способом. </td>
</tr>
<tr>
<td width="100%" colspan="2"xfont size="2">C помощью таблиц можно
разместить элементы страницы в окне браузера
самым произвольным образом.</fontx/td>
</tr>
</table>
</body>
</HTML>
На рис. 2.22 показано форматирование содержимого HTML-страницы с помощью таблицы.
Границы таблицы можно сделать невидимыми, тогда пользователь даже не будет подозревать о том, что вы использовали таблицу для форматирования содержимого HTML-страницы:
<table border="0" width="100%">
Здесь мы задали толщину границы, равную нулю, теперь граница таблицы не будет видима (рис. 2.23).
Изображение
Это простоеизображение
Это пример изображения, котороесформатировано с применением таблиц, это позовляет разместить изображение на странице наиболее удобным способом.
jC помощью таблиц можно разместить элементы страницы в окне ^браузера самым произвольным образом.
Рис. 2.22. Форматируем страницу с помощью таблиц
3 Libhr^bi Ми пыИ! hib'iiwt ix'ihiH" IWnikinq (Ним pj
Изображение
Это простое изображение
Это пример изображения, которое сформатировано с применением таблиц, это позовляет разместить изображение на странице наиболее удобным способом.
С помощью таблиц можно разместить элементы страницы в окне браузера самым произвольным образом.
Рис. 2.23. Тот же файл с единственным изменением —отсутствуют границы в таблице
Ссылки и изображения
Изображение можно использовать в качестве ссылки на другой ресурс Интернета, на другую страницу. Для этого рисунок необходимо поместить между ярлыками якоря <а href= "..."> и </а>.
Рис. 2.24. Рисунок-ссылкаРис. 2.24. Рисунок-ссылка
Рис. 2.24. Рисунок-ссылка
Рис. 2.24. Рисунок-ссылка
Изображение
Это простое изображение
Это пример изображения, котороесформатированос применением таблиц, это позовляет разместить изображение на странице наиболее удобным способом.
С помощью таблиц можно разместить элементы страницы в окне браузера самым произвольным образом.
Изображение
Это простое изображение
Это пример изображения, котороесформатированос применением таблиц, это позовляет разместить изображение на странице наиболее удобным способом.
С помощью таблиц можно разместить элементы страницы в окне браузера самым произвольным образом.
Ссылка на рисунке:
<а href="bgif.htm"ximg src="ball.gif" width="75"><a>
Что при этом получается, можно видеть на рис. 2.24.
По умолчанию рисунок-ссылка обрамлен видимой рамкой. Чтобы рамка стала невидима, зададим толщине границы рисунка нулевое значение:
<а href="bgif .htm"ximg src="ball.gif" border=0 width="75"xa>
При этом ссылка выглядит более аккуратно (рис. 2.25).
Изображения-карты
Создадим простой HTML-файл map.HTML:
<map name= "mapname">
<area [shape= "shape"] coords= 'х,у,...' [href=URL | nohref]>
</тар>
Свойства:
shape — форма определяемой области;
coords — местоположение области и ее размер;
href — URL, на который ссылается область;
nohref — область является "мертвой зоной".
Форма shape может быть задана одним из четырех способов:
default — вся область, которая не определена с помощью других значений, приведенных ниже;
rect — прямоугольная область;
circle — круг;
poly — многоугольная область.
Прямоугольная область определяется четырьмя координатами:
левая;
верхняя;
правая;
нижняя..
Для круга координат три:
горизонтальная координата центра;
вертикальная координата центра;
радиус.
Для многоугольника координаты перечисляются в последовательности xl, yl, х2, у2, хЗ, уЗ и т. д.
ЬФайл map.html '
<HTML>
<head>
<title>KapTa ccbmoK</title>
</head>
<body>
<img src= "pic.jpg"■usemap= "#mapname">
<map name= "mapname">
<area shape = rect coords= "0, 0, 275, 220" href ="refl.html">
<area shape = rect coords= "275, 0, 450, 220" href ="ref2.html">
<area shape = rect coords= "0, 220, 275, 340" href ="ref3.html">
<area shape = rect coords= "275, 220, 450, 340" href ="ref4,html">
</map>
</body>
</HTML>
Загрузив файл map.html в браузер, мы получим картинку, изображенную на рис. 2.26.
Рис. 2.26. Карта ссылок
Сейчас мы перейдем к редактированию HTML-документов.
Редактирование HTML-документов
Существуют средства, позволяющие легко создавать и редактировать HTML- документы. Число таких средств очень велико. Программа Microsoft Front Page позволяет легко, "с нуля", создавать HTML-страницы, причем результат будет виден сразу в процессе работы.
Часто оказывается необходимым работать с HTML-кодом документа. Существуют программы, которые помогают подобрать необходимые свойства того или иного элемента, в них встроены справка-подсказка, подобно редактору C++ в Microsoft Studio. К числу таких средств можно отнести универсальный редактор SlickEdit.
Универсальный редактор SlickEdit
Для разработки программ, используемых в Интернете, очень удобным пред
ставляется редактор SlickEdit (рис. 2.27). Его то, что он поддерживает большое количество форматов файлов, имеет удобную подсказку, дружественный пользовательский интерфейс, удобен и легок в работе. Программу можно скачать из Интернета (бесплатная рабочая копия, функционирующая в течение 30 дней, доступна на сайте http://www.slickedit.com, размер файла примерно 30 Мбайт.Потренируемся в создании HTML- файлов с использованием редактора SlickEdit. В меню File выберем опцию New. Перед нами появится окно выбора типа создаваемого файла (рис. 2.28). Выбираем HTML-файл.Попробуем создать вручную первый ярлык <нтмь>. Как только мы вводим открывающую угловую скобку, редактор выводит подсказку в выпадающем окне, которое располагается под курсором (рис. 2.29).ставляется редактор SlickEdit (рис. 2.27). Его то, что он поддерживает большое количество форматов файлов, имеет удобную подсказку, дружественный пользовательский интерфейс, удобен и легок в работе. Программу можно скачать из Интернета (бесплатная рабочая копия, функционирующая в течение 30 дней, доступна на сайте http://www.slickedit.com, размер файла примерно 30 Мбайт.Потренируемся в создании HTML- файлов с использованием редактора SlickEdit. В меню File выберем опцию New. Перед нами появится окно выбора типа создаваемого файла (рис. 2.28). Выбираем HTML-файл.Попробуем создать вручную первый ярлык <нтмь>. Как только мы вводим открывающую угловую скобку, редактор выводит подсказку в выпадающем окне, которое располагается под курсором (рис. 2.29).главным достоинством являетсяглавным достоинством являетсяfpidhtm?fpidhtm?I 'a cs я ай5 » e1 а яв< i sI 'a cs я ай5 » e1 а яв< i sFlies " ’ backGF ball gil first html firstl.htmlFlies " ’ backGF ball gil first html firstl.htmlpic1.JPG pid ahtml pid b.html pid c.html pidd.html pid e.html pid f.html pidg.html picsize1.html ref.html ref2.htmlpic1.JPG pid ahtml pid b.html pid c.html pidd.html pid e.html pid f.html pidg.html picsize1.html ref.html ref2.htmlIIOjC:\SSCGI.bookOjC:\SSCGI.bookCl filesCl files
ставляется редактор SlickEdit (рис. 2.27). Его то, что он поддерживает большое количество форматов файлов, имеет удобную подсказку, дружественный пользовательский интерфейс, удобен и легок в работе. Программу можно скачать из Интернета (бесплатная рабочая копия, функционирующая в течение 30 дней, доступна на сайте http://www.slickedit.com, размер файла примерно 30 Мбайт.
Потренируемся в создании HTML- файлов с использованием редактора SlickEdit. В меню File выберем опцию New. Перед нами появится окно выбора типа создаваемого файла (рис. 2.28). Выбираем HTML-файл.
Попробуем создать вручную первый ярлык <нтмь>. Как только мы вводим открывающую угловую скобку, редактор выводит подсказку в выпадающем окне, которое располагается под курсором (рис. 2.29).
ставляется редактор SlickEdit (рис. 2.27). Его то, что он поддерживает большое количество форматов файлов, имеет удобную подсказку, дружественный пользовательский интерфейс, удобен и легок в работе. Программу можно скачать из Интернета (бесплатная рабочая копия, функционирующая в течение 30 дней, доступна на сайте http://www.slickedit.com, размер файла примерно 30 Мбайт.
Потренируемся в создании HTML- файлов с использованием редактора SlickEdit. В меню File выберем опцию New. Перед нами появится окно выбора типа создаваемого файла (рис. 2.28). Выбираем HTML-файл.
Попробуем создать вручную первый ярлык <нтмь>. Как только мы вводим открывающую угловую скобку, редактор выводит подсказку в выпадающем окне, которое располагается под курсором (рис. 2.29).
главным достоинством является
главным достоинством является
fpidhtm?
fpidhtm?
I 'a cs я ай5 » e1 а яв< i s
I 'a cs я ай5 » e1 а яв< i s
Flies " ’ backGF ball gil first html firstl.html
Flies " ’ backGF ball gil first html firstl.html
pic1.JPG pid ahtml pid b.html pid c.html pidd.html pid e.html pid f.html pidg.html picsize1.html ref.html ref2.html
pic1.JPG pid ahtml pid b.html pid c.html pidd.html pid e.html pid f.html pidg.html picsize1.html ref.html ref2.html
I
I
OjC:\
SSCGI.book
OjC:\
SSCGI.book
Cl files
Cl files
Рис. 2.28. Создаем пустой HTML-файлРис. 2.28. Создаем пустой HTML-файл
Рис. 2.28. Создаем пустой HTML-файл
Рис. 2.28. Создаем пустой HTML-файл
tfi Visual SlickEdit - [Untitled<24> 1
lop of Filelop of FileXX)^ Eife , Edit -.Search View" Project fiuild QocumenX -Macro3 ^-^^ hl ^'®L£L^^
lop of File
lop of File
X
X
SiStart Tag si
<•> ?
«А
<A ABBR
о» AB В REV
<•> ACRONYM
Рис. 2.29. Автоматическая подсказка
Мы находим ярлык HTML, выбираем его, при этом в окне справа появляется подсказка, в которой поясняется значение этого ярлыка и соответствующего ему элемента HTML (рис. 2.30).
\> Visual Shckfdit - [UnUtled<24> *]\> Visual Shckfdit - [UnUtled<24> *]№B
\> Visual Shckfdit - [UnUtled<24> *]
\> Visual Shckfdit - [UnUtled<24> *]
*Н1^
<HTML> ... </HTML>
«♦ Н2Ж
»НЗ:•
WH4
*Н5^
*♦ нб• >
«♦HEAD «♦ HR<
*) d
After document type declaration, the remainder of an HTML document is contained by the HTML ¥: element. Thus, a epical HTML document has this structure:
<1DOCTYPB HTML PUBLIC "-//W3C//DTD HTML 4.01//BN"Ц
http://www.w3.org/TR/htm!4/strict.dtd">^1
<HTML>;x»
...The head, body, etc. goes here^
</HTML>Si;
Attributes:
dir, lang, versionЖ
Ki Ble Edit "Search ^'^ife'-litij.fiRcSmert-1^Help ’• '-' -Islx
<-Q-3 * * e ада^ЯН*^^^- - >■■*'
Рис. 2.30. Редактор выводит автоматическую подсказку
В подсказке говорится о том, что данный ярлык используется для создания элемента <нтмь>, который содержит все другие элементы HTML-страницы. Далее в подсказке идет перечень атрибутов, которые могут быть заданы для этого элемента. Перечень атрибутов — это перечень ссылок на описание атрибутов. Выберем HTML (в окне подсказки будет отображено <HTML\ введем один пробел, и редактор вновь выведет подсказку (рис. 2.31), в которой предложит нам выбрать атрибут.
Закроем ярлык угловой скобкой. Перейдем к элементу <head>.
Чем удобна подсказка? Подсказка дает большую экономию времени. Часто оказывается, что нам нет необходимости обращаться к документации, так как основные возможности HTML уже раскрыты подсказкой. Например, мы создаем HTML-страницу с рисунком самым обычным непритязательным образом (файл slickl.html), рис. 2.32:
<HTML>
<HEAD>
<Т1ТЬЕ>Использование редактора SlickEdit </TITLE>
</HEAD>■
<BODY>
<IMG SRC='l.jpg'>
</BODY>
</HTML>
Рис. 2.32. Рисунок на странице с параметрами, принятыми по умолчанию
Может возникнуть такая ситуация, что нам не понравится, если рисунок на странице (как и все другие элементы) располагается не от самого края окна браузера, а между верхней границей рисунка и верхним краем браузера возникает белая полоска, которая есть также между левым краем рисунка
и левой границей окна браузера. Мы бы хотели устранить этот недостаток. Если применить немного смекалки, то можно догадаться, что изменить ситуацию, вероятно, можно, задав свойства элемента <body>. После этого все просто, редактор SlickEdit подскажет, что, оказывается, элемент <body> имеет атрибуты leftmargin и topmargin, и если установить значения этих атрибутов, равные 0, то белые полоски исчезнут (рис. 2.33).
Рис. 2.33. Тело страницы и рисунок начинаются с верхнего левого угла окна браузера без отступов
Изменный файл slick2.html
<HTML>
<HEAD>
<Т1ТЬЕ>Использевание редактора SlickEdit </TITLE>
</HEAD>
<BODY LEFTMARGIN=O TOPMARGIN=0>
<IMG SRC='l.jpg'>
</BODY>
Несмотря на то, что SlickEdit не располагает графическими средствами браузера и не может отобразить HTML-документ в том виде, как он будет виден пользователю, наличие подсказки делает его порой незаменимым средством при разработке HTML-документов.
Фреймы
Фреймы — это английское слово, в переводе означающее рамки. HTML- страница, в которой используются фреймы, выглядит разделенной на несколько частей, которые окаймлены границами, как рамками. Мы не будем переводить слово "фрейм", более того, даже будем использовать его русифицированную форму множественного числа. Все это оправдывается тем фактом, что все-таки фреймы — это не совсем то, что обозначает русское слово рамки, к тому же в программировании фреймов мы будем вынуждены пользоваться английскими словами, а в "родном" написании слово фреймы выглядит как frames.
Создание и использование фреймов
Часто возникает вопрос о том, как могут быть связаны друг с другом, казалось бы, совершенно разные вещи, такие как фреймы и язык JavaScript. Не будем спешить и остановимся вначале на рассказе о том, что представляют собой фреймы и для чего они используются. После этого рассмотрим вопрос о том, как могут быть взаимосвязаны фреймы и язык JavaScript.
Окно браузера может быть разделено на несколько фреймов. Фрейм представляет собой прямоугольную область экрана, расположенную в окне браузера. Каждый фрейм показывает свой документ, как правило, это обычный HTML-документ. Например, можно создать два окна и в одно из них загрузить домашнюю страничку компании Netscape, а в другой — домашнюю страничку компании Microsoft.
Несмотря на то, что создание фреймов осуществляется в рамках языка HTML, напомним основные принципы и способы создания фреймов. Для того чтобы создать фреймы, мы пользуемся двумя ярлыками, а именно ярлыком <frameset> и ярлыком <frame>. Страница, разбитая на два фрейма, может быть описана при помощи HTML следующим образом:
<HTML>
<frameset rows="50%,50%">
<frame src="pagel.htm" name="framel">
<frame src="page2.htm" name="frame2">
</frameset>
Этот код порождает два фрейма. В ярлыке <frameset> указано свойство rows (rows — это ряды). Это свойство указывает на то, что два фрейма расположены рядами, друг над другом. Верхний фрейм загружается страницей pagel.htm, а нижний фрейм — страницей page2.htm. Нажмите кнопку строкой ниже, и вы увидите, как будут выглядеть эти фреймы.
Если вы захотите расположить фреймы столбцами, то вместо свойства rows в ярлыке <frameset> укажите cols. Процентные величины "50%,50%" указывают относительные размеры окон фреймов. Если вы не хотите утруждать себя вычислениями того, каким должен быть размер второго окна, чтобы в целом получилось 100%, то можно указать размер окна в пикселах, при этом символ % опускается.
Каждый фрейм имеет свое уникальное имя, которое задается при помощи свойства name в ярлыке <frame>. При помощи этого имени фрейм легко доступен при описании на JavaScript.
Можно использовать несколько последовательных описаний фреймов при помощи ярлыков <frameset>, при этом фреймы могут быть расположены друг в друге. Вот пример такого расположения фреймов:
<frameset cols="50%,50%">
<frameset rows="50%,50%">
<frame src="cell.htm">
<frame src="cell.htm">
</frameset>
<frameset rows="33%,33%,33%">
<frame src="cell.htm">
<frame src="cell.htm">
<frame src="cell.htm">
</frameset>
</frameset>
С фреймами можно осуществлять довольно замысловатые операции, если использовать язык сценариев. Динамическому HTML посвящена следующая глава.
Формы •
Формы — это фрагменты HTML-страниц, выполненные в виде бланков для сбора информации.
Пример формы
Создадим простейший файл с формой forml.html.
[Файл form1.html.■ [
<HTML>'
<head>
<Ь1Ь1е>Простейшая фopмa</title>
</head>
<body>
<form name= "first">
Поле для ввода текста: <br>
<input type=text name = "textl">
<input type= "button" name = "buttonl" value = "Нажми меня">
<P>
</form>
</body>
</HTML>
Загрузим файл в браузер, получится картинка, показанная на рис. 2.34.
3 Простейшая форма - Microsoft Internet Explore... |Ир1 P
File Edit View Favorites Tools Help ‘| ^ |
Поле для воода текста:
Рис. 2.34. Работаем с формами
В коде HTML мы использовали ярлык <form>, он открывает форму. Форма — это контейнер, содержащий элементы, образующие тело формы. Требуется закрывающий ярлык. В своем примере мы указали имя для формы — это значение параметра name.
Элементы, составляющие тело формы
Важными компонентами формы являются поля для ввода текста и кнопки.
В нашем случае поле для ввода текста описано при помощи ярлыка
<input type=text name = "textl">
Здесь используется элемент <input>. Большинство элементов тела формы — это элементы <input>. Элементы <input> бывают разнообразными, все зависит от значения свойства type. В случае, когда type=text, элементом будет текстовое поле для ввода текста (однострочного). Кнопка описывается ЯрЛЫКОМ <input>, Где type=button.
Атрибуты свойства type
Атрибут type может принимать следующие значения:
button;
checkbox;
file;
hidden;
image;
password;
radio;
reset;
submit;
text.
С двумя из них мы уже знакомы, рассмотрим остальные.
Тип Checkbox
Описывает поле для галочки. Величина поля может быть задана путем указания значений параметров height и width. Если значение оказывается более 20 пикселов, то отступ внутри поля для галочки устанавливается равным 4 пикселам, а внутренняя ширина и высота равняется 8 пикселам. Если значение меньше 20 пикселов, но больше 13 пикселов, то отступ внутри поля для галочки равен половине разности от указанной ширины (или высоты) минус 13. При размерах менее 13 пикселов отступ равен 0.
Тип File
Используется для отправки файла серверу. При этом необходимо указать приложение, которое будет обрабатывать форму, указав его в атрибуте action ярлыка <form>. Рассмотрим это на примере файла form2.html.
j Файл form2.html.И
<HTML>'
<head>
<title>Oawi</title>
</head>
<body> cform name= "form" action="scripts/form.php" enctype= "multopart/form-data" method="post"> Отправить файл серверу: <br> cinput type=file name = "filel"> сР>После того, как файл выбран, нажмите кнопку...
cinput type= "button" name = "buttonl" value = "Отправить файл"> cP> c/form>'
c/body> C/HTML>
Кроме атрибута action, при посылке файла серверу необходимо указать значение атрибута enctype в виде multipart/form-data. Методом отправки может быть либо get, либо post. Окно браузера с формой для отправки файла серверу показано на рис. 2.35 и 2.36.
При отправке форм сервер получает информацию в виде пар, каждая из которых представляет собой имя и соответствующее этому имени значение. Эти пары обрабатываются сервером.
Тип Password
Можно в качестве поля текстового ввода данных использовать поле для ввода пароля. Тогда текст, вводимый в это поле, не будет виден в окне браузера, вместо него выводятся звездочки (рис. 2.37).
^Файл-Microsoft Internet Explorer - [Wor7.. |^^1ЕЗ|
File Edit View Favorites . Tools Help j 5*
Отправить файл серверу:
|.Browse... |
После того, как файл выбран, нажмите кнопку...
Отправить файл|—
. d
Рис. 2.35. Отправляем файл серверу
'3t**ai'in *" Microsoft Internet Explorer - [Wor... ввез
Efe EdA View Favorite? -Tools Help _
Editor Audio । Move to Copy to Del
Справкаr
Отправить фана cq)Bqw:
■ Browse.,.
После того, как файл выбран, нажмите кнопку...
Отправить файл I
itml
Ьн няжмт тте кнопку
Choose Me-
ИЕЗ
Look ire
О files
d * й d &
My Recert Documents
Desktop
Qcell.htm Slfirstt.html Й first.html - Qforml.html : lQformla.html ^[formlb.html
5jpicl-.html @ picl.JPG @ picla.html У piclb.html jQpiclc.html Qpicld.html S picle.html Qpiclf.html
^0refpicZhtmI ® samplel.html @tablel,html ^J tablela.html Si table lb.html ® table3.html @ table.html Sjtextl.html
My Documents
♦r-
■ My Compute
My NetwikRaces
@form2.html ftform2a.html
8|form3.html Д framest.html
Smap.html ypicl.html ^picl-.html
^| piclg.html ^ pic. jpg ^ picsizel.html ^J ref2.html @ref3.html ^jref.html Ujrefpicl.htm!
^ text2.html 5jtext3.html iQtext4.html ^) text.html
File name: .
1
d
Open
files of type: '
|AII Files [‘.1
v|
Cancel
]E^2jCGij^^
Рис. 2.36. Выбираем файл
ЗЬ Проел е>шап форма с раролен - Micro^cit... ВВЕЗ:
-File Edit View Favorites Tools .Help ■| ^ ]
Поле для ввода пароля:
]•••.•••••••. Нажми меня j
Тип Radio
Тип cinput type=radio> создает переключатели, которые используются для ограничения пользовательского выбора. Пользователь может выбрать лишь один вариант из нескольких. Для этого несколько переключателей объединяют в группу, все переключатели одной группы имеют одинаковое имя name. При посылке формы значение выбранного переключателя отсылается, как значение имени. Для отметки того или иного переключателя, который будет использоваться по умолчанию, служит свойство checked (см. пример файла form3.html).
I Файл form3.html
<HTML>
<head>
<title>Фaйл</title>
</head>
<body>
<form name= "form"
action="scripts/form.php"
enctype= "multopart/form-data"
method="post">
Отправить файл серверу: <br>
<input type=file name = "filel">
<Р>После того, как файл выбран, установите переключатель...
<input type= "button" name = "buttonl" value = "Отправить файл">
<HR>
<Р>Укажите ваш возраст:
<pxinput type=radio name="radio" > менее 10 лет
<pxinput type=radio name=”radio" checked> менее 11-30 лет
<Pxinput type=radio name="radio" > более 30 лет
<P>
</form>
</body>
</HTML>
Язык HTML предоставляет средства для создания статических Web-страниц. Как обогатить страницы, сделать их динамическими, "оживить", как создавать страницы "на лету", вы узнаете в следующих главах.
Глава 3
Динамические HTML-страницы
В предыдущей главе мы кратко познакомились с тем, как создаются простые HTML-страницы. Вернемся к первому примеру HTML-файла, приведенному в начале гл. 2. В этом примере мы можем заметить элемент, который открывается ярлыком <script>. Элемент script содержит программу- сценарий. Как правило, такая программа бывает написана на зыке JavaScript или VBScript. При помощи языков сценариев можно значительно обогатить возможности HTML-страниц.
Языки сценариев интерпретируются клиентскими приложениями — браузерами. Программа на таком языке не компилируется, программный код доставляется браузеру в таком виде, как он есть. В процессе загрузки код читается и, при обращении к программе или ее части, этот код выполняется встроенным интерпретатором.
Языки JavaScript и VBScript — это объектно-ориентированные языки. В них существуют средства описания и создания объектов. Объектные модели таких языков, как JavaScript и VBScript, порой сильно отличаются от объектных моделей языков C++ или Java. Основное отличие состоит в том, что в JavaScript не существует понятия абстрактного класса. Каждый объект всегда имеет свою конкретную реализацию, нет абстрактных классов и соответствующих им экземпляров классов. Объекты могут быть созданы программистом с использованием средств языка. Помимо этого, программист может воспользоваться заранее определенными объектами, т. е. такими объектами, которые встроены в программу-браузер и всегда доступны для скриптов, а также объектами, которые создаются программой-браузером автоматически при загрузке HTML-страницы и структура которых описана в этой HTML-странице. Как правило, каждому HTML-элементу соответствует некоторый объект. К объекту можно обращаться из программы, как к элементу массива (в браузерах всегда существует массив, состоящий из всех объектов
данной страницы), указав индекс элемента этого массива. К нему можно обратиться так же, как к элементу конкретного массива, т. е. массива, состоящего из объектов данного типа (существует несколько массивов для различных объектов). Причем обращение к элементам массива может быть как к элементам ассоциативного массива (указывая в качестве параметра имя объекта), так и задавая числовой индекс элемента массива. Наконец, к объекту можно обращаться по его имени, если это имя было задано в виде свойства id или name в соответствующем ярлыке при описании HTML- элемента. Как правило, свойства объектов совпадают со свойствами соответствующих им HTML-элементов.
Языки сценариев способны обрабатывать события. Примерами событий являются щелчок мышью, завершение загрузки страницы, перемещение мыши по заданной области, наведение фокуса на тот или иной элемент страницы и т. п. С наступлением того или иного события может быть связана определенная функция. Понятно, что такой механизм позволяет значительно расширить возможности HTML-разметки. Существует возможность активно изменять содержание и внешний вид страницы в зависимости от того, что делает пользователь. При этом, в процессе "общения с пользователем", с помощью языков сценариев мы можем кардинальным образом изменить текущую страницу без обращения к серверу, мы можем, например, создать новые объекты, уничтожить ранее созданные, проверить введенную информацию, заставить изображения двигаться и менять размер (языки сценариев могут работать с таймером).
Основы JavaScript
Что нужно для того, чтобы запустить программу-скрипт, написанную на JavaScript? Все, что для этого требуется, — это обычный интернет-браузер с активированной способностью распознавать JavaScript. Текст программы на языке JavaScript вставляется непосредственно в файл HTML-страницы. Чтобы посмотреть, как это выглядит, приведем пример простейшей HTML- страницы (см. пример файла htmll.html).
Файл html1.html• |
<HTML>
<body>
<br>
<hl align=center>3TO обычный HTML-документе/hl>
<br>
<script language="JavaScript"> document.write("Это и есть JavaScript!")
</script>
<br>
А это простой HTML.
</body>
</HTML>
Как выглядит окно браузера, когда в него загружен этот код, показано на рис. 3.1.
"3 E:\2_CGI_book\Texts\ch3\files\htmll.html - Microsoft Internet Explorer нив
File Edit View Favorites Tools Help ''
Это обычный HTML документ
Это и есть JavaScript!
А это простой HTML.;
d
Рис. 3.1. Простой JavaScript
События
События JavaScript представляют собой важный механизм при работе с динамическими страницами (см. листинг файла html2.html).
jj Файл html2.html|
<form>
<input type="button" value="Button to invoice pop-up window with alert" onClick="alert('Ой-ой')">
</form>
Эта функция выводит окно-предупреждение, где будет написан текст, который мы укажем в качестве аргумента (см. рис. 3.2).
3 E:\2_CGI_h>8k\Te«ts\di3W$\html2.html - Microsoft Inter... № В
Fife Edit V.ew Favofites Took help'| ^ I
Button to invoice pop-up window with alert I
I Microsoft Internet Explorer
Ой-ойO<Ой-ойO<
Ой-ой
O<
Ой-ой
O<
jJ
Рис. 3.2. Обработка события onClick в элементе <input type=button>
Некоторые часто используемые события приведены в табл. 3.1.
Таблица 3.1. События
Событие
В каком объекте чаще используется
Описание
Средство обработки события
Abort
Рисунки
Наступает тогда, когда пользователь прекращает загрузку рисунка до того, как рисунок будет полностью загружен (нажимает кнопку Stop или переходит на другую страницу)
OnAbort
Blur
Windows и все элементы форм
Пользователь перемещает фокус и снимает его с данного объекта или элемента формы
OnBlur
Change
Текстовые поля и списки выбора
Пользователь изменяет содержание элемента
onChange
Click
Кнопки, радиокнопки, поля для отметок, кнопки для посылки форм, кнопки для очистки форм, ссылки
Пользователь производит щелчок мышкой
onClick
DragDrop
Окна
Пользователь перетаскивает объект в окно и "бросает” его там
onDragDrop
Error
Рисунки и окна
В процессе загрузки документа или рисунка произошли ошибки
onError
Таблица 3.1 (окончание)
Событие
В каком объекте чаще используется
Описание "
Средство обработки события
Focus
Окна и все элементы форм
Пользователь устанавливает фокус на окне или элементе формы
OnFocus
KeyDown
Документы, рисунки, текстовые поля
Пользователь нажимает клавишу
onKeyDown
KeyPress
Документы, рисунки, ссылки, текстовые поля
Пользователь нажимает и удерживает клавишу
onKeyPress
Ke у Up
Документы, рисунки, ссылки, текстовые поля
Пользователь отпускает клавишу
onKeyUp
Load
В теле документа body
Пользовательзагружает
страницу в браузер
onLoad
MouseDown
Документы, кнопки, ссылки
Пользователь удерживает кнопку мыши в нажатом состоянии
onMouseDown
MouseMove
Различные элементы
Пользователь перемещает указатель мыши
onMouseMove
MouseOut
Ссылки
Пользователь "уводит" указатель ссылки с объекта ссылки или области клиентской карты ссылок
onMouseOut
MouseOver
Ссылки
Пользователь перемещает указатель мыши по ссылке
onMouseOver
MouseUp
Документы, кнопки, ссылки
Пользовательотпускает
кнопку мыши
onMouseUp
Move
Окна
Пользователь перемещает окно (или окно передвигается программно)
onMove
Reset
Формы
Пользователь очищает содержимое формы (нажимает кнопку Reset)
onReset
Resize
Окна
Пользователь (или скрипт) изменяет размер окна
onResize
Select
Текстовые поля
Пользователь выбирает текстовое поле
onSelect
Submit
Формы
Пользователь посылает форму серверу, нажимая соответствующую кнопку
onSubm.it
Unload
Телодокумента
body
Пользователь покидает страницу
onUnload
Функции
В JavaScript функции описываются без особых трудностей. Рассмотрим простой пример файла html3.html.
I Файл html3.html■|
<HTML>
<script language="JavaScript">
function myFunctionO (
document.write ("<Ь>Это я, функция! </bxbr>") ;
document. write ("Пустите переночевать.,.<br>") ;
myFunction(); myFunction(); myFunction(); </script>
</HTML>
Фреймы и JavaScript
Что представляют собой фреймы и как они используются, мы рассматривали в гл. 7. Напомним основные принципы и способы создания фреймов.
Страница, разбитая на два фрейма, может быть описана при помощи HTML следующим образом:
Файл html4.html '-•
<HTML>'
<frameset rows="50%,50%">
<frame src="pagel.htm" name="framel">
<frame src="page2.htm" name="frame2">
</frameset>
</HTML>
Этот код порождает два фрейма. В ярлыке <frameset> указано свойство rows (rows — это ряды). Это свойство указывает на то, что два фрейма расположены рядами, друг над другом. Верхний фрейм загружается страницей pagel.htm, а нижний фрейм загружается страницей page2.htm.
Фреймы можно расположить столбцами или их можно вкладывать друг в друга.
I Файл html5.html
<frameset cols="50%,50%">
<frameset rows="50%,50%">
<frame src="cell.htm">
<frame src="cell.htm">
</frameset>
<frameset rows="33%,33%,33%">
<frame src="cell.htm">
<frame src="cell.htm">
<frame src="cell.htm">
</frameset>
</frameset>
Как с точки зрения JavaScript выглядят фреймы, расположенные в окне браузера? Создадим два фрейма точно так, как это было сделано в первом примере.
Главным элементом в иерархии является окно браузера. Это окно разбивается на два фрейма. Окно браузера является родительским элементом по отношению к двум фреймам, которые являются дочерними по отношению к окну браузера. Мы дали этим двум фреймам уникальные имена framei и frame2. Используя эти имена, можно передавать информацию из одного фрейма другому. При помощи скриптов решим следующую задачу. Нужно создать такую страницу, в которой, при нажатии ссылки, расположенной в документе первого фрейма, происходит загрузка запрашиваемого документа во второй фрейм, а не в первый. Эта задача может быть актуальной в случаях, когда используются различные меню. Причем фрейм, в котором присутствует меню или содержание и в котором имеется набор ссылок на другие страницы, остается неподвижным и неизменным.
Рассмотрим три следующих варианта:
родительское окно или фрейм обращаются к дочернему фрейму;
дочерний фрейм обращается к родительскому окну или фрейму;
дочерний фрейм обращается к другому дочернему фрейму.
Дочерние фреймы имеют имена framei и frame2. В файле html5.html, рассмотренном ранее, показано, что окно браузера имеет прямые (родительские) связи с этими фреймами. Поэтому если вы используете скрипт, расположенный в родительском фрейме (в окне браузера), т. е. во фрейме, который содержит два дочерних фрейма, и хотите обратиться из родительского фрейма к дочерним, то у вас есть простой метод — укажите имя
дочернего фрейма, к которому необходимо обратиться. К примеру, можно написать так:
frame2.document.write("Обращение из родительского окна.");
Иногда появляется необходимость обратиться к родительскому окну из дочернего фрейма. Эта необходимость может возникнуть, например, тогда, когда нужно избавиться от фреймов. Освобождение от фреймов означает, что в окно браузера загружается другая страница, которая отличается от той, что породила фреймы. В нашем примере это страница, которая содержится в дочернем фрейме. Мы можем обратиться к родительскому окну или родительскому фрейму путем обращения к объекту parent (родитель). Для того чтобы загрузить в окно браузера новый документ, необходимо задать новый адрес URL, присвоив его объекту местоположения location.href. Поскольку мы хотим удалить фреймы, то нам необходимо обратиться к объекту местоположения, который расположен в родительском окне. Так как каждый фрейм может быть загружен своим собственным документом, то у каждого фрейма есть свой собственный объект местоположения. При помощи следующей команды, расположенной в документе дочернего фрейма, можно загрузить новую страницу в родительское окно:
parent.location.href= "http://...";
Довольно часто приходится сталкиваться с задачей, когда из одного дочернего документа необходимо обратиться к другому дочернему документу. Как записать что-либо во второй фрейм, находясь в первом? Иными словами, какая команда должна быть записана в документе pagel.htm, загруженном в первый фрейм, которая приводила бы к появлению во втором фрейме необходимых записей? На нашей картинке нет прямых связей между первым и вторым дочерними фреймами. Это означает, что мы не имеем возможности обратиться из первого фрейма framei ко второму, указав имя второго фрейма frame2 в документе pagel.htm, поскольку первый фрейм ничего "не знает" о существовании второго. С точки зрения родительского окна, второй фрейм носит имя frame2, а с точки зрения первого фрейма, к родительскому окну обращаются при помощи parent. Подведем итоги: для того, чтобы обратиться ко второму фрейму из первого, мы пишем:
parent.frame2.document.write("Это обращение из framei.");
Меню навигации
Рассмотрим пример того, как можно создавать меню навигации. Меню навигации — это набор нескольких ссылок, расположенных в одном фрейме. Если пользователь выбирает какую-либо ссылку из этого фрейма, то выбранная страница загружается не в этот фрейм, а во второй, т. е. во фрейм с именем main.
Вот пример. Вначале мы пишем документ, который создает фреймы. Этот документ выглядит подобно тому, что был приведен в первом примере.
рФайл htmI6.html;
<HTML>
<frameset rows="80%,20%">
<frame src="start.html" name="main">
<frame src="menu.html" name="menu">
</frameset>
</HTML>
Документ start.html — это стартовая страница, которая будет загружена во фрейм, носящий имя main. К этой странице нет никаких особых требований.
Файл start.html
в Вв вв• В ввв ввавве ВВв в Вв в в В вв ■
<HTML>
<head>"
</head>
<body>
<hl> Starting page</hl>
</body>
</HTML>
Во фрейм, который назван menu, будет загружена страница, показанная ниже в примере.
Файл menu.html.
<HTML>
<head>
<script language="JavaScript">
function load(url) {
parent.main.location.href= url;
</script>
</head>
<body>
<а href="javascript:load('first.html')">первая ссыпка</а>
<a href="second.html" target="main">BTopa4 ссыпка</а>
<a href="third.html" target="_top">TpeTb4 ссыпка</а>
</body>
</HTML>
При первоначальной загрузке страницы мы имеем начальную страницу в главном фрейме. После нажатия ссылки в главное окно фрейма загружается другая страница.
Атрибут target=_top сообщает, что страница будет загружена в самое старшее окно.
Документы, создаваемые "на лету"
Создание новых окон
JavaScript обладает одним замечательным свойством. С помощью JavaScript можно создать новое окно браузера, и в это открывшееся окно загрузить уже существующий HTML-документ, но в нем также можно разместить абсолютно новый, создаваемый по ходу работы документ. Вначале мы рассмотрим пример того, как можно создать новое окно браузера и загрузить в него существующий документ.
В приведенных ниже примерах скрипт открывает новое окно браузера (рис. 3.3) и загружает в него HTML-страничку "Новая страница".
: Файл html7.html
<нтмь>
<head>
<script language="JavaScript">
function openWin() {
myWin= open("page.htm");
}
</script>
</head>
<body>
<form>
<input type="button" уа1ие="0ткрываем новое окно" onClick="openWin()">
</form>
</body>
</HTML>
рФайл page.htm|
<HTML>
<head>
</head>
<body>'
<Ь1>новая страница. </hl>
</body>
</HTML>
^ E:\2_CGI_book\Texts\ch3\files\html7.ht~. Щ®E3
i Открываем новое окне |.'
Рис. 3.3. До нажатия кнопки
При открытии нового окна существует возможность выбора параметров внешнего вида создаваемого окна. Например, можно выбрать, будет ли новое окно иметь панель инструментов, панель меню или панель строки состояния. Также возможно задание размера открываемого окна. Следующая программа открывает окно, размер которого устанавливается 400 х 300. Окно не будет иметь строки состояния, меню и панели инструментов.
*Файл html8.html|
<HTML>
<head>
<script language="JavaScript">
function openWin2 () {>
myWin= open("page.htm", "newWindow",
"width=400,height=300,status=no,toolbar=no,menubar=no");
</script>
</head>
<body>
<form>
<input type="button" value="OTKpbiBaeM новое окно 400x300" onClick="openWin2()">
</form>
</body>
</HTML>
Функция open содержит три аргумента:
myWin= open("page.htm", "newWindow",
"width=400,height=300,status=no, toolbar=no,menubar=no");
Второй аргумент — это имя окна. Ранее мы уже видели, как используется свойство target. Если мы знаем имя существующего окна, то загрузить в это окно новый документ можно с использованием свойства target. Это можно осуществить следующим образом:
<а href="page.html" target="newWindow">
Если окно с таким именем не существует, то указанная выше ссылка приведет к созданию нового окна. Также отметим, что mywin не является именем этого окна. При помощи переменной mywin мы можем лишь обратиться к этому окну. Эта переменная может использоваться в пределах данного скрипта JavaScript, т. е. в рамках того модуля JavaScript, где она была описана. Имя же окна (в нашем случае это newWindow) является уникальным именем и может быть использовано во всех окнах браузера.
Закрытие окна
Для закрытия окон используется метод close(). Откроем окно, как это было описано выше, и загрузим в него следующую страницу:
<HTML>
<script language="JavaScript"> function closeltO {
close();
</script>
<center>.
<form>
<input type=button value="3aKpoeM окно" onClick="close!t()">
</form>
</center>
</HTML>
Если нажать кнопку Закроем окно в этом окне, то окно закроется.
Методы open о и closet) — это методы объекта window. Если быть последовательным, то необходимо помнить, что полный вид записей инструкций открытия И закрытия ОКОН должен быть window, open () И window, close () , вместо open () И Closet).
Объект window представляет собой исключение из общего правила, и для вызова методов объекта window не нужно указывать объект (т. е. писать слово window). Это справедливо лишь для данного конкретного объекта (объекта window).
Создание документов по ходу работы
Вначале мы создадим простой HTML-документ и покажем его в новом окне (рис. 3.4). Ниже приведен скрипт, решающий эту задачу.
; Файл html9.html
<HTML>
<head>
«script language="JavaScript">
function openWin3() (-
myWin= open("", "newWindow",
"width=500,height=400,status=yes,toolbar=yes,menubar=yes");
// открываем документ
myWin.document.open();
// создаем документ
myWin.document.write ("<HTMLxheadxtitle>Co3flannM-Ka новое окно и документ на лету в нем");
myWin.document.write("</titlex/headxbody>");
myWin.document.write ("<centerxfont size=+3>") ;
myWin.document.write("Это окно и документ в нем созданы ");
myWin.document.write("при помощи JavaScript!");
myWin.document.write ("</fontx/center>") ;
myWin.document.write("</body></HTML>");
II закрываем документ (но не окно!)
myWin.document.close() ;
}
</script>
</head>
<body>
<form>
<input type=button value="Co3naHHM-Ka новое окно и документ на лету прямо в нем" onClick="openWin3()">
</form>
</body>
</HTML>
RPIBRPIB5 £оздади|8Нса новое «sho и документ на лету в йен - Microsoft internet... BSB |
RPIB
RPIB
F-le Edit View Favorites Tools Help
Это окно и документ в нем
созданы при помощиJavaScript!
|J|F:\2j:GIJro(>k\Tcxts\ch3\files\htn^- Microsoft InternetГир!ш<-г
Fils Edie View Favorites Tools' Help
J > iJ > iСоздадии-ка новое окно и документ на лету прямо в нем
J > i
J > i
Рис. 3.4. Создаем документ "на лету"
Сначала мы открываем новое окно браузера. Первый аргумент функции — пустая строка "". Это означает, что мы не указываем никакой URL. Браузер не должен загружать существующий документ, JavaScript создаст новый документ. Определяем переменную mywin. При помощи этой переменной будем обращаться к новому окну. Здесь мы не можем использовать имя нового окна (newWindow). После того как окно открыто, открываем документ при помощи команды:
myWin.document.open(); "
Здесь мы вызываем метод open (), относящийся к объекту document. Это иной метод, отличающийся от метода open () для объекта window! Эта команда не открывает нового окна, она подготавливает документ для его последующего вывода. Перед document, open о следует указать mywin для того, чтобы обратиться к новому окну.
Далее следующие команды создают содержание нового документа.
// создаем документ
myWin.document.write ("<HTML><headxtitle>Co3flaaMM-Ka новое окно и документ на лету в нем");
myWin. document .write ("</titlex/headxbody>") ;
mywin.document.write("<center><font size=+3>");
myWin.document.write("Это окно и документ в нем созданы ");
myWin.document.write("при помощи JavaScript!");
myWin.document.write ("</fontx/center>") ;
myWin.document.write("</body></HTML>");
Мы видим, что здесь записаны обычные ярлыки, используемые в HTML- документах. Таким образом, мы создаем HTML-страничку. Здесь можно использовать любые ярлыки, допустимые в HTML. После окончания вывода необходимо закрыть документ. Это делается при помощи следующей инструкции.
// закрываем документ (но не окно!)
myWin.document.close();
Если, например, у нас существует два фрейма с именами frame! и frame2 и мы хотим создать новый документ, который будет размещен во фрейме frame2, то во фрейме framei следует написать следующее:
parent.frame2.document.open();
parent.frame2.document.write("Здесь мы пишем наш HTML-код");
parent.frame2.document.close();
Строка состояния
JavaScript имеет возможности, которые позволяют осуществлять вывод информации на панель состояния (мы будем пользоваться терминами "строка состояния" и "панель состояния" как синонимами, не делая между ними различия). Панель состояния находится на нижней части рамки окна браузера. Для того чтобы вывести текстовую строку на панель состояния, необходимо присвоить window.status значение, равное этой строке. Нижеследующий пример осуществляет запись и уничтожение текста на панели состояния (рис. 3.5).
I Файл html10.html"'"
<HTML>
<head>
<script language="JavaScript"> function statbar(txt) { window.status = txt;
}
</script>
</head>
<body>
<form>
cinput type="button" name="look" value="nnmeM на панель состояния!" onClick="statbar('Вот она, панель состояния!');">
cinput type="button" name="erase"
value="CmpaeM текст с панели состояния!" onClick="statbar('');"> </form> </body> </HTML>
Э £Д2. £bl_book\T exts’\£h3\files\htrrj5 1oietrnl-T^
File Edit tew Favc^tes Tools Help ;
Пишем | Стираем [
§Вотс^, ги^» состояния!" ’ |^f~^|^[y jty сог^
Рис. 3.5. Пишем на панель состояния
При нажатии кнопки Пишем на панель состояния!, на панели состояния, расположенной в нижней части окна, появляется текст: "Вот она, панель состояния!".
Здесь мы создаем форму с двумя кнопками. Обе кнопки приводят к вызову функции statbar о. Кнопка Пишем на панель состояния! приводит к исполнению следующей функции:
statbar('Вот она, панель состояния!');
В скобках мы записали текст "Вот она, панель состояния!". Эта строка передается для обработки функции в виде параметра. Сама функция statbar о была определена нами следующим образом: function statbar (txt) { window.status = txt;
Еще один пример, когда мы переписываем содержимое панели состояния, вместо гипертекстовой ссылки на панели состояния будет показан текст "Не нажимай меня!".
^Файл html11.html•.:|
<а href="dontclck.htm"
onMouseOver="window.status='He нажимай меня!'; return true;" onMouseOut="window.status='';"> ссылка </a>
Создание временных задержек
Если задать временную задержку,-то компьютер будет выполнять действия по истечении указанного времени. В следующем примере, если нажать на кнопку Временная задержка, то спустя 4 секунды на экране всплывет новое окно (рис. 3.6).
^айл html12.html"-. ',
<script language="JavaScript"> function timer () {
setTimeout("alert('Пришло время появиться новому окну!')", 4000);
</script>
<form>
cinput type="button" value="BpeMeHHan задержка" onClick="timer()"> </form>
Команда setTimeout () — ЭТО МСТОД, ОТНОСЯЩИЙСЯ К объекту window. При помощи данного метода происходит установка величины задержки, о чем нетрудно догадаться. Первым аргументом в выражении, присваиваемом данному методу, является код на языке JavaScript, который будет выполнен по истечении определенного промежутка времени.
Рис. 3.6. Временные задержки
В данном случае будет исполнена команда:
alert(Пришло время появиться новому окну!')
Второй аргумент сообщает компьютеру продолжительность задержки — время, через которое необходимо выполнить указанные команды. Время указывается в миллисекундах (4000 миллисекунд = 4 секунды).
Движущийся текст
Приведем пример движущегося текста (рис. 3.7).
Файл html13.html
<HTML>
<head>
<script language="JavaScript">
// Задаем выводимый текст
var scrtxt = "Этот текст выводится при помощи JavaScript! " +
"Этот текст выводится при помощи JavaScript! " +
"Этот текст выводится при помощи JavaScript!";
var length = scrtxt.length;
var width = 100;
var pos = -(width + 2);
function scroll() {
// выводим текст с правой позиции и устанавливаем временную задержку
// сдвигаем позицию на один шаг pos++;
// вычисляем, какая часть текста будет видима
var scroller = "";
if (pos == length) { pos = -(width + 2);
)
// если текст не достиг пока левого края,
// то необходимо добавить несколько пробелов — иначе придется
// отсекать переднюю часть текста
if (pos < 0) {
for (var i = 1; i <= Math.abs(pos); i++) { scroller = scroller + " ”;)
scroller = scroller + scrtxt.substring(0, width — i + 1);
)
else {
scroller = scroller + scrtxt.substring(pos, width + pos);
)
// выводим текст на панель состояния window.status = scroller;
// вновь обращаемся к функции спустя 100 миллисекунд
setTimeout("scroll()", 100);
)'
</script>
</head>
<body onLoad="scroll()">
Здесь располагается текст HTML-странички.
</body>
</HTML>
13E:\2^ttnj3c^fc\TeKts\ch3\fli£$\ht»M^^linbernet Explorer '
FA? ' Edt View Favcntes Tqcls Help'Л
Здесь располагается текст HTML-странички.
ЙЙ 'Этот текст выводится при помощи JavaScript! Этот текст выводится |, • | -
|| ;j Му Computer 1 .
Рис. 3.7. На панели состояния движущийся текст
Объекты JavaScript
JavaScript использует объекты, которые содержат свойства и методы. Рассмотрим основные объекты JavaScript, наиболее часто используемые в работе.
Объект Date
Объект Date предназначен для работы с датами и временем. Например, текущая дата и время могут быть представлены следующим образом:
Time: 16:47
Date: 12/1/2002.
Файл html14.html
<script language="JavaScript">
now= new Date();
document.write("Time: " + now.getHours() + ":" + now.getMinutes() + "<br>");
document.write("Date: " + (now.getMonth() + 1) + "/" + now.getDate() +
"/" + (1900 + now.getYear()));■
</script>
Однако такая программа не всегда работает корректно. Следует дополнительно проверить, в каком формате будет выведен текущий год.
Здесь мы использовали метод getHours о, с помощью которого получили значение часов нашего нового объекта Date с именем new. Вы, наверное, заметили, что в программе прибавляется число 1900 к значению года, получаемого при помощи getYear (). Метод getYear () возвращает значение года, начиная с 1900. Если это 1997 год, то getYear о возвратит величину 97, для 2005 года — число 105. Полезно иметь в виду, что при написании программ, работающих со временем, легко получить результат, когда минуты и секунды, представленные в строчной записи, не будут содержать нуль впереди значащей цифры, если цифра окажется меньше десяти, т. е. время будет выглядеть примерно так: 14:3, — тогда как следовало бы вывести 14:03. В приведенной ниже программе этот момент учтен и внесены необходимые исправления.
Рассмотрим программу, которая выводит на экран в окне браузера изображение идущих часов (рис. 3.8).
• Файл html15.html
<HTML>
<head>
<script Language="JavaScript"> var timeStr, dateStr;
function clock() {
now= new Date();
// время
hours= now.getHours();
minutes= now.getMinutes();
seconds= now.getSeconds();
■ timeStr= "" + hours;
timeStr+= ((minutes < 10) ? ":0" : ":") + minutes; timeStr+= ((seconds < 10) ? ":0” : ":") + seconds; document.clock.time.value = timeStr;
// дата
date= now.getDate();
month= now.getMonth()+1;
year= 1900 + now.getYear();
dateStr= "" + month;
dateStr+= ((date < 10) ? "/0" : "/") + date;
dateStr+= "/" + year;
document.clock.date.value = dateStr;
Timer= setTimeout("clock()",1000);
}
</script>
</head>
<body onLoad="clock()">
<form name="clock">
Время:
<input type="text" name="time" size="8" value=""><br>
Дата:
<input type="text" name="date" size="8" value="">
</form>
</body>
</HTML>
5E^^ra^^*^^ts^3\fites\ht^l&ht^25^2M@SI
file Edit View! Favorites Tools Help| ^ !
Время: |9:54:53
Дата: 1/19/3902
Рис. 3.8. Идущие часы
Объект массива Array
Массивы позволяют объединить множество переменных, связав их вместе друг с другом. Доступ к таким переменным осуществляется посредством одного единственного имени и числа (или чисел). Пусть наш массив носит имя names. Тогда первое имя, хранящееся в этом массиве, можно получить при помощи обращения names [0]. Доступ ко второму имени может быть осуществлен посредством names [ 1 ] и т. д.
Объект Math
Если появляется необходимость производить математические вычисления, то математический объект Math предоставляет целый набор методов, позволяющих осуществить множество математических операций. Полный список методов объекта Math приводится в справочниках. Например, у объекта Math существует метод sin о, позволяющий вычислять значения синусов. Продемонстрируем в качестве примера, как работает метод random (). Если вызвать Math, random(), то мы получим случайное число в промежутке от 0 до 1. Вот результат выполнения команды document, write (Math, random о ): всякий раз при перезагрузке страницы получаемое число будет иным, отличным от предыдущего.
Картинки и JavaScript
Предварительная загрузка картинок, используемых на страничке
Загрузка картинки из сети Интернет может занять некоторое время. В иных ситуациях такая временная задержка может быть и приемлемой, однако не всегда допустимо ждать долгое время до окончания загрузки страницы. Можно загрузить рисунок, который потребуется при дальнейшей работе со страницей, заранее. Для этой цели создадим новый объект image.
ImgNew= new Image();
ImgNew.src= "img3.gif";
В первой строчке мы создали новый объект image и назвали его imgNew. Вторая строчка задает адрес этого нового объекта. Присваивание адреса свойству зге приводит к тому, что указанный рисунок загружается из сети. При выполнении второй строчки браузер прйетупит к загрузке картинки img3.gif. Поскольку картинка с именем imgNew нигде на HTML-страничке не используется, то картинка imgNew останется скрытой от пользователя,
она будет загружена из сети и останется где-то в памяти компьютера, откуда она быстро может быть извлечена и помещена на страничку. Для того чтобы показать этот рисунок на страничке, мы можем использовать такую строчку: '
document.myImage.src = hiddenlmg.src;
После исполнения этой команды изображение будет извлечено из памяти и тотчас показано. Таким образом мы можем использовать картинки, которые были заранее загружены на компьютер.
Конечно, для того чтобы рисунок, который должен быть заранее загружен, мог появиться в окне браузера без задержки, он должен быть полностью загружен на компьютер. Поэтому, если картинка велика по размеру или на странице содержится большое количество заранее загружаемых картинок, может все же возникнуть нежелательная задержка ввиду того, что браузер будет занят работой по загрузке изображений из сети. Используемый метод заблаговременной загрузки изображений ускоряет процесс развертывания изображения на экране компьютера; он заставляет браузер приступить к загрузке нужных в дальнейшем изображений как можно скорее, не дожидаясь непосредственного обращения к этим изображениям, но этот метод ни в коей мере не ускоряет процесс загрузки изображений из сети. Чем скорее мы начнем загрузку изображений, тем скорее мы будем иметь на своем компьютере готовые для развертывания в окне браузера изображения. При этом весь процесс работы происходит более равномерно и более удобно для пользователя.
Изменение картинок в ответ на действия пользователя
Мы имеем возможность создавать интересные эффекты перемены изображений в ответ на те или иные действия пользователя. Например, мы можем изменить изображение на новое, если указатель мыши будет находиться над той или иной областью изображения (рис. 3.9 и 3.10).
ьФайл html16.html "’'
<а href="#"
onMouseOver="document,mylmage2.src=1img2.gif1"
onMouseOut="document,mylmage2.src='imgl.gif'">
cimg src="imgl.gif" name="mylmage2" width=160 height=50 border=0x/a>
Рис. 3.9. Страница только что загружена
3 E:\2_CGI_book\Texts\ch3\- Ц® В
[Address |^1 \files\htmll6.html ^['ВЗ Go
| File Edit View Favorites “ j 3^
Рис. 3.10. Указатель мыши находится над рисунком
Объектная модель в JavaScript
Объектная модель в языке JavaScript основана на прототипах в противоположность объектной модели, основанной на классах.
Языки, основанные на классах, и языки, использующие структуру объектов-прототипов
Языки, основанные на объектной модели, использующей концепцию классов, например, язык C++, в своей основе строятся на двух принципиально различных и дополняющих друг друга понятиях. Мы имеем в виду понятие класса и понятие экземпляра класса.
Класс определяет все содержащиеся в нем свойства (члены класса в C++, методы и поля в Java). Эти свойства характеризуют определенное множество объектов, для описания которых создается класс. Класс представляет собой весьма абстрактную конструкцию. В свою очередь множество элементов, объединенных понятием класса, состоит из конкретных членов — экземпляров класса.
Экземпляр класса — это конкретное воплощение структуры, реализованной в виде абстрактного описания класса.
В языках, использующих объекты-прототипы, не существует такой разницы между абстрактным описанием класса и его конкретной реализацией в виде
экземпляра класса. Прототипы-объекты в языках, подобных JavaScript, являются своеобразными шаблонами, содержащими те или иные свойства, применяемые при создании новых объектов. В любом объекте могут быть использованы присущие этому объекту свойства, причем они могут быть созданы либо в момент определения объекта, либо во время выполнения программы. Каждый объект может служить в качестве объекта-прототипа при создании другого объекта, при этом второй объект может использовать свойства первого объекта.
Определение класса
В языках, основанных на структуре классов, например C++ и Java, классы создаются независимо друг от друга при помощи описаний (определений) классов. Эти описания могут содержать специальные методы, называемые конструкторами класса. При помощи конструкторов класса можно создавать новые экземпляры класса. Функция-конструктор может содержать в виде параметров значения тех или иных свойств данного класса, а также содержать другие инструкции, допустимые для выполнения в момент создания экземпляра класса. Для создания экземпляра класса используется оператор new в сочетании с методом-конструктором класса.
В JavaScript используется модель, во многом похожая на эту. Отличие состоит в том, что в JavaScript нет различия между описанием абстрактного класса и созданием экземпляра этого класса. Здесь мы можем определить функцию-конструктор, с помощью которой создаем объект с конкретным набором свойств и значений. Любую функцию JavaScript можно использовать в виде конструктора. Для этого используется оператор new в сочетании с конструктором функции. При этом создается новый экземпляр класса.
Наследование и подклассы
В языках, объектная модель которых строится на классах, иерархия классов и наследование реализуются через механизм определения классов. В определении класса мы имеем возможность описать новый класс, указав тот факт, что этот новый класс будет являться подклассом другого существующего класса. Такой подкласс унаследует все свойства старшего класса, а также может содержать в себе новые свойства или может использовать унаследованные свойства, модифицировав их. Так, например, класс сотрудников Rabotnik может иметь свойства, например, имени name и отдела otdei. Предположим, что это все свойства класса Rabotnik. Пусть класс управляющих Rukovodstvo является подклассом класса Rabotnik, и в этом классе дополнительно определено свойство podchnennye, с помощью которого можно описывать взаимоотношения менеджеров и сотрудников, устанавливая программный аналог производственной иерархии. В этом примере подкласс Rukovodstvo будет иметь свойства name, otdei И podchnennye.
В JavaScript наследование осуществляется с применением объектов- прототипов в сочетании с конструкторами функций. В этом случае мы также можем организовать структуру классов, описанную ранее, но терминология и способ построения такой структуры будут несколько отличаться. Вначале мы определим функцию-конструктор с именем Rabotnik, указав в ней свойства name и otdei. Затем мы определяем другую функцию-конструктор с именем Rukovodstvo, у которой будет одно свойство — свойство podchnennye. Далее при создании НОВОГО объекта (Rukovodstvo) мы указываем, что объект Rabotnik является объектом-прототипом для конструктора функции Rukovodstvo. И, наконец, после создания нового объекта Rukovodstvo, этот объект будет содержать в себе свойства name и otdei, унаследованные из объекта Rabotnik.
Вставка и удаление свойств
В языках, основанных на классах, класс создается, как правило, во время компиляции и инициализируется, образуя экземпляр класса либо во время компиляции, либо во время исполнения. При этом мы не имеем возможность изменить набор свойств данного класса: количество этих свойств и их тип после того, как класс описан. В противоположность этому, JavaScript позволяет удалять и вставлять новые свойства в любой объект в процессе выполнения программы. Если новое свойство будет добавлено в объект, который является прототипом для других объектов, то те объекты, прототипом которых является первый объект с новыми свойствами, также получат в свое распоряжение набор этих новых свойств.
Обзор различий .
Сведем различия объектной модели классов и объектной модели объектов- прототипов в табл. 3.2. Затем мы рассмотрим примеры использования JavaScript конструкторов и объектов-прототипов при создании иерархии классов в сравнении с тем, как это может быть сделано в языке Java.
Таблица 3.2. Сравнение объектной модели для языков, использующих классы (Java), и для языков, использующих объекты-прототипы (JavaScript)
Модель классов (Java)Модель объектов-прототипов (JavaScript)
Класс и экземпляр класса отличаются Все объекты являются своими экземплярами (нет различия между формальным описанием объекта и экземпляром объекта)
Класс определяется при помощи Объекты определяются и создаются при noclass, экземпляр класса создается с мощи функций-конструкторов использованием метода конструктора класса
Модель классов (Java)Модель классов (Java)Отдельный экземпляр класса создается с помощью оператора newИерархия объектов образуется с помощью определений классов с указанием подклассов для существующих классовНаследование свойств происходит по цепочке наследования между классамиОпределение класса (class) содержит описание всех свойств, которые будут содержаться во всех экземплярах данного класса. Не существует возможности добавить новые свойства динамически во время исполнения программыОтдельный экземпляр класса создается с помощью оператора newИерархия объектов образуется с помощью определений классов с указанием подклассов для существующих классовНаследование свойств происходит по цепочке наследования между классамиОпределение класса (class) содержит описание всех свойств, которые будут содержаться во всех экземплярах данного класса. Не существует возможности добавить новые свойства динамически во время исполнения программы
Модель классов (Java)
Модель классов (Java)
Отдельный экземпляр класса создается с помощью оператора new
Иерархия объектов образуется с помощью определений классов с указанием подклассов для существующих классов
Наследование свойств происходит по цепочке наследования между классами
Определение класса (class) содержит описание всех свойств, которые будут содержаться во всех экземплярах данного класса. Не существует возможности добавить новые свойства динамически во время исполнения программы
Отдельный экземпляр класса создается с помощью оператора new
Иерархия объектов образуется с помощью определений классов с указанием подклассов для существующих классов
Наследование свойств происходит по цепочке наследования между классами
Определение класса (class) содержит описание всех свойств, которые будут содержаться во всех экземплярах данного класса. Не существует возможности добавить новые свойства динамически во время исполнения программы
Модель объектов-прототипов (JavaScript)
Отдельный объект создается с помощью оператора new
Иерархия объектов организуется при помощи указания атрибута объекта propotype в сочетании с функцией-конструктором
Наследование свойств происходит по цепочке объектов-прототипов
Функция-конструктор или prototype задают лишь начальный набор свойств. Свойства могут быть удалены и добавлены в тот или иной объект или весь набор объектов динамически в процессе выполнения программы
Пример иерархии объектов
Рассмотрим пример иерархии объектов (рис. 3.11).
Здесь мы видим следующие объекты:
объект сотрудников Rabotnik обладает свойствами name (по умолчанию значение этого свойства — пустая строка) и otdei (по умолчанию значение general);
объект менеджеров Rukovodstvo происходит от объекта Rabotnik. В нем содержится дополнительное свойство podchnennye, по умолчанию это свойство принимает значение, равное пустому массиву; предполагается, что этот массив содержит набор объектов Rabotnik;
объект работников Rabotyaga основывается на объекте сотрудников Rabotnik. В нем, помимо свойств объекта Rabotnik, содержится свойство проектов zadachi, значение которого по умолчанию равно пустому массиву; предполагается, что это свойство содержит массив строк (названий проектов);
объект продавцов sbytovik основан на объекте работников Rabotyaga. Этот объект имеет свойство quota (по умолчанию равно 100). В этом объекте свойство otdei переписывается, принимая значение sbyt; это обозначает, что все продавцы относятся к отделу продаж;
объект инженеров injener основывается на объекте работников Rabotyaga. Этот объект содержит свойство svoistvo (по умолчанию — пустая строка), в этом объекте свойство otdei принимает значение Injenering.
Задание иерархии объектов
Существует несколько способов организовать описанную иерархию объектов с помощью функций-конструкторов. Выбор того или иного варианта зависит от того, каким мы хотим видеть свое приложение. Рассмотрим сравнительно простой, но достаточно гибкий способ описания приведенной иерархии объектов. Создаваемые новые объекты получают значения свойств по умолчанию, эти свойства могут быть изменены в дальнейшем. На рис. 3.12 показана та же иерархия объектов, что изображена на рис. 3.11, но здесь мы записали определения объектов.
Определение такой иерархии объектов на JavaScript и Java практически одинаковы. Отличием является то, что в Java необходимо явно указать тип каждого свойства, а также создать явный вид конструктора Java класса (табл. 3.3).
Рис. 3.12. Иерархия объектов работников
Таблица 3.3. Сравнение Java и JavaScript
JavaScriptJava
function Rabotnik () (Public class Rabotnik (
this.name = "";public String name;
this.otdel = "general";public String otdel;
}public Rabotnik () (
this.name = ""; this.otdel = "general"; } }
Определения объектов Rukovodstvo и Rabotyaga могут послужить примером того, как отличаются модели классов и объектов-прототипов при задании иерархии классов (табл. 3.4). В JavaScript мы указываем свойство prototype для объекта, который использует уже существующий объект в качестве прототипа. Это происходит с использованием функции-конструктора. Такое задание свойства prototype может быть осуществлено в любое время и после того, как был использован конструктор. В Java мы можем указать имя суперкласса лишь при определении класса. За переделами определения класса не существует возможности задать имя суперкласса для данного класса.
Таблица 3.4. Конкретный пример JavaScript и Java
JavaScript
Java
function Rukovodstvo
0 (
public class Rukovodstvo extends Rabotnik {
this.podchnennye : }
= [J;
public Rabotnik[] podchnennye;
■public Rukovodstvo () {
Rukovodstvo.prototype Rabotnik;
= new
this.podchnennye = new Rabotnik[0]; } }
function Rabotyaga ()
{
this.zadachi = []
public class Rabotyaga extends Rabotnik {
}
public String[] zadachi;
Rabotyaga.prototype = Rabotnik;
new
public Rabotyaga () {
this.zadachi = new String[0];
}
}
На этом примере мы видим, насколько короче получаются конструкции, записанные на JavaScript (табл. 3.3, 3.4).
Объекты injener и sbytovik происходят от объекта Rabotyaga и, следовательно, от объекта Rabotnik. Эти объекты имеют свойства, унаследованные от всех вышестоящих объектов. Кроме того, в этих объектах переписывается значение свойства otdei (табл. 3.5).
Таблица 3.5. Сравнение двух объектов
JavaScript
Java
function Sbytovik () {
Public class Sbytovik extends Rabotyaga {
this.otdei = "sbyt";
public double quota;
this.quota = 100;
public Sbytovik () {
JavaScriptJavaScriptJavaJava
JavaScript
JavaScript
Java
Java
}Sbytovik.prototype = new Rabotyaga;function Injener () {this.otdel = "Injener- ing";this.svoistvo = "";}Injener.prototype = new Rabotyaga;}Sbytovik.prototype = new Rabotyaga;function Injener () {this.otdel = "Injener- ing";this.svoistvo = "";}Injener.prototype = new Rabotyaga;this.otdel = "sbyt";
}
Sbytovik.prototype = new Rabotyaga;
function Injener () {
this.otdel = "Injener- ing";
this.svoistvo = "";
}
Injener.prototype = new Rabotyaga;
}
Sbytovik.prototype = new Rabotyaga;
function Injener () {
this.otdel = "Injener- ing";
this.svoistvo = "";
}
Injener.prototype = new Rabotyaga;
this.quota = 100.0;
}
}
public class Injener extends Rabotyaga { public String svoistvo;
public Injener () {
this.otdel = "Injenering";
this.svoistvo = "";
}
Используя приведенные определения, можно создавать экземпляры класса (объекта) со свойствами, значения которых равны значениям, принимаемым по умолчанию.
Примечание ^|
Экземпляр класса в языках, основанных на классах, имеет вполне конкретный смысл. В случае с JavaScript этот термин не имеет особого смысла. Таким термином можно пользоваться, например, при создании объекта и с использованием функции-конструктора. '
Свойства объекта
В этом разделе мы обсудим вопрос о том, как объекты унаследуют свойства по цепи объектов-прототипов и что происходит тогда, когда мы добавляем новое свойство во время выполнения программы.
Наследование свойств
Предположим, что нам необходимо создать объект kolya как экземпляр объекта Rabotyaga (рис. 3.13), для чего мы используем запись:
kolya = new Rabotyaga;
Когда JavaScript встречает оператор new, то создается новый объект, который будет передан в качестве объекта, являющегося значением ключевого слова this, конструктору функции Rabotyaga. Конструктор задает значение свойства zadachi. Он также задает свойствоproto. Это свойство имеет по два символа подчеркивания в начале в конце.
Vera.svoistvo -"
Рис. 3.13. Создание объектов и с использованием их простого описания
При этом не обязательно происходит автоматическое задание локальных значений для свойств в объекте kolya, которые унаследованы из других вышестоящих объектов. В первую очередь JavaScript определяет, доступны ли локальные значения для свойств данного объекта. Если в объекте нет локальных значений, то значения свойств наследуются по цепочке в иерархии объектов с использованием свойстваproto. Если в этой цепочке встречается объект, содержащий значение требуемого свойства, то это значение будет возвращено в качестве значения свойства текущего объекта. Если в цепочке иерархии объектов свойство не будет найдено, то значение его устанавливается по умолчанию, а именно: kolya.name = "";
kolya.otdel = "general";
kolya.zadachi = [];
Объект kolya наследует значения свойств name и otdel из объекта- прототипа kolya.proto. Этими свойствами могут быть, например, свойства, заданные с использованием конструктора, например, Rabotyaga.
Значения свойств всегда можно изменить. И мы можем, например, написать: kolya.name = "Vasya, Kolya";
kolya.otdel = "direktsiya"; kolya.zadachi = ["vodoprovod"];
Добавление новых свойств
JavaScript позволят добавлять новые свойства в объект в процессе выполнения программы. Причем мы не ограничены в выборе исключительно тех свойств, которые были указаны в функции-конструкторе объекта. Чтобы добавить в объект новое свойство, достаточно лишь задать значение этого свойства, например: kolya.bonus = 3000;
Конкретные объектыКонкретные объектыИерархия объектовИерархия объектовVictor = new InjenerVictor = new InjenerPetr = new RabotnikPetr.dolzhnost - 'none'Petr = new RabotnikPetr.dolzhnost - 'none'Savelij = new Rabotyaga Savelij.dolzhnost - ‘none’Savelij = new Rabotyaga Savelij.dolzhnost - ‘none’Рис. 3.14. Добавляем новые свойстваРис. 3.14. Добавляем новые свойства
Конкретные объекты
Конкретные объекты
Иерархия объектов
Иерархия объектов
Victor = new Injener
Victor = new Injener
Petr = new Rabotnik
Petr.dolzhnost - 'none'
Petr = new Rabotnik
Petr.dolzhnost - 'none'
Savelij = new Rabotyaga Savelij.dolzhnost - ‘none’
Savelij = new Rabotyaga Savelij.dolzhnost - ‘none’
Рис. 3.14. Добавляем новые свойства
Рис. 3.14. Добавляем новые свойства
Сейчас объект kolya обладает свойством bonus. При этом данным свойством не будет обладать никакой другой объект в иерархии работников Rabotyaga.
Если свойство добавлено в объект, который является прототипом, то вновь вставленное свойство наследуется и передается всем другим объектам, для которых данный объект является прототипом. Например, в объект сотрудников можно вставить свойство специальности doizhnost. При этом должно быть использовано свойство prototype. Это можно сделать так:
Rabotnik.prototype.doizhnost = "none";
После этого объект kolya также будет обладать свойством specialty со значением попе. На рис. 3.14 показан пример добавления свойства в объект Rabotnik, это свойство переписано в объекте injener.
Конструкторы. Более гибкие инструменты
Конструкторы, которыми мы пользовались до настоящего времени, не представляли возможностей для задания значений свойств в момент создания объектов. Но мы можем использовать аргументы, которые указываются в функциях-конструкторах и могут быть использованы для передачи начальных значений. В качестве иллюстрации рассмотрим рис. 3.15.
В табл. 3.6, представленной ниже, показаны способы задания аргументов в языках JavaScript и Java.
Таблица 3.6. Аргументы в Java и JavaScript
JavaScript
Java
function Rabotnik (name, ot- del) {
public class Rabotnik { public String name;
this.name = name |] "";
public String otdel;
this.otdel = otdel || "general";
public Rabotnik () {
}
this("", "general");
}
public Rabotnik (name) { this(name, "general");
}
public Rabotnik (name, otdel) { this.name = name;
this.otdel = otdel;
}
}
Таблица 3.6 (окончание)
JavaScript
Java
function Rabotyaga (projs) { this.zadachi = projs || [];
public class Rabotyaga extends Rabotnik { public String[] zadachi;
public Rabotyaga () {
this(new String[0]);
Rabotyaga.prototype = new Rabotnik;
}
public Rabotyaga (String[] projs) { this.zadachi = projs;
}
Function Injener (mach) { this.otdel = "Injenering"; this.svoistvo = mach I] "";
}
public class Injener extends Rabotyaga { public String svoistvo;
public Rabotyaga () {
this.otdel = "Injenering";
Injener.prototype = new Rabotyaga;
this.svoistvo = "";
}
public Rabotyaga (mach) { this.otdel = "Injenering"; this.svoistvo = mach;
}
}
В JavaScript используется специальная конструкция, с помощью которой могут быть заданы значения, присваиваемые по умолчанию в том случае, если аргументы конструктора не заданы: this.name = name || "";
Эта конструкция с логическим оператором ИЛИ (| |). Оператор проверяет первый аргумент. Если этот аргумент приводится к значению true, то оператор возвращает значение первого аргумента, в противном случае оператор возвращает значение второго аргумента. Таким образом, если name указано в качестве аргумента, то оно может быть сведено к логическому значению true. Поэтому this.name примет значение, указанное в качестве аргумента. В противном случае значением будет пустая строка. На первый взгляд это может показаться странным, однако в этой конструкции нет ничего необычного.
Приведем пример:
Marina = new Injener("horosho");
Иерархия объектовИерархия объектовКонкретные объектыКонкретные объектыРис. 3.15. Задаем свойства в виде параметров функции-конструктораРис. 3.15. Задаем свойства в виде параметров функции-конструктора
Иерархия объектов
Иерархия объектов
Конкретные объекты
Конкретные объекты
Рис. 3.15. Задаем свойства в виде параметров функции-конструктора
Рис. 3.15. Задаем свойства в виде параметров функции-конструктора
Свойства объекта Marina:
Ma г ina . name == " ";
Marina.otdel == "general";
Marina.zadachi == [];
Marina.svoistvo == "horosho"
Отметим, что при помощи такой конструкции мы не имеем возможности задавать начальное значение для свойства, передаваемого по иерархии, например, для свойства name. Для решения проблемы необходимо вставить несколько дополнительных строчек кода в функцию-конструктор.
Таким образом, функция-конструктор может быть использована как для создания объекта, так и для задания начальных значений его свойств. С помощью конструктора можно добавлять новые свойства для объектов, расположенных выше в дереве иерархии. Такой способ проиллюстрирован на рис. 3.16.
Иерархия объектов Конкретные объекты
Katya = new Injener ("Simonova, Katya”, ["navigator”, “javascript"]);
Katya.name - "Simonova, Katya"
Katya.otdfel - ‘injenering’
Kaatya.zadachi - ["navigator”, “javascript” ] katya.svoistvo - “horosho”
Рис. 3.16. Задаем свойства объектов с использованием конструкторов
Рассмотрим в подробностях то, что здесь происходит. Мы использовали такой код: function Injener (name, projs, mach) ( this.nasledie = Rabotyaga; this.nasledie(name, "Injenering", projs); this.svoistvo = mach || "";
}
Затем можем записать, например, так:
Marina = new Injener("Vasya, Marina", ["vodoprovod", "javascript"], "horosho");
Вот что происходит при исполнении такого кода:
Оператор new создает новый объект и устанавливает его свойство proto, равное Injener.prototype.
Оператор new передает новый объект функции-конструктору injener в качестве значения ключевого слова this.
Конструктор создает новое для этого объекта свойство nasledie и присваивает ему значение конструктора Rabotyaga. Это приводит к тому, что конструктор Rabotyaga становится методом объекта injener. Имя свойства nasledie не является специальным словом или специальным свойством. Здесь можно использовать любое имя, в нашем случае было использовано ИМЯ nasledie.
Конструктор вызывает метод na.si6di6, передавая ему два значения, хра~ нящиеся В переменных (значения Vasya, Marina И массив ["vodoprovod", "javascript"]), а также явную строку-литерал injenering. Это соответствует указанию на то, что все объекты injener имеют одно и то же значение свойства otdei.
Функция Rabotyaga передает значения Vasya, Marina И ["vodoprovod", "javascript"], полученные в качестве аргументов, конструктору Rabotnik. Затем функция Rabotyaga использует аргументы для задания свойства zadachi.
После выполнения метода nasledie, конструктор Injener инициализирует свойство svoistvo значением horosho.
После выполнения конструктора, JavaScript присваивает новый объект переменной Marina.
На первый взгляд может показаться, что обращение к конструктору injener устанавливает правила наследования объектов в иерархии injener. Это не так. Если мы, например, добавим позже новое свойство в объекты Rabotnik или Rabotyaga, то это свойство (значения свойств) не будет добавлено в объект injener, поскольку порядок наследования здесь не был задан явно.
function Injener (name, projs, mach) (
this.nasledie = Rabotyaga;
this.nasledie(name, "Injenering", projs);
this.svoistvo = mach || "";
}
Marina = new Injener("Vasya, Marina", ["vodoprovod", "javascript"], "horosho");
Rabotnik.prototype.specialty = "none";
Объект Marina не будет содержать свойства specialty. Для того чтобы это свойство было унаследовано, необходимо явно указать порядок наследования, а именно: function Injener (name, projs, mach) (
this.nasledie = Rabotyaga;
this.nasledie(name, "Injenering", projs);
this.svoistvo = mach I I "";
)'
Injener.prototype = new Rabotyaga;
Marina = new Injener("Vasya, Marina", ["vodoprovod", "javascript"], "horosho");
Rabotnik.prototype.specialty = "none";
Сейчас в объекте Marina присутствует свойство specialty, значением которого является строка попе.
Наследование свойств
Мы рассмотрели, как используются функции-конструкторы и свойства prototype языка JavaScript для задания иерархии объектов и наследования свойств объектов. Сейчас мы остановимся на рассмотрении некоторых деталей механизма наследования.
Локальные и унаследованные значения
При проверке значений свойств объекта, JavaScript производит следующую последовательность действий:
Проверяет, присутствует ли локальное значение свойства. Если да, то свойство возвращает это локальное значение.
Если локальное значение не присутствует, то проверяется последовательность по цепочке прототипов с использованием свойстваproto.
Если по цепочке объектов прототипов встречается значение указанного свойства, то возвращается найденное значение.
Если значение свойства не было найдено в цепи объектов-прототипов, то свойство будет отсутствовать.
Вернемся к нашему примеру: function Rabotnik () { this.name = ""; this.otdel = "general"; } function Rabotyaga () { this.zadachi = []; }■
Rabotyaga.prototype = new Rabotnik;
Предположим также, что создан объект sveta при помощи такого выражения:
sveta = new Rabotyaga;
Данный объект имеет одно локальное свойство — это свойство zadachi. Свойства name и otdei не являются локальными по отношению к объекту sveta, соответственно, они будут получать значения из объектов, указанных в свойствеproto. sveta.name == ""; sveta.otdei = "general"; . sveta.zadachi == [];
Предположим, что мы изменили значение свойства name в объекте- прототипе следующим способом:
Rabotnik.prototype.name = "Unknown"
Может показаться, что внесенное изменение будет распространяться вниз по иерархии объектов. Но это не так.
В момент создания объекта sveta значениями свойств этого объекта будут являться локальные значения. И лишь в том случае, если локальное значение не будет найдено, осуществляется поиск локальных значений для объектов, расположенных выше в дереве иерархии.
Если в дальнейшем процессе выполнения программы нам необходимо заменить старые значения свойств на новые, причем замену необходимо произвести так, чтобы она была "видна" по всей иерархии объектов, то для этого недостаточно использовать конструктор объекта. Вместо этого нужно использовать прототип (свойство prototype) этого конструктора. Предыдущий пример выглядит теперь так: function Rabotnik () {'
this.otdel = "general";
}
Rabotnik.prototype.name = "";
function Rabotyaga () {
this.zadachi = [ ];
}
Rabotyaga.prototype = new Rabotnik;
sveta = new Rabotyaga;
Rabotnik.prototype.name = "Unknown";
Сейчас свойство name в объекте sveta приняло значение Unknown.
Еще раз повторим: для того чтобы изменить значение свойства объекта и при этом сделать изменение и во всех объектах, расположенных ниже в иерархии объектов, необходимо вместо свойства конструктора данного объекта использовать свойство в прототипе конструктора объекта. (Не в самом конструкторе, а в прототипе конструктора!)
Взаимосвязь экземпляров объектов
Иногда бывает полезно знать, какой объект является прототипом для данного объекта, т. е. где расположен данный объект в цепи прототипов, из какого объекта он наследует свои свойства. В языках, использующих объектную модель классов, для этого может быть использован оператор instanceof. В JavaScript такого оператора нет, однако подобную функцию можно создать собственными силами.
При создании нового объекта с использованием оператора new и конструктора, JavaScript устанавливает значение proto для данного объекта в соответствии со значением прототипа конструктора (prototype для функции-конструктора). Эти значения могут быть использованы в целях определения последовательности наследования.
Предположим, что мы имеем набор тех же объектов, что были описаны ранее. Создадим новый объект при помощи выражения:
Nikolai = new Injener("Baraban, Nikolai", ["eou”], "cvbewhhg");
Сейчас мы можем записать ряд тавтологий, показывающих, как можно осуществлять определение последовательности наследования объектов. Все выражения являются истинными:
Nikolai.proto == Injener.prototype;
Nikolai.proto.proto == Rabotyaga.prototype;
Nikolai.proto.proto.proto == Rabotnik.prototype;
Nikolai.proto.proto.proto.proto == Object.prototype;
Nikolai,proto.proto.proto. proto . proto ==null;
Аналог функции instanceof в JavaScript в интерпретации может быть записан весьма тривиально, например, так:
function instanceof(object, constructor) {'
while (object != null) (
if (object == constructor.prototype) return true; object = object.proto;
} return false; )■
Все перечисленные ниже логические выражения возвращают значение true: instanceOf (Nikolai, Injener) instanceOf (Nikolai, Rabotyaga) instanceOf (Nikolai, Rabotnik) instanceOf (Nikolai, Object)
Пример обращения к функции unstanceOf, когда возвращаемое значение будет false: instanceOf (Nikolai, Sbytovik)
Конструкторы и глобальная информация
При использовании конструкторов необходимо быть осторожными в тех случаях, когда в них используется глобальная информация. Предположим, что мы хотим автоматически присваивать каждому сотруднику уникальный номер ID. Можно сделать это так: var idCounter = 1; function Rabotnik (name, otdel) { this.name = name || ""; this.otdel = otdel || "general"; this.id = idCounter++;
)
При этом, когда создается новый объект Rabotnik с помощью конструкции new Rabotnik, конструктор присваивает очередное значение номера ID. В примере, приведенном ниже, свойство matryona.id равно 1, siava.id равно 2: matryona = new Rabotnik("Fafantik, Matryona", "pubs") Slava = new Rabotnik("Tschopik, Slava", "sbyt")'
Казалось бы, что все хорошо и нет никаких проблем. Однако опасность состоит в том, что счетчик увеличивается всякий раз при создании объекта типа Rabotnik вне зависимости от того, в каких целях создается такой объект. Рассмотрим в качестве примера такой код: var idCounter = 1;
function Rabotnik (name, otdel) {
this.name = name I I "";
this.otdel = otdel I| "general";
this.id = idCounter++;
}
function Rukovodstvo (name, otdel, podchnennye) {...}
Rukovodstvo.prototype = new Rabotnik;
function Rabotyaga (name, otdel, projs) {...}
Rabotyaga.prototype = new Rabotnik;
function Injener (name, projs, mach) {...}
Injener.prototype = new Rabotyaga;
function Sbytovik (name, projs, quota) {...}
Sbytovik.prototype = new Rabotyaga;
mac = new Injener("Kartnov, Mac");
Предположим также, что среди свойств объектов (которые не приведены для краткости) присутствует свойство nasiedie (метод, определенный ранее, представляющий собой конструктор объекта, являющегося прототипом для данного объекта, т. е. каждая функция производит обращение к конструкторам-прототипам). При этом, после создания объекта mac, свойство mac. id будет иметь значение 5.
В зависимости от задач приложения, это может иметь какое-либо существенное значение или нет. Однако такое поведение всегда необходимо иметь в виду при написании программ. Рассмотренный выше пример может быть переписан следующим способом: function Rabotnik (name, otdel) {
this.name = name I| "";
this.otdel = otdel || "general";
if (name)
this.id = idCounter++;'
}
Сейчас происходит проверка имени. Если имя не указывается, то увеличение счетчика не происходит. Значением mac. id будет 1.
Множественное наследование
Некоторые объектно-ориентированные языки программирования позволяют осуществлять множественное наследование, при котором свойства и значения объекта могут быть унаследованы из нескольких объектов. В JavaScript нет множественного наследования.
Поскольку объект имеет единственное свойствоproto, то множественное наследование становится невозможным, объект не может наследовать свойства более чем из одного объекта. Однако в конструкторе объекта можно
использовать более одной функции-конструктора других объектов. Это в некоторой степени заменяет множественное наследование: function Dopolnitlno (uvlechenie) {
this.uvlechenie = uvlechenie II "boi_na_kulakah"; } function Injener (name, projs, mach, uvlechenie) {
this.naslediel = Rabotyaga;
this.naslediel(name, "Injenering", projs);
this.nasledie2 = Dopolnitlno;
this.nasledie2(uvlechenie); this.svoistvo = mach || ""; } Injener.prototype = new Rabotyaga; Karapuz = new Injener("Vasya, Karapuz", ["myt_tualet"], "tak_sebe") Предполагая, что Rabotyaga определен так, как было описано ранее, мы получаем такие значение свойств: Karapuz.name == "Vasya, Karapuz" Karapuz.otdel == "Injenering".
Karapuz.zadachi == ["myt_tualet"]
Karapuz.svoistvo == "tak_sebe"
Karapuz.uvlechenie == "boi_na_kulakah"
Объект Karapuz получил СВОЙСТВО uvlechenie ИЗ конструктора Dopolnitlno. Затем можно добавить новое свойство, вставив его в прототип конструктора Dopolnitlno:
Dopolnitlno.prototype.equipment = ["ertbyn", "tyjhrtj", "hhhrthhh", "csregkgj"]
При этом объект Karapuz не унаследует это новое свойство, так как "прямое" наследование из еще одного объекта невозможно.
Активные страницыАктивные страницы
Активные страницы
Активные страницы
Глава 4
Активные серверные страницы (ASP — Active Server Pages) — это технология компании Microsoft. В предыдущих главах мы рассмотрели статические HTML-документы и возможность их "оживления" на клиентской стороне средствами языков сценариев. Как правило, основным языком клиентских сценариев является JavaScript.
Как происходит связь между клиентом и сервером в Интернете? Клиент создает запрос и посылает его серверу, в запросе содержится информация о запрашиваемом документе. Сервер пытается найти этот документ. Если документ существует, то сервер отправляет его содержимое клиенту. Не всегда бывает интересно отправлять документ в статическом виде, т. е. в том виде, в каком он хранится на жестком диске. Часто оказывается полезным предварительно изменить документ. Для этого в документ вставляются сценарии, которые выполняются сервером. Если сервер находит файл со сценарием (он определяет это, например, по расширению файла), то сценарий выполняется, создается HTML-код, и этот код отправляется клиенту.
Именно для того, чтобы можно было включать в хранимую на сервере HTML-страницу выполняемый код, была создана технология активных серверных страниц. Технология была реализована на Web-серверах компании Microsoft. Однако почти все Web-серверы поддерживают эту технологию в той или иной мере. Под технологией активных серверных страниц в этом случае следует понимать возможность интерпретации сервером скриптов, включенных в HTML-страницу, перед тем, как страница будет отправлена клиенту, причем интерпретатор должен быть внутренним, встроенным в сервер средством. Поскольку интерпретатор языка ASP для каждого конкретного случая свой, то модель языка, а порой и его название, меняются от сервера к серверу. Существенно меняется и окружение, в котором происходит выполнение серверных скриптов.
При создании данной книги мы отдали предпочтение Web-серверу Sambar. Этот сервер использует технологию ASP в сочетании с языком CScript.
Устанавливаем сервер Sambar
*] ^Пдрзхсд ‘'IM*-*] ^Пдрзхсд ‘'IM*-Интерпретаторы и компиляторы многих языков могут работать на различных платформах. Выбор платформы зависит от большого количества факторов, в том числе от типа Web-сервера, с которым будет работать cgi- приложение. Технология ASP разработана компанией Microsoft и может быть использована только в тех случаях, когда Web-сервером является тот или иной сервер от Microsoft, работающий под операционной системой Windows. Мы имеем полную свободу выбора и можем воспользоваться, например, сервером Apache, который хорошо зарекомендовал себя при работе с Unix, или другими серверами.
*] ^Пдрзхсд ‘'IM*-
*] ^Пдрзхсд ‘'IM*-
J.. ^J.. ^4 а4 а>} Sambar Server - Microsoft Internet Explore!
J.. ^
J.. ^
4 а
4 а
,^ Назад r r
i' АйрвС leT^T^ccaihcsV
SAMBAR TECHNOLOGIES
Sambar Server V5.0 Beta 5
Search ToolsSearch ToolsFindFindSambar ServerSambar Server
Search Tools
Search Tools
Find
Find
Sambar Server
Sambar Server
Site Search HeinISAPI Search Tool Perl Search ToolSite Search HeinISAPI Search Tool Perl Search ToolPro Version DocumentationSecurity Suggestions Frequently Asked Questions Sambar Server SamplesPro Version DocumentationSecurity Suggestions Frequently Asked Questions Sambar Server Samples
Site Search Hein
ISAPI Search Tool Perl Search Tool
Site Search Hein
ISAPI Search Tool Perl Search Tool
Pro Version Documentation
Security Suggestions Frequently Asked Questions Sambar Server Samples
Pro Version Documentation
Security Suggestions Frequently Asked Questions Sambar Server Samples
rWW ResourcesrWW ResourcesWorld Wide Web Consortium NCSA HTTPd Anache Doctor HTML Neterali Survey WWW piIUWorld Wide Web Consortium NCSA HTTPd Anache Doctor HTML Neterali Survey WWW piIUС*ГотовоС*ГотовоSystem AdministrationThe System Administration page provides basic site management By default, the username is ’admin* and the password is blank. We recommend that you set a password for the admin account using the Admin link on the User Management page.System AdministrationThe System Administration page provides basic site management By default, the username is ’admin* and the password is blank. We recommend that you set a password for the admin account using the Admin link on the User Management page.ГТПйМестная интрасетьГТПйМестная интрасетьяя
rWW Resources
rWW Resources
World Wide Web Consortium NCSA HTTPd Anache Doctor HTML Neterali Survey WWW piIU
World Wide Web Consortium NCSA HTTPd Anache Doctor HTML Neterali Survey WWW piIU
С*Готово
С*Готово
System Administration
The System Administration page provides basic site management By default, the username is ’admin* and the password is blank. We recommend that you set a password for the admin account using the Admin link on the User Management page.
System Administration
The System Administration page provides basic site management By default, the username is ’admin* and the password is blank. We recommend that you set a password for the admin account using the Admin link on the User Management page.
ГТПйМестная интрасеть
ГТПйМестная интрасеть
я
я
Рис. 4.1. Основная страница сервера Sambar
Установим Web-сервер Sambar. Его можно найти и скачать по адресу http://www.sambar.com (размер несколько мегабайт). После того как программа установлена, заходим через последовательность Start -> Программы ->
SambarServer и запускаем сервер. Сервер работает. В браузере набираем адрес http://localhost (или http://127-0.0-l, или ЬИр://"имя вашего компьютера"), появляется главная страница сервера (рис. 4.1). Первое, что нам необходимо научиться делать, — это администрировать сервер. Для этого входим по ссылке System Administration (по умолчанию администраторский логин admin, пароль отсутствует; логин и пароль можно в дальнейшем заменить) на страницу администрирования (рис. 4.2).
^рес[а ittp/flocalhost/sysadrmn/mdex stm?systemeftp^рес[а ittp/flocalhost/sysadrmn/mdex stm?systemeftpЗ Sambar Server Administration - Microsoft Internet ExplorerЗ Sambar Server Administration - Microsoft Internet ExplorerПУПУ
^рес[а ittp/flocalhost/sysadrmn/mdex stm?systemeftp
^рес[а ittp/flocalhost/sysadrmn/mdex stm?systemeftp
З Sambar Server Administration - Microsoft Internet Explorer
З Sambar Server Administration - Microsoft Internet Explorer
ПУ
ПУ
LOGOUT Restart ServerLOGOUT Restart ServerServer Load: »»Server Load: »»сД Server DocumentationServer Configuration ^ System ManagementсД Server DocumentationServer Configuration ^ System ManagementUser ManagementUser ManagementServersServers
LOGOUT Restart Server
LOGOUT Restart Server
Server Load: »»
Server Load: »»
сД Server Documentation
Server Configuration ^ System Management
сД Server Documentation
Server Configuration ^ System Management
User Management
User Management
Servers
Servers
AU ServersAU ServersFTP ServerWWW ServerFTP ServerWWW ServerRunningRunningRunningRunningShow System Configuration Users Connections Threads File CacheSynchronize ClockNetwork I/O Performance Connection PerformanceConfigurationMappings/Aliases Security System Variables Virtual HostsReports HT1P Performance CGI PerformanceISAPIs In-Line Scalars RFCs Environment Variables config.ini iconmap.ini mime.ini vhosts.ini server.logShow System Configuration Users Connections Threads File CacheSynchronize ClockNetwork I/O Performance Connection PerformanceConfigurationMappings/Aliases Security System Variables Virtual HostsReports HT1P Performance CGI PerformanceISAPIs In-Line Scalars RFCs Environment Variables config.ini iconmap.ini mime.ini vhosts.ini server.log
AU Servers
AU Servers
FTP Server
WWW Server
FTP Server
WWW Server
Running
Running
Running
Running
Show System Configuration Users Connections Threads File Cache
Synchronize Clock
Network I/O Performance Connection Performance
Configuration
Mappings/Aliases Security System Variables Virtual Hosts
Reports HT1P Performance CGI Performance
ISAPIs In-Line Scalars RFCs Environment Variables config.ini iconmap.ini mime.ini vhosts.ini server.log
Show System Configuration Users Connections Threads File Cache
Synchronize Clock
Network I/O Performance Connection Performance
Configuration
Mappings/Aliases Security System Variables Virtual Hosts
Reports HT1P Performance CGI Performance
ISAPIs In-Line Scalars RFCs Environment Variables config.ini iconmap.ini mime.ini vhosts.ini server.log
Proxies
AU ProxiesAU ProxiesConfigurationConfiguration- р^Г^^’местная интрасеть- р^Г^^’местная интрасеть
AU Proxies
AU Proxies
Configuration
Configuration
- р^Г^^’местная интрасеть
- р^Г^^’местная интрасеть
Рис. 4.2. Страница администрирования сервера
Мы вновь вернемся к администрированию сервера Sambar в следующей главе. Сейчас нам важно помнить, что все документы мы будем располагать в каталоге сервера /docs. Поместим в него простой HTML-файл simple.html:
( Файл simple.html
<html>
<head>
<title>Example HTML</title>
</head>
<body>
<div align=center>
Простой HTML-файл на сервере Sambar.
</div>
</body>
</html>
Ц Example HTML - Microsoft Internet Explore!
J Фейи Дравке' £иа Избранное Сервис Справка ]йарес|® http://localhost/simple.html
ИИ щ
3
Простой HTML-файл на сервере Sambar.
Рис. 4.3. Файл загружен по запросу браузера с сервера
а 31
^^Памота
Disable POP3 Enhanced
Running
Enable
Running
POP3 Proxy
Real/AV Proxy
SMTP Proxy
Services
ASP Pages Compression DBMS Scripting DOT-File Security HTAccess JavaEnglne
Disable Enable Enable Disable Enable
Enable
CScript Packages Control Panel Performance
Monitor Invalid Logins Enable
Performance Monitor Scheduler Daemon Search Engine Watcher Daemon
Disable
Running Running Enable
Schedule Tasks Show Tasks
Configuration Show Indexes Performance stopwordani
eS
Т»
Сохраним его в каталоге, где размещен сервер Sambar, в папке /docs. После это вызовем браузер и введем адрес http://localhost/simple.html. В окне браузера будет отображен наш файл (рис. 4.3).
Сейчас мы создадим простейший ASP-файл. Сервер будет распознавать активные файлы по расширению, так он устроен. Не следует размещать ASP- файлы в каталог cgi-bin. Чтобы сервер понимал ASP, необходимо его сконфигурировать. Заходим на страницу конфигурирования и включаем работу ASP, как это показано на рис. 4.4.
Простейший ASP-скрипт
Как всегда, начнем сразу с примера. Вот текст простейшего скрипта ASP, файл cscriptl.asp.
! Файл cscriptl.asp
<html>
<head>
<title>Example</title>
</head>■
<body>
printf("Hello ASP world!");
%>
</body>
</html>
В браузере запрашиваем страницу с адресом http://localhost/cscriptl.asp.
В окне браузера получаем ответ (рис. 4.5).
-|СТх-|СТх'Э Example - Microsoft Internet Explorer
-|СТх
-|СТх
]йдрм?ь|ё] httpV/tocalhost/cscnptl у | ^Лереж» jjjJnks
Hello ASP world!
Рис. 4.5. Первый ASP-скрипт благополучно выполнен
Из примера понятно, что скрипт вставляется непосредственно в HTML- страницу, между символами <% и %>. В данном примере скрипт выводит текст "Hello ASP world!" с помощью функции printf.
Чтобы научиться пользоваться возможностями ASP, необходимо овладеть деталями языка для данного сервера, а также знать особенности самого сервера.
Вопросы безопасности
Разработчики сервера сообщают, что язык CScript постоянно совершенствуется, его возможности приближаются к возможностям языка С. Когда скрипты используются даже как интерпретируемые фрагменты HTML- страниц, то и в этом случае они выполняются в таком окружении, что существует возможность осуществлять доступ к файловой системе, запускать программы в режиме командной строки, открывать сетевые соединения. Важно иметь в виду, что серверные страницы могут быть выключены либо для всего сервера в целом в файле config/config.ini, либо для каких-то конкретных каталогов, что отражается в htaccess-файле (параметр поехес).
Сравниваем С и CScript
Сравним два простых фрагмента кода на С и на CScript. Вот простая программа на С: void main() (
printf("Hello WorldXn");
}
Когда мы создаем ASP-страницу, мы можем записать так: <htmlxbody>
<%
printf("Hello World!");
%>
</bodyx/html>
Результат будет такой же, как и при работе программы на С, будет выведено сообщение "Hello World". Программа на С содержит функции и переменные. Необходимо, чтобы была описана функция Main о, в которой содержится общая логика программы. ASP-скрипт помещает фрагменты скриптов HTML-страницы внутрь функции main» , существующей неявно.
Приведенный выше код вызывает функцию printf из библиотеки вво- да/вывода. Полное описание библиотек можно найти в документации по серверу.
Программу можно переписать в более подробном виде, результат ее работы будет неизменен (рис. 4.6.).
|:Файл cscript2.asp■
<HTMLXBODY>
<%
main(){printf("Hello World\n");}
Hello World*
Рис. 4.6. Программа работает по-прежнему
Этот пример можно переписать в еще более детальном виде (файл cscript3.asp, рис. 4.7).
' Файл cscript3.asp
<HTML>
<BODY>
<% main() (
= 1;
= 2;
= 3;
um = a + b + c;
printf("sum is %d\n", sum);
}
%>
^ http://localhost/cscript3.asp - Microsoft Internet..
ltkws Риа й^Г^н^ Су. t Ьи^г http //localhost/cscnptS.asp *] ‘^Перейв".
sum is 6
Рис. 4.7. Более сложная конструкция
Различия между CScript и С
CScript — это подмножество языка С, но разработчики предпринимают усилия, чтобы он стал полноценным языком С, используемым для создания активных серверных страниц.
Различия в синтаксисе
Свойства языка CScript перечислены ниже:
не обязательно использование блока main ();
объявление переменных не обязательно;
указание типов не обязательно, возможно явное преобразование типов, например
b = 1; а = (string)b;
тип unsigned не используется;
модификатор static не используется;
тип const не используется;
не поддерживаются макросы;
оператор сото не используется;
структуры, объединения и нумераторы (structure, union, enum) не используются.
Различия в операторах
Свойства операторов языка CScript приведены далее:
операторы +, <, <=, >, >=, ==, != могут быть использованы при работе со строками;-■
оператор [ ] автоматически производит проверку диапазона;
оператор sizeof возвращает количество элементов массива, длину строки, количество байт;
оператор typeof получает идентификатор типа объекта.'
Различия в переменных
Свойства переменных языка CScript:
локальные переменные видны только в пределах блока функции;
все переменные неявно инициализируются нулем;
массивы могут увеличиваться и иметь произвольные элементы, т. е. элементы различных типов;
ссылки на объекты используются только при передаче данных от внешних программ.
Различия в структуре
В языке Cscript не поддерживаются заголовочные файлы. Пользовательские библиотеки и функции должны быть включены в программу в явном виде, например, #include <foo.c>.
ASP от Microsoft
Microsoft — законодатель моды в технологиях ASP. Было бы несправедливо обойти вниманием ASP от Microsoft. Мы предпочтем воспользоваться сервером IIS, который входит в комплект Windows 2000 Server. Убедитесь, что IIS установлен, если он не установлен, то установите его. Он входит в состав компонентов Microsoft (рис. 4.8). -
to add dr remove a component, cfcfi the checkbox. A shaded box means that only.
.. part of the component will be instaied. T о see what s included in a component, clidk * Details Components: ..
1.4 MB ^J'*-00MB I 1 ■22.1 MB' ,5.5 MB42 A MB Zj "1.4 MB ^J'*-00MB I 1 ■22.1 MB' ,5.5 MB42 A MB Zj ", _] Certificate Services Я ^Indexing Service Я ^Internet Information Services (IIS]
1.4 MB ^J'*-
00MB I 1 ■
22.1 MB' ,
5.5 MB4
2 A MB Zj "
1.4 MB ^J'*-
00MB I 1 ■
22.1 MB' ,
5.5 MB4
2 A MB Zj "
''П 3З Management and M onitonng Tools
Чтобы проверить конфигурацию сервера IIS, откроем меню Start ->
-[□lx-[□lxPrograms -> Administrative Tools -> Internet Services Manager (рис. 4.9).
-[□lx
-[□lx
^g Internet Information Services
Tree |Q-^| Default FTP SiteTree |Q-^| Default FTP SiteNameNameI PathI Pathe^ie^iDefault Web SitejDefault Web SitejEl Cj| Scripts ffi Ж USHelpS- ж IISAdminВ 38 IlSSamplesШ § MSADCВ Qj PrintersEl Cj| Scripts ffi Ж USHelpS- ж IISAdminВ 38 IlSSamplesШ § MSADCВ Qj Printers^IISHelp ^IISAdmin j^HSSamples ^MSADC^IISHelp ^IISAdmin j^HSSamples ^MSADCO classesO classesc:\inetpub\scriptsc: \winnt\help\iishelpC:\WIN N T\System32\inetsrv\iisadminc: \inetpub\iissamplesc:\program filesScommon files\system\msadcC:\WINNT\web\printersC:\Program FilesSCommon FilesSMicrosoft SharedWeb Se.c:\inetpub\scriptsc: \winnt\help\iishelpC:\WIN N T\System32\inetsrv\iisadminc: \inetpub\iissamplesc:\program filesScommon files\system\msadcC:\WINNT\web\printersC:\Program FilesSCommon FilesSMicrosoft SharedWeb Se.
Tree |
Q-^| Default FTP Site
Tree |
Q-^| Default FTP Site
Name
Name
I Path
I Path
e^i
e^i
Default Web Sitej
Default Web Sitej
El Cj| Scripts ffi Ж USHelp
S- ж IISAdmin
В 38 IlSSamples
Ш § MSADC
В Qj Printers
El Cj| Scripts ffi Ж USHelp
S- ж IISAdmin
В 38 IlSSamples
Ш § MSADC
В Qj Printers
^IISHelp ^IISAdmin j^HSSamples ^MSADC
^IISHelp ^IISAdmin j^HSSamples ^MSADC
O classes
O classes
c:\inetpub\scripts
c: \winnt\help\iishelp
C:\WIN N T\System32\inetsrv\iisadmin
c: \inetpub\iissamples
c:\program filesScommon files\system\msadc
C:\WINNT\web\printers
C:\Program FilesSCommon FilesSMicrosoft SharedWeb Se.
c:\inetpub\scripts
c: \winnt\help\iishelp
C:\WIN N T\System32\inetsrv\iisadmin
c: \inetpub\iissamples
c:\program filesScommon files\system\msadc
C:\WINNT\web\printers
C:\Program FilesSCommon FilesSMicrosoft SharedWeb Se.
E' Si classes £ D auctionE' Si classes £ D auctionLJ _vti_pvtLJ _vti_pvtW Cj „vtijog Э О „private $ Cj „vtijxtW Cj „vtijog Э О „private $ Cj „vtijxtQj „privateQj „privateSi.,vti_scriptSi.,vti_script
E' Si classes £ D auction
E' Si classes £ D auction
LJ _vti_pvt
LJ _vti_pvt
W Cj „vtijog Э О „private $ Cj „vtijxt
W Cj „vtijog Э О „private $ Cj „vtijxt
Qj „private
Qj „private
Si.,vti_script
Si.,vti_script
Si images
Cj maps Щ clienlhtmlCj maps Щ clienlhtmll£ S] images
Cj maps Щ clienlhtml
Cj maps Щ clienlhtml
M Qi maps
S A Administration Web Site *.
Рис. 4.9. Конфигурирование сервера
Первый файл с ASP
ASP — это просто. Файл активных серверных страниц содержит ASP- вставки, которые выполняются сервером, и код HTML, который передается клиентскому агенту без изменений.
Создадим файл asp 1.asp и поместим его в основной каталог сервера wwwroot.
Файл aspl.asp
<html>
<head>
<title>First ASP Page.</title>
</head>
<body>
<Н1 align=center>This is our first ASP script page.</hl>
<P>Green font text is script generated text:
<font color=green size=+2>
<%
response.write("Kak pogoda horosha! — This is instead of <b> Hello world</b>!")
%>
</font>
</body>
</html>
Откроем браузер и перейдем по адресу http://localhost/aspl.asp. Результат работы активных серверных страниц показан на рис. 4.10.
z3 First ASP Page. - Microsoft Internet Explorer
>'' E-ir-Vew - FavotteT Took'; Heb;, Address [^ HUpV/localhost/aspI asp
This is our first ASP script page
Green font text is script generated text: Кзк pOgoda llOfOsha! This is instead of Hello world!
Рис. 4.10. Первый ASP-скрипт в работе
В скрипте мы воспользовались методом write объекта response. Этот метод помогает осуществлять запись в стандартный вывод. Объект response обладает и другими методами. Встроенные объекты ASP сервера IIS не ограничиваются объектом response. Краткая справка по объектам севера IIS приведена в приложении 2.
Примеры ASP-страниц
Мы разберем несколько несложных примеров работы с ASP, после чего создание ASP-страниц не будет составлять для читателей никакого труда.
Обработка информации, полученной из HTML-форм
HTML-форму зададим в виде такого кода.
| код html.V:^^£$fW^У®*^I
<HTML>
<HEAD>
<TITLE>Form Data Processing</TITLE>
</HEAD>
<BODY BGCOLOR="White" TOPMARGIN="10" LEFTMARGIN="10">
<FONT SIZE="4" FACE="ARIAL, HELVETICA">
<B>Form Posting</BX/FONTXBR>
<HR>
<P>This page will take the information entered in the form fields, and use the POST method to send the data to an ASP page.
<FORM NAME=Forml METHOD=Post ACTION="asp3.asp"> First Name: <INPUT TYPE=Text NAME=fnameXP> Last Name: <INPUT TYPE=Text NAME=lnameXP> <INPUT TYPE=Submit VALUE="Submit">
</FORM>
<HR>
</BODY>
</HTML>
В этот код мы вставим пару строк кода ASP:
<% Response.Write Request.form ("fname")%>
<% Response.Write Request.form("Iname”)%>
Страница для обработки формы практически готова. Мы собираемся упаковать ее в один файл asp2.asp.
■ Файл asp2.asp
<%@ Language = VBScript %>
<HTML>
<HEAD>
<TITLE>Form Data Processing</TITLE>
</HEAD>
<BODY BGCOLOR="White" TOPMARGIN="10" LEF7MARGIN="10">
<FONT SIZE="4" FACE="ARIAL, HELVETICA">
<B>Form Posting</BX/FONTXBR>
<HR>
<P>This page will take the information entered in the form fields, and use the POST method to send the data to an ASP page.
<FORM NAME=Forml METHOD=Post ACTI0N="asp2.asp"> First Name: <INPUT TYPE=Text NAME=fnameXP> Last Name: <INPUT TYPE=Text NAME=lnamexP> <INPUT TYPE=Submit VALUE="Submit">
</FORM>
<HR>
<b>Hello, <i>
<% Response.Write Request.form("fname")%>
<% Response.Write Request.form("Iname")%>
</i>
, you are welcome!</b>
</BODY>
</HTML>
Результат работы скрипта показан на рис. 4.11.
Form Posting
This page will take the information entered in the form fields, and use the POST method to send the data to an ASP page.
First Name: I!
Last Name: |. -
Submit |
Hello, OxanaNikolenko, you are welcome!
z3 Form Posting - Microsoft Internet Explorer
File Edit View- Favorites Tools Help ' -'•■
Adcess [Zjhttp://localhosVasp3.asp^ ’ ^ So
Form Input Processing
Input your First Name: f Input your Last Name: f Submit'.
Hello, Andrei Polyakov, you are welcome!
Рис. 4.12. Скрипт на JScript работает точно так же
Приведенный выше скрипт написан с помощью языка VBScript. Этот язык, по традиции, наиболее часто используется при создании серверных ASP- скриптов для серверов Microsoft. Visual Basic Script не единственный язык, который понимает сервер IIS. Этот же скрипт можно написать, например, используя JScript, т. е. JavaScript в версии Microsoft. Вариант на JScript приведен в файле asp3.asp. Результат работы показан на рис. 4.12.
! Файл asp3.asp.'
<%@ Language = JScript %>
<HTML>
<HEAD>■
<TITLE>Form Posting</TITLE>
</HEAD>
<BODY BGCOLOR="White" TOPMARGIN="LO" LEFTMARGIN="10">
<FONT SIZE="4" FACE="ARIAL, HELVETICA">
<B>Form Input Processing</Bx/FONT><BR>
<HR>
<P>
<F0RM NAME=Forml METHOD=Post ACTI0N="asp3.asp">
Input your First Name: <INPUT TYPE=Text NAME=fnamexP>
Input your Last Name: <INPUT TYPE=Text NAME=lnameXp>
<INPUT TYPE=Submit VALUE="Submit">
</FORM>
<HR>
<b>Hello, <i>
<% Response.Write (Request.form("fname"));%>
<% Response. Write (Request, formflname")) ;%>
</i>
, you are welcome!</b>
</BODY>
</HTML>
Работа c ASP-компонентами
Вернемся к простым примерам. Создадим ASP-файл для вывода текста шрифтом разного размера.
Файл asp4.asp
<%@ LANGUAGE=VBScript %>
<HTML>
<BODY><p align=center>
<% For i = 1 To 7 %>
<FONT SIZE=<% = i %» Have a nice day!<BR>
</FONT>
<% Next %> </p>
</BODY>
</HTML>
В окне браузера мы увидим картинку, показанную на рис. 4.13. Размер шрифта можно изменить непосредственно в браузере, тот же самый код HTML будет выглядеть по-другому (рис. 4.14).
Конечно, такой скрипт тоже может оказаться полезным, однако сервер IIS позволяет использовать гораздо более богатые возможности, которые открываются перед нами, когда мы пользуемся компонентами ASP, которые можно создавать и самим. Создадим несложный ASP-компонент, в соответствии с тем, который описан в документации по ASP. Для создания компонента выберем язык Visual Basic. Для этого можно использовать, например, Visual Basic 6.0 из Microsoft Visual Studio 6.
Откроем Visual Basic, и в меню File -> New Project выберем пиктограмму ActiveX DLL (рис. 4.15).
Полезно указать свойства проекта. В меню Project выбираем команду Projectl Properties (рис. 4.16).
В качестве имени зададим MS, установим флажок Unattended Execution (рис. 4.17). В окне справа мы можем задать свойства класса (рис. 4.18).
Рис. 4.13. Скрипт выводит текст шрифтами разной величиныРис. 4.13. Скрипт выводит текст шрифтами разной величины
Рис. 4.13. Скрипт выводит текст шрифтами разной величины
Рис. 4.13. Скрипт выводит текст шрифтами разной величины
Э http://Iocalhost/asp4.asp - Microsoft Internet Exploitri^BBjlЭ http://Iocalhost/asp4.asp - Microsoft Internet Exploitri^BBjl
Э http://Iocalhost/asp4.asp - Microsoft Internet Exploitri^BBjl
Э http://Iocalhost/asp4.asp - Microsoft Internet Exploitri^BBjl
Fie Edit View Favo^tes Tools uelpESI
Address |&] http://localhost/asp4.asp^ ^S<J |
Hwe a nice dy!
Have a nice day!
Have a nice day!
Have a nice day!
Have a nice day!
Have a nice day!
Have a nice day!
Рис. 4.15. Создаем новый проект
ГЁ'О|ес1 Fgrmat jlebug Bun Q'13 Add EarnI
&AddModule 1 '; 5 ' I Й Add Qatt Module
"ij$ Add User Control\
" iS Add Eroperfy Page
•I®) Add User document•
AddWebClass * ' • ‘‘ '■
Add Data Report Add DHTML Page Add Data Environment More ActiveX Designert , > 'SddFie Clrto' ’
Bemove Clast!
6 Reference*. ' * -( Components 1 Ctrl*! I
Рис. 4.17. Создаем проект
Alphabetic | categorized |.
i(Name){Classi
iDataBindingBehavitO - vbNone
|DataSourceBehavic 0 - ybNone
1___2ВИ57MultiUse " ^| X MTSTransactionMotO - NotAnMTSObji $ Persistable :0 - NotPersistable
Instancing
Instancing
Sets a value that specifies whether you can create Instances of a public
Класс назовем Finance (рис. 4.19).
В классе запишем такой код (рис. 4.20):
Public Function CalcFV(rate, nper, pmt, Optional pv, Optional whendue) CalcFV = FV(rate, nper, pmt, pv, whendue)
End Function
Здесь мы использовали готовую функцию fv.
Properties - Finance •
^Finance ClassModuIe
Alphabetic Categorized |
В Mise
|(Name)
DataBindingBehavO - vbNoneDataSourceBehav 0 - vbNone
Instancingt5 - MultiUse
IMTSTransactionM 0 - NotAnMTSOt
Persistablei 0 - NotPersistab ■
Рис. 4.19. Класс назовем Finance
A MS - Finance (Code)
|(General)^jcaleFVv| ?
Public Function CalcFV (rate, nper, pmt, Optional pv, Optional whendue)"$';
CalcFV = FV(rate, nper, pmt, pv, whendue)•^:
End Functionj0 ‘
Рис. 4.20. Создаем функцию CalcFV
Серверные компоненты требуют, чтобы была задана точка вхождения. Для этого необходимо вставить модуль, который представляет собой функцию main. В меню Project выберем команду Add Module (рис. 4.21). В окне модуля введем код: Sub Main () End Sub
Редактор с кодом показан на рис. 4.22.
||Add Module||Add ModuleГ5°jact' Fermat Qebug Run Q'tj. Add Ferm . IЙ Add MD; -erm I
||Add Module
||Add Module
& Add Class ModuleI
^ Add User Control .
S Add Erapert'yPageЛ
^[ Add User Qpcumerit , ,
Add WebClass •
.. Add Data Repo-t . ,
' ■ Add DHTML Page
Add Data, Environment
More ActiveX Designers..; ►
RddFie... Ctrl+D ■
. Remove Finance ' -
6 References... ■ '
Сртропеп^м. Ctd+T
M5 Properties,..
Рис. 4.21. Создаем модуль для точки вхождения
I - ;MS - Module 1 (Code)
=JL3i2g
"S;|(General)v| (Main
Sub Main()"
Encl Sub
Рис. 4.22. Модуль создан
Процедура main о вызывается тогда, когда мы обращаемся к методу Server.CreateObject.
Сохраним проект под именем Finance.cis в папке \WINNT\system32\inetsrv.
Однако нам нужна библиотека dll. Создадим ее. Выберем меню File -> Make MS.dll и запомним библиотеку в папке \WINNT\system32\inetserv под именем Finance.dll. Зарегистрируем библиотеку. Для этого зайдем в папку \WINNT\system32\inetserv и из командной строки выполним команду regsvr32 finance.dll (рис. 4.23).
Рис. 4.23. Регистрируем библиотеку ms.dll в системе
Теперь создадим простой HTML-файл aspcomponent.html.
Файл aspcomponenthtml
<html>
<HEAD>
<TITLE>Our own ASP component</TITLE>
</head>
<body>
<НЗ>ОПРЕДЕЛЯЕМ, СКОЛЬКО БУДЕТ НА СЧЕТУ ПО ИСТЕЧЕНИИ ЗАДАННОГО СРОКА.</НЗ>
<FORM METHOD=POST ACTION="finance.asp">
<TABLE>
<TR>
<ТОЖакую сумму вы будете откладывать каждый месяц?</ТО>
CTDXINPUT TYPE=TEXT NAME=Payment> </TD>
</TR>
<TR> <ТОЖаков годовой процент по вкладу? </TD>
CTDXINPUT TYPE=TEXT NAME=APR> </TD>
</TR>
<TR>
<ТОЖак долго вы будете накапливать? </TD>.
CTDXINPUT TYPE=TEXT NAME=TotPmts> </TD>
</TR>.
<TR>
<TD>B начале или в конце месяца вы будете вносить деньги? </TD>
<TD><INPUT TYPE=RADIO NAME=PayType VALUE="Beginning" CHECKED>Beginning
CINPUT TYPE=RADIO NAME=PayType VALUE=”End">End </TD>
</TR>
<TR>
<ТВЖакая сумма у вас сейчас на счету? </TD>
CTDXINPUT TYPE=TEXT NAME=PVal> </TD>■
</TR>
<TR>.
<TD> </TD>
<TD><INPUT TYPE=SUBMIT VALUE=" Сосчитать сумму на конец периода "></TD>
</TR>
</TABLE>
</FORM>
</BODY>
</HTML>
Форма посылается скрипту finance.asp.
Файл finance.asp
<%@ LANGUAGE = VBScript %>
<html>
<HEAD>
<TITLE>Calculations are ready</TITLE>
</head>
<body>
<%
' Был ли введен годовой процент If IsNumeric(Request("APR")) Then ' был ли процент введен верно If Request("APR") > 1 Then APR = Request("APR") / 100 Else
APR = Request("APR")
End If
Else
APR = 0
End If
* Введено ли количество месяцев
If IsNumeric(Request("TotPmts")) Then TotPmts = Request("TotPmts") Else TotPmts = 0 End If
' Введен ли размер месячного платежа If IsNumeric(Request("Payment")) Then Payment = Request("Payment") Else Payment = 0 End If
' Введена ли сумма на счету If IsNumeric(Request("PVal")) Then PVal = Request("PVal") Else PVal = 0 End If
'Когда вносится платеж If Request("PayType") = "Beginning" Then PayType = 1 ' BeginPeriod Else PayType = 0 ' EndPeriod End If
' Создаем экземпляр объекта Finance
Set Finance = Server.CreateObject("MS.Finance")
' Используем созданный экземпляр объекта ' для расчета суммы на счету в будущем ' на основе данных, полученных из формы, ' и с использованием метода CalcFV.
FVal = Finance.CalcFV(APR / 12, TotPmts, -Payment, -PVal, PayType) %>-
<h3 align=center>Your account will hold <font size=+2 color=blue> <%= Formatcurrency(FVal)%></font>.</h3> </BODY> </HTML>
Разместим файл aspcomponent.html и finance.asp на сервере в каталоге wwwroot и обратимся из браузера к файлу aspcomponent.html. Вводим в текстовые поля требуемые значения (суммы в долларах и количество месяцев, а также банковский процент) для обработки (рис. 4.24).
После нажатия кнопки Сосчитать сумму на конец периода, браузер отобразит ответ (рис. 4.25).
ГПВГПВ^Ош own ASP component - Microsoft Internet Explorer - (Working Offline]
ГПВ
ГПВ
J' File Er# View /Favorite®- Todt, Help‘J '” ^'^
j 4я Back v ** :* ^'Й S ^Search j^Favorites yHetoji ; ^’ ^ ^J <1§)
i Address |SJhttp://localhosl/aspcamponenl hlmli Address |SJhttp://localhosl/aspcamponenl hlmlОПРЕДЕЛЯЕМ, СКОЛЬКО БУДЕТ НА СЧЕТУ ПО ИСТЕЧЕНИИОПРЕДЕЛЯЕМ, СКОЛЬКО БУДЕТ НА СЧЕТУ ПО ИСТЕЧЕНИИ" S' Г7 ®л«1 intranet . :/^" S' Г7 ®л«1 intranet . :/^Рис. 4.24. Вводим данные в форму для обработки собственным ASP-компонентомРис. 4.24. Вводим данные в форму для обработки собственным ASP-компонентом
i Address |SJhttp://localhosl/aspcamponenl hlml
i Address |SJhttp://localhosl/aspcamponenl hlml
ОПРЕДЕЛЯЕМ, СКОЛЬКО БУДЕТ НА СЧЕТУ ПО ИСТЕЧЕНИИ
ОПРЕДЕЛЯЕМ, СКОЛЬКО БУДЕТ НА СЧЕТУ ПО ИСТЕЧЕНИИ
" S' Г7 ®л«1 intranet . :/^
" S' Г7 ®л«1 intranet . :/^
Рис. 4.24. Вводим данные в форму для обработки собственным ASP-компонентом
Рис. 4.24. Вводим данные в форму для обработки собственным ASP-компонентом
^| Calculations are ready - Microsoft Internet Explorer|ЭДв1Ё®-111
Henbit View - Favorites toolsAdae»[^http://localho$t/fmance asp
Your account will hold $7,217.79.
Рис. 4.25. Результат вычислений
Резюме
Мы создали собственный ASP-компонент. Для этого мы воспользовались языком Visual Basic, создав в нем проект ActiveX, в котором описали метод CaicFV, скомпилировали проект в виде библиотеки finance.dll, затем зарегистрировали библиотеку в системе. В ASP-файле мы создали экземпляр объекта finance и вызвали его метод.
Глава 5
Создание серверных приложений на языке PHP
Настоящая глава посвящена созданию независимых Web-приложений. Web- приложения требуют для своей работы наличия Web-серверов, своеобразных программ-посредников. Серверы обрабатывают клиентские запросы, и если в этих запросах появляется обращение к файлу, содержащему CGI-программу, то результат выполнения этой программы сервер передаст браузеру в соответствии с инструкциями, описанными в программе. Что передавать, в каком виде и как это осуществляется, описано в стандарте CGI (Common Gateway Interface).
Для создания CGI-приложений можно использовать практически любой язык программирования. Однако существуют такие языки, как PHP и Perl, которые специально разрабатывались как языки, предназначенные для создания CGI-приложений. Средства, наиболее часто используемые в CGI- программировании, организованы в них в наиболее компактном и удобном виде. Такие языки часто оказываются интерпретируемыми языками, т. е. программный код анализируется интерпретатором языка в момент обращения к нему и тут же прочитанная программа выполняется. Поэтому следует иметь в виду, что в некоторых случаях, когда особенно важным оказывается быстро выполнения программ, необходимо использовать частично или полностью другие языки, например, C++ или Java. Скорость выполнения скомпилированных программ не всегда оказывается выше, чем скорость выполнения интерпретируемых программ. На скорости отражается общая архитектура приложения, наличие запросов к сторонним серверам, базам данных и т. п. Всегда необходимо искать разумный компромисс между сложностью приложений, скоростью работы и экономичностью создания программ.
Устанавливаем
Web-сервер
В гл. 4 было подробно рассмотрено, как установить Web-сервер Sambar (рис. 5.1). В данном разделе займемся вопросами его администрирования. Для этого откроем страницу администрирования сервера Sambar (рис. 5.2).
2ШЗ2ШЗВся информация представлена довольно компактно и удобно. Здесь есть ссылка на документацию, ссылка на страницу конфигурирования сервера, ссылка на страницу управления пользователями, страницу управления системой. Зайдем на страницу конфигурирования сервера (рис. 5.3).
2ШЗ
2ШЗ
'3 Sambar Server - Microsoft Internet Explorer - [Автономная работа}
[1<й^|6"http://locaho$t/[1<й^|6"http://locaho$t/Остановить Обновить Домой Поиск Избранное Жщнал Почта
[1<й^|6"http://locaho$t/
[1<й^|6"http://locaho$t/
SAMBAR TECHNOLOGIES
Sambar Server V5.0Beta 5
Search ToolsSearch ToolsFindFindSambar ServerSambar Server
Search Tools
Search Tools
Find
Find
Sambar Server
Sambar Server
Site Search Help ISAPI Search Tool Perl Search ToolSite Search Help ISAPI Search Tool Perl Search ToolPro Version Documentation Security Suggestions Frequently Asked Questions Sambar Server SamplesPro Version Documentation Security Suggestions Frequently Asked Questions Sambar Server Samples
Site Search Help ISAPI Search Tool Perl Search Tool
Site Search Help ISAPI Search Tool Perl Search Tool
Pro Version Documentation Security Suggestions Frequently Asked Questions Sambar Server Samples
Pro Version Documentation Security Suggestions Frequently Asked Questions Sambar Server Samples
i¥WW Resourcesi¥WW ResourcesWorld Wide Web Consortium NCSAHTTPd Apache Doctor HTML Netcraft Survey WWW PingWorld Wide Web Consortium NCSAHTTPd Apache Doctor HTML Netcraft Survey WWW PingSystem AdministrationThe System Administration page provides basic site management. By default, the username is 'admin' and the password is blank. We recommend that you set a passwordSystem AdministrationThe System Administration page provides basic site management. By default, the username is 'admin' and the password is blank. We recommend that you set a password
i¥WW Resources
i¥WW Resources
World Wide Web Consortium NCSAHTTPd Apache Doctor HTML Netcraft Survey WWW Ping
World Wide Web Consortium NCSAHTTPd Apache Doctor HTML Netcraft Survey WWW Ping
System Administration
The System Administration page provides basic site management. By default, the username is 'admin' and the password is blank. We recommend that you set a password
System Administration
The System Administration page provides basic site management. By default, the username is 'admin' and the password is blank. We recommend that you set a password
Sambar Server Administration
Current Time: Tue, 01 Oct 2002 22:13:08
Server Started: Tue, 01 Oct 2002 22:10:55
I^OGOLJT Restart Server
Server Load: >>»
гД Server Documentation
^> Server Configuration
System Management
jS^l Pro License;
№ User Management<
AU Servers
Show System Configuration Users
Connections Threads File Cache
Synchronize Clock
Network I/O Performance Connection'
Performance
Рис. 5.2. Страница администрирования сервера Sambar
it". ВИ»./',^-. f»ow*«i 0«Hew»‘:'ijG6' 1. new'’time» 'ijw ** ^ПотГ^печ»»?^" ^.-^
^Jfi№66j€J htip./A>catK>st/$ys»±r>n/coriigtim
^ гГеремб a*«w
System Administrator
4J
The System Administrator username is used to accessU
these sysadmin folder and administrator methods. Byfl
1 adminЦ
default, the administrator username is ’admin’.Ж
System Administrator IP
If left blank, the Sambar Server System Administrator may login from any host A space-separated list of IP addresses may be provided (the wild-card character ’•’ may be used,
|127.O.O.1
i.e. 140.172.165.*) to ensure that only hosts which you plan to use for administration have access to your System Administration tools. For maximum security, only allow access to the ”localhost" account (127.0.0.1).
User IP
If left blank, Sambar Server users may login from any host. A space-separated list of IP addresses may be provided (the wild-card character ’*' may be used, i.e.
140.172.165.*) to ensure that only hosts which you plan to use for user logins have access to your server.if)
Server Port
The TCP/IP protocol has a number of ports which are used to differentiate requests to different processes. The
I60.
standard HTTP port number is 80. You can choose any port number from 1 to 65000, however, many port* ’
numbers on your system are reserved for otherW
applications. Should you choose any port other than port $1
; ■■•■■;■>" "■aiAnwwwKm ;-■-<
На этой странице мы находим, что каталог, в котором будут располагаться документы, — это docs/, а выполняемые программы расположены в каталоге cgi-bin/. Кроме того, здесь можно задать расширения для файлов выполняемых программ (например exe, php, cgi).
Проверим, сможет ли возвратить наш сервер запрашиваемый файл. Создадим простой HTML-файл ask.html.
i Файл ask.html
<html>
<head>
<title>
Ask file
</title>■
<body>
<hl>Simple trial file</hl>
</body>_
</html>
Найдем в каталоге, где размещен сервер Smabar, подкаталог docs, и скопируем в него файл ask.html. В браузере обратимся к URL с адресом http://localhost/ask.html. Если сервер работает, то в окне увидим текст нашего файла (рис. 5.4).
Устанавливаем интерпретатор PHP
В этой главе мы рассмотрим возможности программирования с использованием языка PHP. Скомпилированные программы и исходный код языка могут быть скачаны с сайта http://www.php.net. Установим пакет PHP. Создадим простейший PHP-файл, который назовем test.php.
I Файл testphp
<?
echo "<hl>this is php</hl>";
Если вы работаете в Windows, то щелкните на файле test.php мышью, и, при условии, что PHP зарегистрирован в системе, файл автоматически будет выполнен. Если система "не узнает" файл по расширению, то расширение нужно зарегистрировать. Простейший способ выбрать в диалоговом окне, появившемся после щелчка мышью на файле test.php, программу php.exe (в каталоге, куда был установлен PHP) и отметить, что эта программа будет вызываться всякий раз при обращении к файлам с расширение php (поле для установки флажка слева внизу). При запуске файла test.php будет появляться консольное окно, в котором отображается результат работы этой программы.
Разместим файл test.php в каталоге выполняемых файлов сервера Sambar, в cgi-bin/. В браузере укажем адрес http://Iocalhost/cgi-bin/test.php, после чего в окне браузера появится результат работы программы, записанной в файле test.php (рис. 5.5).
Рис. 5.5. Результат работы программы сервер передает браузеру
Вернемся на несколько строк назад и уделим немного внимания администрированию сервера Sambar.
Работающий сервер выводит информацию о запросах в специальное окно, которое можно вызвать, щелкнув на пиктограмме сервера на панели задач (рис. 5.6).
Н Sambar Server
Sambar Server VS 0Sambar Server VS 0Sambar Server ‘olymp.80" IP Address: 127.0.0.1 Server Dlr. CJsambarSOSambar Server ‘olymp.80" IP Address: 127.0.0.1 Server Dlr. CJsambarSOServer Threads: 4HTTP Connections: 1Network Connections: 3Server Threads: 4HTTP Connections: 1Network Connections: 3Build" Jul 2 2001 2203:48
Sambar Server VS 0
Sambar Server VS 0
Sambar Server ‘olymp.80" IP Address: 127.0.0.1 Server Dlr. CJsambarSO
Sambar Server ‘olymp.80" IP Address: 127.0.0.1 Server Dlr. CJsambarSO
Server Threads: 4
HTTP Connections: 1
Network Connections: 3
Server Threads: 4
HTTP Connections: 1
Network Connections: 3
Clear] Pause |
[olymp] [21:05:10] 127.0.0.1 200[olymp] [23:47:17] 127.0.0.1 200[olymp] [23:50:10] 127.0.0.1 200[olymp] [23:54:26] 127.0.0.1 200[olymp] [23:55:45] 127.0.0.1 200[olymp] [23:56:01] 127.0.0.1 200[olymp] [00:04:30] 127.0.0.1 401[olymp] [00:04:35] 127.0.0.1 200[olymp] [00:04:36] 127.0.0.1 200[olymp] [00:04:51] 127.0.0.1 200[olymp] [00:04:58] 127.0.0.1 200[olymp] [00:05:01] 127.0.0.1 200[olymp] [21:05:10] 127.0.0.1 200[olymp] [23:47:17] 127.0.0.1 200[olymp] [23:50:10] 127.0.0.1 200[olymp] [23:54:26] 127.0.0.1 200[olymp] [23:55:45] 127.0.0.1 200[olymp] [23:56:01] 127.0.0.1 200[olymp] [00:04:30] 127.0.0.1 401[olymp] [00:04:35] 127.0.0.1 200[olymp] [00:04:36] 127.0.0.1 200[olymp] [00:04:51] 127.0.0.1 200[olymp] [00:04:58] 127.0.0.1 200[olymp] [00:05:01] 127.0.0.1 200GET /cgi-bin/mysql7.php 0.GET /cgi-bin/mysql7.php 0GET /cgi-bin/mysql7.php0:GET /cgl-bin/mysql7.php 0GET /cgi-bin/mysql7.php0:GET /cgi-bin/mysql7.php0-GET /sesslorVadminlogln0.GET /session/adminlogin 0GET /sysadmin/index.stm 0GET /sysadmin/show/showcfg.strrGET /sysadmln/show/showlcon.stiGET /sysadmin/show/showmime sGET /cgi-bin/mysql7.php 0.GET /cgi-bin/mysql7.php 0GET /cgi-bin/mysql7.php0:GET /cgl-bin/mysql7.php 0GET /cgi-bin/mysql7.php0:GET /cgi-bin/mysql7.php0-GET /sesslorVadminlogln0.GET /session/adminlogin 0GET /sysadmin/index.stm 0GET /sysadmin/show/showcfg.strrGET /sysadmln/show/showlcon.stiGET /sysadmin/show/showmime s
[olymp] [21:05:10] 127.0.0.1 200
[olymp] [23:47:17] 127.0.0.1 200
[olymp] [23:50:10] 127.0.0.1 200
[olymp] [23:54:26] 127.0.0.1 200
[olymp] [23:55:45] 127.0.0.1 200
[olymp] [23:56:01] 127.0.0.1 200
[olymp] [00:04:30] 127.0.0.1 401
[olymp] [00:04:35] 127.0.0.1 200
[olymp] [00:04:36] 127.0.0.1 200
[olymp] [00:04:51] 127.0.0.1 200
[olymp] [00:04:58] 127.0.0.1 200
[olymp] [00:05:01] 127.0.0.1 200
[olymp] [21:05:10] 127.0.0.1 200
[olymp] [23:47:17] 127.0.0.1 200
[olymp] [23:50:10] 127.0.0.1 200
[olymp] [23:54:26] 127.0.0.1 200
[olymp] [23:55:45] 127.0.0.1 200
[olymp] [23:56:01] 127.0.0.1 200
[olymp] [00:04:30] 127.0.0.1 401
[olymp] [00:04:35] 127.0.0.1 200
[olymp] [00:04:36] 127.0.0.1 200
[olymp] [00:04:51] 127.0.0.1 200
[olymp] [00:04:58] 127.0.0.1 200
[olymp] [00:05:01] 127.0.0.1 200
GET /cgi-bin/mysql7.php 0.
GET /cgi-bin/mysql7.php 0
GET /cgi-bin/mysql7.php0:
GET /cgl-bin/mysql7.php 0
GET /cgi-bin/mysql7.php0:
GET /cgi-bin/mysql7.php0-
GET /sesslorVadminlogln0.
GET /session/adminlogin 0
GET /sysadmin/index.stm 0
GET /sysadmin/show/showcfg.strr
GET /sysadmln/show/showlcon.sti
GET /sysadmin/show/showmime s
GET /cgi-bin/mysql7.php 0.
GET /cgi-bin/mysql7.php 0
GET /cgi-bin/mysql7.php0:
GET /cgl-bin/mysql7.php 0
GET /cgi-bin/mysql7.php0:
GET /cgi-bin/mysql7.php0-
GET /sesslorVadminlogln0.
GET /session/adminlogin 0
GET /sysadmin/index.stm 0
GET /sysadmin/show/showcfg.strr
GET /sysadmln/show/showlcon.sti
GET /sysadmin/show/showmime s
Рис. 5.6. Информация по запросам к Web-серверу
Эта информация обновляется в реальном времени и может быть полезна для администратора сервера.
Страница администрирования Web-сервера позволяет просмотреть статистику обращений к серверу. Например, переходя по ссылке CGI Performance, можно посмотреть временную зависимость количества обращений к исполняемым скриптам сервера в графическом виде (рис. 5.7).
Сервер позволяет отображать различные типы статистических данных, например, в виде, показанном на рис. 5.8.
Страница Security позволяет установить желаемый уровень безопасности путем, например, ограничения доступа к определенным ресурсам, расположенным на сервере. Пример показан на рис. 5.9.
Сервер позволяет задать произвольные переменные окружения и установить их значения. Это можно сделать на странице System Variables. Мы создали новую переменную college_update и установили ее значение, равное "5 years" (рис. 5.10).
Сервер позволяет создавать виртуальные хосты (рис. 5.11).
||'Э Sambar Server Performance - Microsoft Internet Explorer
№□11
-L^? /Д^?' ^ .l®3®*'®**?' - с;^ - _ 6**» ■).
CGI Performance
12am
0.00%
0
lam
0.00%
о
2am
0.00%
0
3am
0.00%
0:
4 am
0.00%
0!
5am
0.00%
0
6am
0.00%
0
7 am
0.00%
■ O'
Saw 61.95%
70 «ив
9am 12.39%
14.
10am25.66%
-29ew.
Ham
0.00%
0
12noon
0.00%
0> '
Рис. 5.7. Статистика обращений к CGI-скриптам
ЙЙf.r^pli ' /Остенов..' Обновить Помой I Поиск' Избренн.f.r^pli ' /Остенов..' Обновить Помой I Поиск' Избренн.'Э HTTP Server Log Statistic:; - Microsoft Internet Explorer
Й
Й
f.r^pli ' /Остенов..' Обновить Помой I Поиск' Избренн.
f.r^pli ' /Остенов..' Обновить Помой I Поиск' Избренн.
Адрис^http://locdhosVsysadmin/reports/nttp/sra^ htm
Concise Report
Report Covers: 1/5/1998 to 1/15/1998 (10 days)
Number of Unique Hosts: 1
Number of Requests: 59
Total Unsuccessful Requests: 6
Number of Corrupt Log Lines: 0
Total Unique Requests (HTML pages & session): 23
Average Page Response Time: 1764ms
Average requests/hour: 0.244
Average requests/day: 5.900
Top 23 Documents By Hits
Hits % Reqs iResp Time {Document
813.56% 16441ms |/cgi-bin/search.pl
16il0.17%|122ms[/session/pagecount
610.17%;2783ms l/sampies/ssi.shtmi
!5! 8.47% I80ms I/fee dback.htm
Рис. 5.9. Ограничение доступа на странице Security
1 ж*» Ви*» В^-*«Й^М* Гт»«-&«../? г ■- ....,•Ш
'I ^з ^-„^ ©<£ ЗфЛ-а . jj ^"'<’6-' "
। i toP6C |€J Н1р/Лос#ют'Ау»4дтп/*а1».Ят*J r;.№flw**My|iil^
System Variables
Add/Modify a System
Defined System
Variables
Variable
Name
Datat
Variable ।
next sched down
none
Name:
college update
5 years
Variable ।
Data:
Sambar
_;A^NodiyVBM*l»_:J
wmheader
Server
Webmail
Creator
Tod SambarI"
site_name
Sambar Demo Site i
MagazineCo
Magazines Online
'<j Готово.'- - ? , г Цветной датрвсеть
I ' Ими Жг^л-- Остановить Рбносиг» . Домой ^ Пенс* Избранное Жирнел - Лонге Печать Правил ~ |4ч«1®' ■>ltp:/A)calio:-t/*ywdmr/vhottj/vhci!j htm°" J ^n.p*«Ju*>»I ' Ими Жг^л-- Остановить Рбносиг» . Домой ^ Пенс* Избранное Жирнел - Лонге Печать Правил ~ |4ч«1®' ■>ltp:/A)calio:-t/*ywdmr/vhottj/vhci!j htm°" J ^n.p*«Ju*>»Virtual hostsManagementCreate New Virtual HostVirtual hostsManagementCreate New Virtual HostЙ S auctionЙ S auctionCreate New Virtual HostCreate New Virtual HostVirtual Г Host NameVirtual Г Host NameAutomatic <Log mailtoAutomatic <Log mailtoCGI Specify the path to the CGI directory, Directory the /cgi-Ыи/ alias will be used to access this directory.CGI Specify the path to the CGI directory, Directory the /cgi-Ыи/ alias will be used to access this directory.WinCGI DirectoryWinCGI Directoryl/cgi-wby"l/cgi-wby"
I ' Ими Жг^л-- Остановить Рбносиг» . Домой ^ Пенс* Избранное Жирнел - Лонге Печать Правил ~ |4ч«1®' ■>ltp:/A)calio:-t/*ywdmr/vhottj/vhci!j htm°" J ^n.p*«Ju*>»
I ' Ими Жг^л-- Остановить Рбносиг» . Домой ^ Пенс* Избранное Жирнел - Лонге Печать Правил ~ |4ч«1®' ■>ltp:/A)calio:-t/*ywdmr/vhottj/vhci!j htm°" J ^n.p*«Ju*>»
Virtual hostsManagementCreate New Virtual Host
Virtual hostsManagementCreate New Virtual Host
Й S auction
Й S auction
Create New Virtual Host
Create New Virtual Host
Virtual Г Host Name
Virtual Г Host Name
Automatic <
Log mailto
Automatic <
Log mailto
CGI Specify the path to the CGI directory, Directory the /cgi-Ыи/ alias will be used to access this directory.
CGI Specify the path to the CGI directory, Directory the /cgi-Ыи/ alias will be used to access this directory.
WinCGI Directory
WinCGI Directory
l/cgi-wby"
l/cgi-wby"
Рис. 5.11. Создаем виртуальные хосты
Работаем с PHP
Язык PHP предоставляет большое количество возможностей для создания полнофункциональных серверных Web-приложений. Среди основных свойств можно назвать такие: обработка информации, введенной пользователем, посылка почты, работа с базами данных, работа с изображениями, работа с сетью, работа с объектами CORBA. Сейчас мы кратко рассмотрим основные возможности, без которых Web-программирование просто немыслимо, затем вернемся к более подробному изучению языка PHP.
Обработка HTML-форм
HTML-формы представляют собой механизм передачи серверу данных от пользователя клиентского браузера. Рассмотрим HTML-файл, содержащий форму (файл form.html), внешний вид страницы показан на рис. 5.12.
Файл form.html"
<html>
<head>
<title>
Пример формы. Передаем пользовательскую информацию серверу.
</title>
<head>
<body>
<form name="formname" method=post action="http://localhost/cgi- bin/form.php">
<Р>Введите текстовую информацию: <input type="text"
name="textl">
<P><input type="submit" value="Submit the form to the server">
</form>.
</body>
</html>
Рис. 5.12. Заполняем форму
Элемент формы начинается открывающим ярлыком <form>. В качестве свойств элемента в ярлыке указаны имя элемента formname, метод передачи данных post и свойство action. Последнее свойство — это адрес файла, содержащего программу, которая будет обрабатывать данные. Адрес этот может быть как относительный (относительно местоположения данного HTML-файла), так и абсолютный. Внутри элемента формы описано несколько компонентов. Важным для нас являются элементы input. Каждый элемент
input имеет имя и значение. Именно эти пары имен и значений будут переданы серверу в виде name=vaiue. Так, в нашем случае переменной с именем texti будет соответствовать строковое значение, которое пользователь введет в соответствующее поле. Различные типы элементов input, описанные в языке HTML, соответствуют различным графическим элементам, отображаемым в окне браузера. Кнопка отправки формы имеет тип "submit". Все пары name=vaiue, содержащиеся в форме, будут переданы программе, указанной в качестве значения свойства action. В файле form.php обратиться к этим значениям можно, просто указав имя соответствующей им переменной. Все переменные в PHP начинаются со знака $, поэтому наша переменная будет иметь вид $testi.
Напишем простой PHP-файл form.php для обработки данной формы. Мы уже видели, что текст PHP программы начинается с символов <? и заканчивается ?>.
; Файл form.php
Echo "<html><head><title>Forms</title></head><body>";
Echo "<hl>User 1приР</Ь1>Пользователь ввел такую строку:<Р>";
Echo $textl;
Echo "</body></html>”;
?>
j Файл Правка Виа Избранное Сервис Справка; ~
^ Н83^ _ ^Вп^-д ' _ ^стам08ИТ^„ Обновить _Домой f ' Поиск ■ Избранное ^
j ^рвс |551Й11|7л1ос<^^^Переход j] Links
User input
Пользователь ввел такую строку:
Вводим текст сюда
@ Готово:Г ["""{^Местнаяинтрасеть д
Рис. 5.13. Пользовательские данные были успешно обработаны
Файл сохраняем в каталоге cgi-bin/. После нажатия кнопки отправки формы, видим, что пользовательские данные возвращены сервером (рис. 5.13).
Приведенная в этом примере страница не имеет никакого дизайна. Коммерческие Web-приложения должны быть оформлены с учетом возможностей HTML-форматирования и удобства пользователей при работе.
Отправка писем с помощью PHP
Бывает необходимо осуществлять отправку писем с Web-сервера. Для этого в PHP существуют специальные функции. Если разработчик сам является администратором своего собственного сервера, то перед тем, как создавать приложение, которое посылает почту с использованием функции maii(), необходимо сконфигурировать PHP надлежащим образом. В файле php.ini требуется указать адрес (имя) SMTP-сервера. Таким сервером может быть сервер, установленный на том же самом компьютере, что и Web-север, или этим сервером может быть другой SMTP-сервер, через который открыт доступ для посылки писем. Фрагмент файла php.ini будет выглядеть примерно так:
| Фрагмент файла php.ini
[mail function]
; For [Ml]Win32 only. - Только для Windows[ o2 ]
SMTP= mail.yourname.com ; for Win32 only
; For [М3]Win32 only. . - Только для Windows[o4]
sendmail_from= yourname@yourhost.com ; for Win32 only
; For [M5]Unix only. You may supply arguments as well
; (default: 'sendmail -t -i').
; Только для UNIX. Можно также указать аргументы, по умолчанию: 'sendmail -t -i'
;sendmail_path=[M6] [o7]
В качестве примера создадим простой PHP-скрипт, который будет отправлять e-mail.
Файл mail.phpI
<?php.
$date = date("F j, Y");
$time = date("g:i a");
$ip=$REMOTE_ADDR;
$stringl="Date of visit: ".$date."\r\n Time of visit: ".$time."\r\n Visited from: ",$ip;
function whois($domain, $server="www.geektools.com") {
$fp = fsockopen ($server, 43, &$errnr, &$errstr) or die("$errno: $errstr");
fputs($fp, "$domain\n");
$string2="";
while (!feof($fp))
$string2.= fgets($fp, 2048);
fclose ($fp) ;
$m = mail("yourname@yourhost.com", "File mail.php has been visdited recently", $stringl.$string2, "From: name@host.com\r\n" ."Reply-To: name@address.com\r\n"."X-Mailer: PHP/", phpversion());
whois($ip);
?>
<html>
<head>
<title>Mail
</title>
<body>
<Ь1>0тправка почты сервером.</hl>
<Р>При этом пользователь ничего не подозревает...
</body>
</html>
Немного поясним приведенный пример. Отправка почтового сообщения осуществляется функцией mail о, аргументами которой являются адрес получателя (первый аргумент), второй аргумент — это строка — поле subject, тема сообщения, третьим аргументом идет тело письма (в нашем случае это конкатенация двух строк с именами $stringi и $string2, четвертым аргументом служит строка, содержащая дополнительные заголовки. В этой строке имеются управляющие последовательности символов \г и \п — переход на новую строку, а также функция определения версии языка PHP.
Стандартная функция PHP mail () помещена внутрь пользовательской функции whois ($ip), аргументом которой является строка, содержащая имя или IP-адрес хоста. Скрипт определяет время обращения к нему и IP-адрес, с которого
к нему обратились (встроенная переменная окружения $REMOTE_ADDR). Идентифицированный IP используется для получения информации о хосте, который связан с данным IP. Для этого происходит обращение к базе, расположенной на сервере по адресу www.geektools.com с портом 43. Для соединения используется протокол TCP. Соединение осуществляется при помощи стандартной функции языка PHP fsockopen(). Работу с сетью мы рассмотрим немного позже. Функции связи с сервером и отправки информации по указанному адресу организованы в самостоятельную пользовательскую фуНКЦИЮ whois().
Если пользователь зайдет на ваш сайт (предположим, что файл mail.php расположен на сайте http://yoursite.com/cgi-bin/mail.php), то PHP тут же запросит базу данных сервиса whois, который расположен на одном из удаленных серверов, положение которых указано в файле mail.php, и сгенерирует e-mail, отправив его по адресу, указанному в качестве первого аргумента функции mail о . По этому адресу вскоре придет сообщение, содержащее примерно такую информацию в теле письма:
Query:212.46.197.136
Registry: whois.ripe.net
Results:
% This is the RIPE Whois server.
% The objects are in RPSL format.
% Please visit http://www.ripe.net/rpsl for more information.
% Rights restricted by copyright.
% See http://www.ripe.net/ripencc/pub-services/db/copyright.html
inetnum:
212.46.192.0 - 212.46.206.255
netname:
CITYLINERU
descr:
Cityline offers dial-up and leased line access to Internet
country:
RU■
admin-c:
CTNC1-RIPE
tech-c:
CTNC1-RIPE
status:
ASSIGNED PA
remarks:
Please send abuse notification to abuse@cl.spb.ru
remarks:
please direct all queries to postmaster@cl.spb.ru
notify:
noc@Cityline.ru
mnt-by:
CITYLINERU-MNT
changed:
mih@cityline.ru 20010219
source:
RIPE
route:
212.46.197.0/24
descr:
Cityline offers dial-up and leased line access to Internet
descr:
for StPete citizens
origin:
AS8755
remarks:Please send abuse notification to abuse@cl.spb.ru
remarks:please direct all queries to support@cl.spb.ru
notify:noc@cityline.ru
mnt-by:CITYLINERU-MNT
changed:fil@cl.spb.ru 20001124
source:RIPE
role:cityline.ru NOC
address:Cityline Ltd.
address:1/2 str 6, Korobeinikov per.
address:119034 Moscow
address:Russia
phone:+7 095 3633312
fax-no:+7 095 2487848
e-mail:noc@cityline.ru
admin-c:MR14224-RIPE
tech-c:MR14224-RIPE
nic-hdl:CTNC1-RIPE
notify:dbm@cityline.ru
mnt-by:. CITYLINERU-MNT
changed:mih@cityline.ru20020219
source:RIPE
Results brought to you by the GeekTools WHOIS Proxy Server results may be copyrighted and are used with permission. Your host (195.10.228.211) has visited 1 times today.'
] Ж«Лл 'Ер»^ У.ИЙ ИМеанна»' Сервий; Справка.. ,, Г<_‘ '^ЩЛ
-] Назад ' Зтфся Остановить Обновить Домой ; Поиск. • Избранное - j&lpec [^JhttpT/iocalhosb^
Отправка почты сервером.
При этом пользователь ничего не подозревает...
§ Готово . . ,, ', . 1 . .. [. Г* -^ Местная интрасеть - д
Из этого сообщения мы можем узнать, что посетитель странички зашел к нам с IP-адреса 212.46.197.136, который принадлежит компании Cityline. Письмо содержит также другую полезную информацию.
Отметим, что вне зависимости от того, какие действия будут произведены на серверной стороне, клиентский браузер может получить любую HTML- информацию, пользователь даже не будет подозревать о том, что информация о нем была каким-то образом обработана и передана средствами электронной почты (рис. 5.14).
Работа с базами данных
Продолжим наш краткий экскурс в мир CGI-программирования с использованием языка PHP демонстрацией простого примера работы с базой данных. Установим на компьютер сервер и клиент базы данных. Выберем MySQL, программу можно найти по адресу http://www.mysql.com. Установим пакет в каталог MySQL и найдем необходимые для начала работы сведения в документации в каталоге mysql\docs. Запустить сервер MySQL можно из командной строки командой mysqld или mysqid-nt (в Windows NT). Проверим, работает ли сервер, выполнив команду mysqlshow. Если сервер работает, то в результате получим примерно такой ответ:
Databases
mysql test
Запускаем клиента MySQL (команда mysql), чтобы потренироваться в основных командах языка SQL. Появляется приглашение в форме стрелки:
Чтобы начать работу, нужно выбрать базу данных:
> use test;
В конце каждой инструкции MySQL ставится символ точка с запятой.
Понятно, что для работы с базами данных из PHP необходимо знать или иметь представление о том, как создавать запросы на языке SQL.
Приведем список основных функций языка PHP, предназначенных для работы с MySQL:
mysql_affected_rows — выдает количество строк, полученных предыдущим оператором;
mysql_close — закрывает соединение;
mysql_connect — открывает соединение с сервером MySQL;
mysql_create_db — создает базу данных MySQL;
mysqi_data_seek — перемещает внутренний указатель в полученном результате;
mysqi_db_query — посылает MySQL-запрос;
mysqi_drop_db — удаляет базу данных MySQL;
mysqi_fetch_array — подбирает результат запроса в виде ассоциативного или нумерованного массива или в виде и того, и другого;
mysqi_fetch_assoc — подбирает результат запроса в виде ассоциативного массива;
mysql_fetch_fieid — возвращает информацию о колонке и возвращает объект;
mysqi_fetch_iengths — возвращает длину каждого результата;
mysqi_fetch_object — возвращает строку результата в виде объекта;
mysqi_fetch_row — возвращает строку результата в виде нумерованного массива;
mysqi_fieid_name — возвращает имя поля;
mysqi_f ieid_ien — возвращает длину поля;
mysqi_fieid_seek — устанавливает указатель в результате на заданную позицию;
mysqi_fieid_tabie — возвращает имя таблицы, в которой находится результат;
mysqi_f ieid_type — возвращает тип поля;
mysqi_insert_id — возвращает идентификатор id, сгенерированный предыдущей операцией insert;
mysqi_iist_dbs — возвращает список баз данных, доступных на сервере MySQL;
mysqi_iist_tabies — получает список таблиц базы MySQL;
mysqi_num_f ieids — возвращает количество полей результата;
mysqi_num_rows — возвращает количество строк результата;
mysqi_pconnect — открывает постоянное соединение с сервером MySQL;
mysqi_query — посылает запрос серверу MySQL;
mysql_unbuffered_query — посылает SQL-запрос серверу MySQL без буферизации (и возможности дальнейшего подбора) строк результата;
mysqi_resuit — получает данные результата;
mysqi_seiect_db — выбирает базу данный MySQL;
mysqi_get_host_infо — информация о хосте базы MySQL;
mysqi_get_proto_infо — информация о протоколе MySQL;
mysqi_get_server_infо — информация о сервере MySQL.
Это неполный перечень PHP-функций, предназначенных для работы с базами данных MySQL. PHP имеет готовые к применению функции, разработанные для различных баз данных, включая Informix, Oracle, MS SQL и др. При работе с конкретной базой данных необходимо учитывать ее особенности. Важно правильно сконфигурировать PHP. Мы не будем подробно останавливаться на деталях работы с каждым типом баз данных. Сейчас мы перейдем к рассмотрению основных примеров работы с базой данных MySQL на языке PHP.
Еще раз убедимся в том, что MySQL-север работает. Для это выполним команду (в каталоге mysql\bin) mysqi. В консольном окне должно появиться приглашение mysqi>. Если приглашение не появилось, то в среде Windows сервер удобно запустить директивой winmysqiadmin, расположенной в том же каталоге mysql\bin. На дисплее появится основное окно панели администратора (рис. 5.15), которое тут же исчезнет, если сервер удачно стартует. Если в системе нет файла my.ini, то появится приглашение зарегистрировать пользователя (рис. 5.16).
L^WinMySOLadmin 11ГЛИ?
-, —Ч1WinMySOLadminVarl 1 fur Wm9b/Win98/Nr/Win?0U0
Copynght (С) 1979 2001 MySQL АВ Monty Program КВ .Outrun НВhi4MC1n
* All rights rosonwd Shu tho file PUBLIC tor hcvncu infurmutiun
This software сотое with ABSOLUTELY NO WARRANTY мое the Mo PUBLIC lor details
Рис. 5.16. Создаем пользователя сервера MySQL
Убедимся, что сервер работает. Если запущена программа Windows- администратор, то на панели состояния системы появится изображение светофора. При работающем MySQL-сервере цвет светофора будет зеленый (рис. 5.17).
№5 Р:36
Рис. 5.17. Светофор показывает, что сервер работает
Попытаемся обратиться к серверу из консоли, для этого вызовем клиента командой mysqi, сервер работает (рис. 5.18).
Создадим простой PHP-файл и обратимся к MySQL-серверу через CGI- приложение из клиентского браузера.
Файл mysqil.php разместим в каталоге \cgi-bin Web-сервера.
Файл mysqll.php
<?php
$c=mysql_connect("localhost:3306", "username", "password"); mysql_select_db("test",$c);
$stroka="show tables";
$result = mysql_query($stroka);
if($result) echo $result;
l^ http://localhost/cgi-bin/mysql3 php - Microsoft Internet fexplorerU -^«fw IQpwes .Же -_.Ц#₽й«®-'. ^Й^.'^РЙ*1^l^ http://localhost/cgi-bin/mysql3 php - Microsoft Internet fexplorerU -^«fw IQpwes .Же -_.Ц#₽й«®-'. ^Й^.'^РЙ*1^Назад •_ бЬер^йТ-’". Останов." Обновить -. Домой? J-"» 6ДРВ,?|® http://localhost/cgi-bin/mysq!3.phpНазад •_ бЬер^йТ-’". Останов." Обновить -. Домой? J-"» 6ДРВ,?|® http://localhost/cgi-bin/mysq!3.php
l^ http://localhost/cgi-bin/mysql3 php - Microsoft Internet f
explorer
U -^«fw IQpwes .Же -_.Ц#₽й«®-'. ^Й^.'^РЙ*1^
l^ http://localhost/cgi-bin/mysql3 php - Microsoft Internet f
explorer
U -^«fw IQpwes .Же -_.Ц#₽й«®-'. ^Й^.'^РЙ*1^
Назад •_ бЬер^йТ-’". Останов." Обновить -. Домой? J-"» 6ДРВ,?|® http://localhost/cgi-bin/mysq!3.php
Назад •_ бЬер^йТ-’". Останов." Обновить -. Домой? J-"» 6ДРВ,?|® http://localhost/cgi-bin/mysq!3.php
Query: SELECT * FROM newtable WHERE namel = 'arkady';
Resource id #2Rows number: 1
namel: arkady name2: ivanovich
name3: serov bnirthdate: 1934-03-30
Рис. 5.18. Консольный клиент благополучно общается с сервером
Эта программа осуществляет соединение с сервером MySQL (первый оператор), выбирает базу данных (стандартную базу с именем test), выполняет запрос. Если запрос выполняется, то функция mysqi_query возвращает значение, равное идентификатору ресурса и отличное от значения false. Если $ result имеет значение true (т. е. запрос выполнен), то программа передает браузеру через сервер идентификатор ресурса, связанный с запросом $stroka. Наша программа успешно работает (рис. 5.19).
З http://localhost/cgi-bin/mysql1.php - Microsoft Internet Е... НИВ
И-фВМ , фяха.. §ид Избранное .Cgpprc щпраегд. -. Щ। j topee [§Jihttp^7io«iihost7igHiir^^^Переход ,] Links ”]
Resource id #2
Рис. 5.19. MySQL-запрос обработан серверомРис. 5.19. MySQL-запрос обработан сервером
Рис. 5.19. MySQL-запрос обработан сервером
Рис. 5.19. MySQL-запрос обработан сервером
Создадим новую базу данных из консоли MySQL. Назовем ее newdb: mysql> CREATE DATABASE newdb;
Переходим к использованию этой базы данных:
mysql> use newdb;
Создадим таблицу newtable (рис. 5.20):
mysql> CREATE TABLE newtable (namel VARCHAR(20), name2 VARCHAR(20) , name3 VARCHAR(20), sex CHAR(l), birth DATE);
Посмотрим, какие имеются сейчас таблицы в нашей базе данных:
mysql> show tables;
Рис. 5.20. Создали новую таблицу в новой базе данных
Запишем вручную данные в таблицу (два ряда):
mysql> INSERT INTO newtable VALUES ('arkady', 'Ivanovich', 'serov','m' ,4934-03-30');
и
mysql> INSERT INTO newtable VALUES ('max','i','klein','m','1964-08-23');
Сейчас посмотрим, что содержит наша таблица:
mysql> select * from newtable;'
Результат показан на рис. 5.21.
Рис. 5.21. Заполнили таблицу
Сейчас мы научимся читать данные из базы данных средствами PHP. Для этого создадим файл mysql2.php.
Файл mysql2.php
<?php
$c=mysql_connect("localhost:3306", "olymp", "vad"); echo mysql_select_db("newdb",$c);
$stroka = "select * from newtable;";
$result = mysql_query($stroka);
$noro=mysql_num_rows($result);
echo "Rows number: ".$noro."<P>";
while ($row = mysql_fetch_array ($result)) {
echo "namel: ".$row["namel"]."<br>\n";
echo "name2: ".$row["name2"]."<br>\n";
echo "name3: ",$row["name3"]."<br>\n";
echo "bnirthdate: ".$row["birth"]."<br>\n"; echo "<hr>";
Здесь первая строка предназначена для соединения с базой данных, которая установлена на локальном компьютере со стандартным портом для MySQL 3306, указан пользователь и пароль, для проверки выводится идентификатор ресурса. В переменной $stroka формируется SQL-запрос, который передается функции mysqi_query. Для контроля далее определяется, сколько строк содержится в результате. Затем цикл выводит полученный результат в окно браузера (рис. 5.22).
Для успешной работы с базами данных необходимо знать язык запросов к базам данных. Ниже мы приводим краткие сведения по использованию баз данных на примере MySQL.
Работаем с MySQL
Выбор отдельного ряда
Мы имеем возможность выбрать ряды на основе указанных условий. Для этого требуется написать запрос, указав эти условия, например:
mysql> SELECT * FROM newtable WHERE namel = "arkady";
PHP-запрос будет выглядеть таким образом, как показано в файле mysql3.php.
I Файл mysqlS.php .>. •. ... - j
<?php
$c=mysql_connect("localhost:3306", "olymp", "vad"); mysql_select_db("newdb",$c);
$stroka = "SELECT * FROM newtable WHERE namel = 'arkady';";
echo "Query: ".$stroka."<P>";
echo $result = mysql_query($stroka) ;.
$noro=mysql_num_rows($result);
echo "Rows number: ",$noro."<P>";
while ($row = mysql_fetch_array ($result)) (
echo "namel: ".$row["namel"]."<br>\n";
echo "name2: ".$row["name2"]."<br>\n";
echo "name3: ",$row["name3"],"<br>\n";
echo "bnirthdate: ",$row["birth"]."<br>\n";
echo "<hr>";
}
?>
В дальнейшем мы будем изменять только значение переменной $stroka. Будьте внимательны к пробелам. Лишние пробелы в конце строки запроса могут привести к ошибке запроса. Если запрос составлен верно, получаем ответ, изображенный на рис. 5.22. Если мы вставим лишний пробел в строке перед закрывающей кавычкой, MySQL-сервер будет работать неправильно и определить такую ошибку нелегко (рис. 5.23).
IRows number: 2
namel: arkady name2: ivanovich
патеЗ: serov,
bnirthdate: 1934-03-30
namel: max
name2: t
патеЗ: klein
bnirthdate: 1964-08-23
Рис. 5.22. Ответ сервера в случае верно составленного запроса
■к • XX--QX* а‘ й "зХ1 Хз*; т " tj Назад , =J4^ Останов, Обновить Помой Поиск Избрани Журнал ' Почта. Печать Правка X ;|барес|ёhttp://1ocalho$Vcgr-bin/mysql3 php~jJ ^rJ
Query: SELECT * FROM newtable WHERE namel = 'arkady';
Warning: Supplied argument is not a valid MySQL result resource in C:/sambar50/cgi-bin/mysql3.php on line 7 Rows number:
Warning: Supplied argument is not a valid MySQL result resource in C:/sambar50/cgi-bin/mysql3.php on line 9
Ошибки при обращении к серверу могут происходить многократно. Удаление одной ошибки не гарантирует работоспособность программы в целом (рис. 5.24).
Эмр/Л-Эмр/Л-■ ■■г-^4 -.,■ ^епелбтпй-пг^. ,даЙЬJ4==™l®: - ^ocalhosVcgi-bin/mysql3 pho■ ■■г-^4 -.,■ ^епелбтпй-пг^. ,даЙЬJ4==™l®: - ^ocalhosVcgi-bin/mysql3 phoSy й^оSy й^о
Эмр/Л-
Эмр/Л-
■ ■■г-^4 -.,■ ^епелбтпй-пг^. ,даЙЬ
J4==™l®: - ^ocalhosVcgi-bin/mysql3 pho
■ ■■г-^4 -.,■ ^епелбтпй-пг^. ,даЙЬ
J4==™l®: - ^ocalhosVcgi-bin/mysql3 pho
Sy й^о
Sy й^о
Query: SELECT * FROM newtable WHERE namel = 'arkady';
Warning: Supplied argument is not a valid MySQL result resource in C:/sambar50/cgi-bln/mysql3.php on line 7 Rows number:
Рис. 5.24. Ответ сервера при возникновении ошибки
•^http.Z^ocalhosl/r.qrbin/mysqM php •• Microsoil
'ЗЦ Ьир://кч:ЫЬтч^иИип^Mhjot'ЗЦ Ьир://кч:ЫЬтч^иИип^Mhjot№с@ littp://localhosVcgi-bin/mysql4.php .....—.—...........№с@ littp://localhosVcgi-bin/mysql4.php .....—.—...........
'ЗЦ Ьир://кч:ЫЬтч^иИип^Mhjot
'ЗЦ Ьир://кч:ЫЬтч^иИип^Mhjot
№с@ littp://localhosVcgi-bin/mysql4.php .....—.—...........
№с@ littp://localhosVcgi-bin/mysql4.php .....—.—...........
'^г^м-вЬид фбг**» >УП[ Мазеп г -» г Останов Обнов!1^р2с№з http^^I'^г^м-вЬид фбг**» >УП[ Мазеп г -» г Останов Обнов!1^р2с№з http^^IQuery: SELECT * FROM newtable;Query: SELECT * FROM newtable;Resource id #2Rows number: 4Resource id #2Rows number: 4Query: SELECT * FROM newtable;Query: SELECT * FROM newtable;Resource id #2Rows number: 3Resource id #2Rows number: 3namel: arkady name2: ivanovichпатеЗ: serov bnirthdate: 1934-03-30namel: arkady name2: ivanovichпатеЗ: serov bnirthdate: 1934-03-30
'^г^м-вЬид фбг**» >УП
[ Мазеп г -» г Останов Обнов!
1^р2с№з http^^I
'^г^м-вЬид фбг**» >УП
[ Мазеп г -» г Останов Обнов!
1^р2с№з http^^I
Query: SELECT * FROM newtable;
Query: SELECT * FROM newtable;
Resource id #2Rows number: 4
Resource id #2Rows number: 4
Query: SELECT * FROM newtable;
Query: SELECT * FROM newtable;
Resource id #2Rows number: 3
Resource id #2Rows number: 3
namel: arkady name2: ivanovich
патеЗ: serov bnirthdate: 1934-03-30
namel: arkady name2: ivanovich
патеЗ: serov bnirthdate: 1934-03-30
namel: arkady name2: ivanovichпатеЗ: serov bnirthdate: 1934-03-30namel: max name2: t патеЗ: klein bnirthdate: 1964-08-23namel: nikolay name2: Stepanovich патеЗ: ilyin bnirthdate: 1978-08-23namel: arkady name2: ivanovichпатеЗ: serov bnirthdate: 1934-03-30namel: max name2: t патеЗ: klein bnirthdate: 1964-08-23namel: nikolay name2: Stepanovich патеЗ: ilyin bnirthdate: 1978-08-23namel: maxname2: tпатеЗ: kleinbnirthdate: 1964-08-23namel: maxname2: tпатеЗ: kleinbnirthdate: 1964-08-23namel: nikolay name2: Stepanovich патеЗ: ilyin bnirthdate: 1978-08-23namel: nikolay name2: Stepanovich патеЗ: ilyin bnirthdate: 1978-08-23namel: nikolay name2: Stepanovich патеЗ: karaev bnirthdate: 1979-03-13namel: nikolay name2: Stepanovich патеЗ: karaev bnirthdate: 1979-03-13
namel: arkady name2: ivanovich
патеЗ: serov bnirthdate: 1934-03-30
namel: max name2: t патеЗ: klein bnirthdate: 1964-08-23
namel: nikolay name2: Stepanovich патеЗ: ilyin bnirthdate: 1978-08-23
namel: arkady name2: ivanovich
патеЗ: serov bnirthdate: 1934-03-30
namel: max name2: t патеЗ: klein bnirthdate: 1964-08-23
namel: nikolay name2: Stepanovich патеЗ: ilyin bnirthdate: 1978-08-23
namel: max
name2: t
патеЗ: klein
bnirthdate: 1964-08-23
namel: max
name2: t
патеЗ: klein
bnirthdate: 1964-08-23
namel: nikolay name2: Stepanovich патеЗ: ilyin bnirthdate: 1978-08-23
namel: nikolay name2: Stepanovich патеЗ: ilyin bnirthdate: 1978-08-23
namel: nikolay name2: Stepanovich патеЗ: karaev bnirthdate: 1979-03-13
namel: nikolay name2: Stepanovich патеЗ: karaev bnirthdate: 1979-03-13
Рис. 5.25. Таблица в базе данныхсодержит три записиРис. 5.25. Таблица в базе данныхсодержит три записиРис. 5.26. В таблице четыре записиРис. 5.26. В таблице четыре записи
Рис. 5.25. Таблица в базе данныхсодержит три записи
Рис. 5.25. Таблица в базе данныхсодержит три записи
Рис. 5.26. В таблице четыре записи
Рис. 5.26. В таблице четыре записи
:ДЬ11р://кзсЫ^- Mien
;Ж^?.^^.е " .$?? \Иэ^»мнс^5 Сер»
Назад -Останов Обно
£дрес|ё] http://1 о calhost/cgi-bin/mysqMphp
Resource id #2Rows number: 5
namel: arkady ' name2: ivanovich патеЗ: serov bnirthdate: 1934-03-30
name 1: max name2: t патеЗ: klein bnirthdate: 1964-08-23
namel: nikolay
name2: Stepanovich
■патеЗ: ilyin
bnirthdate: 1978-08-23
namel: nikolay
name2: Stepanovich патеЗ: karaev
-bnirthdate: 1979-03-13
'namel: nikolay
name2: grigorievich
I патеЗ: bait
Рис. 5.27. В таблице уже пять записей
Расширим нашу таблицу, для этого используем следующие данные: $string="insert into newtable values ('nikolay' ,'Stepanovich','ilyin','m',4978-08-23')" ;
$res = mysql_db_query("newdb", Sstring);
Несколько раз варьируем данные и вводим их по очереди (рис. 5.25—5.27): $string="insert into newtable values ('nikolay' ,'Stepanovich','karaev','m','1979-03-13') ";
$res = mysql_db_query("newdb", Sstring);
$string="insert into newtable values ('nikolay' ,'grigorievich','hajt','m','1963-02-03') ";
$res = mysql_db_query("newdb", $string);
Сейчас мы можем усложнить условие запроса:
$stroka = "SELECT * FROM newtable where birth < '1960-01-01';";
Получим список лиц, родившихся до 1 января 1960 года (рис. 5.28).
Еще условие:
$stroka = "SELECT * FROM newtable where namel='nikolay' and birth > 4970-01-01’;";
Результат показан на рис. 5.29.
1 '3 http://localhost/cgi-bin/mysql4n.php - Microsoft Internet Explorer
ив в
J Файл Правка Вид ИзбранноеЗйрвис ..\£правка ‘.
lllllllll^^
гт™'™
1 ’НазадSn-p^ - Остановить_ Обновить Домой
a Lid ^
Поиск „HsdpwHpo Журнал *
] Дйрес |^J http //localhost/cgi bin/my$ql4n php
J ^Переход
j Links”,
Query: SELECT * FROM newtable where birth < T 960-01-0Г;
Resource id #2Rows number: 1
namel: arkady name2: ivanovich
патеЗ: serov bnirthdate: 1934-03-30
-I
^Готово,_' /- >> 4 ‘-X'
- 1 Л- 1 Д Местная интрасеть
Рис. 5.28. Дополнительные условия запроса
:-З http://localhosVcgi-bin/mysql4 php - Microsoft Internet Explorer
Назад --rjcprr,. ^'Останов >01
Ддрас|« httpV/locadhosVcgi-bin/mysqM php
Query: SELECT * FROM newtable where namel='nikolay' and birth > '1970-01-01';
Resource id #2Rows number: 2
namel: nikolay name2: Stepanovich
патеЗ: ilyin bnirthdate: 1978-08-23
namel: nikolay
name2: Stepanovich патеЗ: karaev
bnirthdate: 1979-03-13
Логические операторы он и and можно комбинировать, например:
$stroka = "SELECT * FROM newtable where namel='nikolay' or name2='t' and birth > 4960-01-01';";
Результат показан на рис. 5.30.
*6ac9c|g] nbp://locaihosVcgi-bin/mysqH.php
Query: SELECT * FROM newtable where namel-nikolay’ or name2-1’ and birth > ’1960-01-01';
Resource id #2Rows number: 4
namel: max
name2: t
патеЗ: klein
bnirthdate: 1964-08-23
namel: nikolay
name2: Stepanovich
патеЗ: ilyin
bnirthdate: 1978-08-23
namel: nikolay
name2: Stepanovich патеЗ: karaev
bnirthdate: 1979-03-13
namel: nikolay
name2: grigorievich
патеЗ: hajt
bnirthdate: 1963-02-03
Рис. 5.30. Комбинация логических операторов
Выбор столбца
Для того чтобы выбрать столбец, можно составить запрос, как показано в файле mysq!5.php.
i Файл mysqlS.phpi
<?php
$c=mysql_connect("localhost:3306", "olymp", "vad"); mysql_select_db("newdb",$c);
$stroka = "SELECT namel, birth FROM newtable;";
echo "Query: ",$stroka."<Р>";
echo $result = mysql_query($stroka);
$noro=mysql_num_rows($result);
echo "Rows number: ".$noro."<P>";
while ($row = mysql_fetch_array ($result)) {
for ($1=0; $1 < 2; $1++)
{
echo $row[$l]."";
)
echo "<br>\n";
)
?>
Результат работы отображен на рис. 5.31.
3b hMp;//tot:nlhosi/r;gi btn/mysqlb.php Microsoft
Query: SELECT namel, birth FROM newtable;
Resource id #2Rows number: 5
arkady 1934-03-30 max 1964-08-23 nikolay 1978-08-23 nikolay 1979-03-13 nikolay 1963-02-03
Рис. 5.31. Выбор отдельных столбцов
Чтобы выбрать столбцы только с уникальными значениями, делаем такой запрос: $stroka = "SELECT DISTINCT namel FROM newtable;";
При этом не забудем изменить значение параметра $1=1.
Результат видим на рис. 5.32.
Рис. 5.32. Только уникальные значения (нет повторов)
Сортировка строк результата
MySQL располагает встроенными возможностями сортировки результата, полученного по SQL-запросу.
$stroka = "SELECT namel, birth FROM newtable ORDER BY birth;";
Результат показан на рис. 5.33.
|фдр@С [gj http://locaihosVcgi-birVmysql5.php
Query: SELECT namel, birth FROM newtable ORDER BY birth;
Resource id #2Rows number: 5
arkady 1934-03-30
nikolay 1963-02-03 max 1964-08-23
nikolay 1978-08-23
nikolay 1979-03-13
Рис. 5.33. Сортировка строк результата
Сортировка может быть организована по нескольким полям:
$stroka = "SELECT * FROM newtable ORDER BY патеЗ, birth;";
Результат приведен на рис. 5.34.
I j Адрес p|jTttp%toca^^
■ Query: SELECT * FROm newtable order by патеЗ, birth;
Resource id #2Rows number: 5
nikolay grigorievich hajt m 1963-02-03
nikolay Stepanovich ilyin m 1978-08-23
nikolay Stepanovich karaev m 1979-03-13
max t klein m 1964-08-23
arkady ivanovich serov m 1934-03-30
Рис. 5.34. Сортировка по двум полям
MySQL позволяет производить математические вычисления с данными.
Можно, например, вычислить возраст, выразив его в количестве дней:
$stroka = "SELECT патеЗ, (TO_DAYS(NOW())-TO_DAYS(birth)) FROM newtable;";
Смотрите результат на рис. 5.35.
■j:]AflP@fi)® http://localhosVcgi-bin/mysql5.php
Query: SELECT патеЗ, (TO_DAYS(NOW())-TO_DAYS(birth)) FROM newtable;
Resource id #2Rows number: 5
serov 24935
klein 13831
ilyin 8718
karaev 8516
hajt 14398
Рис. 5.35. Математические вычисления, производимые средствами MySQL
Несколько более усовершенствованный вариант этого запроса может выглядеть так:
$stroka = "SELECT патеЗ, (TO_DAYS (NOW ())-TO_DAYS (birth) )/365 as age FROM newtable ORDER BY age;";
Что получается в результате, мы видим на рис. 5.36.
11МР£6|<У http://locaihosVcgi-bm/mysql5.php
Query: SELECTпатеЗ, (TO_DAYS(NOW())-TO_DAYS(birth))/365
Resource id #2Rows number: 5
karaev 23.33
ilyin 23.88
klein 37.89
hajt 39.45
serov 68.32
as age FROM newtable order by age;
Рис. 5.36. Усовершенствованные условия вычислений и сортировки
Сейчас мы покажем, как можно работать с текстовыми моделями. Запрос для выбора строк, начинающихся с буквы к (знак % соответствует произвольному количеству любых символов, знак _ соответствует одному произвольному символу).
$stroka = "SELECT * FROM newtable WHERE патеЗ LIKE 'k%';";
Все фамилии, начинающиеся на k, будут выбраны (результат показан на рис. 5.37).
$stroka = "SELECT * FROM newtable WHERE патеЗ LIKE '%in';”;
Выбираются все фамилии, заканчивающиеся на in (результат мы видим на рис. 5.38).
$stroka = "SELECT * FROM newtable WHERE патеЗ LIKE '%a%';";
Выбираются фамилии, содержащие в себе букву а (результат приведен на рис. 5.39).
:"Э Wp //toojihusi/cqf-bm/^ysqK' php - Mirju&ott internet Fxplc>i«г
Файл Правке йид "Избранно» Сервис Нлраа»а
' -ПоискИзбрани'.' -ПоискИзбрани'.. . Назад - .<йгрзьц -: Останов.:. Обновить Домой
' -ПоискИзбрани'.
' -ПоискИзбрани'.
11 Адрес |^J http;//localhost/cgi-bin/mysql5.php
Query: SELECT * FROM newtable WHERE патеЗ LIKE ’k%';
Resource id #2Rows number: 2
max t klein m 1964-08-23
nikolay Stepanovich karaev m 1979-03-13
'SI http://localhost/cgi-bin/mysql5.php - Microsoft Internet Explorer
НпфМ, > Останов.. Обновить • ДомойНпфМ, > Останов.. Обновить • ДомойАдрес у http://localhost/cgi-bin/mysql5.phpАдрес у http://localhost/cgi-bin/mysql5.php
НпфМ, > Останов.. Обновить • Домой
НпфМ, > Останов.. Обновить • Домой
Адрес у http://localhost/cgi-bin/mysql5.php
Адрес у http://localhost/cgi-bin/mysql5.php
Query: SELECT * FROM newtable WHERE патеЗ LIKE '%in';
Resource id #2Rows number: 2
max t klein m 1964-08-23
nikolay Stepanovich ilyin m 1978-08-23
Рис. 5.38. Выбор фамилии, заканчивающейся на in
•^ http://localhost/cgi-bin/mysql5 php - Microsoft Internet Explorer
ij Дайл Правка Вид- Избранное ;Сарвир ^правка, r,.-y^~ с j/ »<4"*-<<f
V "* . Ф 134 ■ ‘
Назад"—- г Останов Обновить Домой Поиск- " Избранн
— - ..s^.^. ..,—.——=]._^™-^ ^^,-^-щ
Адрес ру http://localhosVcgi-bin/mysql5.php■
Query: SELECT * FROM newtable WHERE патеЗ LIKE '%a%';
Resource id #2Rows number: 2
nikolay Stepanovich karaev m 1979-03-13
nikolay grigorievich hajt m 1963-02-03
Рис. 5.39. Выбор фамилии, содержащей букву а
Запрос
SELECT * FROM newtable WHERE патеЗ LIKE "'
выводит все фамилии, состоящие из 5 символов (рис. 5.40).
Смысл некоторых стандартных моделей такой:
'. ' — один любой символ;
'[...)'— любой символ из тех, что перечислен в квадратных скобках. Например, ' [ abc ] ' — соответствует либо' а', либо ' ь', либо ' с'. Можно указать диапазон символов, например, ' [a-z]' — это соответствует любой строчной букве, а ' [0-9] ' — любой цифре;
1 *' — соответствует нескольким (в том числе и 0) символам, стоящих перед знаком звездочки. Например, 'х*’ — соответствует произвольному количеству букв х, ' [0-9] *• — произвольному количеству цифр, ' .*' — произвольному количеству любых символов;
следует иметь в виду, что модели регулярных выражений являются чувствительными к регистру. Это можно учесть, указав, например, * [аА] *, что соответствует как прописной, так и строчной букве а, а конструкция ' [a-zA-z]' соответствует всем строчным и прописным буквам;
шаблон соответствует модели, если он встречается в любом месте. Чтобы ограничить себя поиском только тех шаблонов, что располагаются в начале, используется символ '"', для тех шаблонов, что располагаются в конце, следует использовать символ ' $'.
3 http://localhosVcqrbin/mysqlb php - Microsoft Internet Explorer
Ддрес|в) http://localhosVcgi-birVmysql5.php
Query: SELECT * FROM newtable WHERE name3 LIKE ’
Resource id #2Rows number: 3
arkady ivanovich serov m 1934-03-30 max t klein m 1964-08-23
nikolay Stepanovich ilyin m 1978-08-23
Рис. 5.40. Выбор фамилий по длине
Э http://fo#nlhosV(::<ji-ti^^• Micro :>ah Internet Explorer
J\< i LtWrd ди- u- о»ноа .Сервис , a -v . ,_
Назад >' Останов Обновить Помой I Поиск Избрани Жур
М# ittp://tocalhosVcgi-bm/mysql5 phpI
Query: SELECT * FROM newtable WHERE name3 REGEXP ,Лк’;;
Resource id #2Rows number: 2
max t klein m 1964-08-23
nikolay Stepanovich karaevm 1979-03-13
В запросах при использовании моделей регулярных выражений нужно вставлять слово regexp.
$stroka = "SELECT * FROM newtable WHERE name3 REGEXP 'Лк';";
На рис. 5.41 показан пример работы с регулярными выражениями.
Использование нескольких таблиц одновременно
Предположим, что нам необходимо собирать информацию, касающуюся тех персонажей, что описаны в таблице newtable, и хранить эту информацию в новой таблице. Это может быть, например, информация, касающаяся определенных событий в жизни данных лиц. Новая таблица может содержать имя человека, к которому относится событие, дату события, описание события, тип события.
Создадим новую таблицу event:
mysql> CREATE TABLE event (патеЗ VARCHAR(20), date DATE,
type VARCHAR(15), remark VARCHAR(255));
Заполним таблицу такими событиями (табл. 5.1).
Таблица 5.1. Заполняем базу данных
патеЗ
date
type
remark
klein
2002-07-15
First
Arrived
klein
2002-07-16
Second
Departed alone
klein
2002-07-17
. First
Arrived with cargo
karaev
2002-07-16
Third
Awaiting
hajt
2002-07-17
Second
Departed with cargo
serov
2002-07-10
Other
ilyin
2002-07-16
Other
ilyin
2002-07-17
Fourth
Admitted
Запомним эту информацию в текстовом файле event.txt в виде:
Файл event.bet
klein
2002-07-15FirstArrived
klein
2002-07-16SecondDeparted alone
klein
2002-07-17FirstArrived with cargo
karaev
2002-07-16ThirdAwaiting
hajt
2002-07-17SecondDeparted with cargo
serov2002-07-10Other
ilyin2002-07-16Other
Ilyin2002-07-17FourthAdmitted
Вставим данные в базу данных их консольного клиента: mysql> LOAD DATA LOCAL INFILE "event.txt" INTO TABLE event; Сейчас мы несколько усовершенствуем интерфейс, сделаем вывод немного более красивым (см. файл mysql6.php ниже).
i Файл mysqlS.php:
<?php■
$c=mysql_connect("localhost:3306", "olymp", "vad"); mysql_select_db("newdb",$c); $stroka = "SELECT * FROM event"; echo "Query: ".$stroka."<P>"; echo $result = mysql_query($stroka); $noro=mysql_num_rows($result); echo "Rows number: ".$noro."<P>";
echo '<table border=l>';
while ($row = mysql_fetch_array ($result)) {• .
echo '<tr>'; for ($1=0; $1 < 4; $1++)■
{ echo '<td>'; echo $row[$l]." </tdxtd>”; } echo "</trxtr>"; } echo '</table>'; ?>.
Результат ввода данных в новую таблицу виден на рис. 5.42.
] АдрееруТёр^
Query: SELECT * FROM event
Resource id #2Rows number: 8
klein I 2002-07-15
First :
Arrived
klein |2002-07-1б
Second
Departed alone :
klein : 2002-07-17
First
Arrived with cargo
karaev 2002-07-16
Third :
Awaiting:
|.hajt \ 12002-07-17
Second
Departed with cargo
|serov : 12002-07-10
other
lilyin : 12020-02-07
other i
ilyin i 2020-02-07
Fourth ■
admitted>
Рис. 5.42. Вывод таблицы из базы данных
[^дрес |е] http://localhosVcgi-birVmysql6.php
Query: SELECT newtable.name3, namel, data, rematk FROM newtable, event;
Resource id #2Rows number: 40
[serov jklein ilyin
larkady: [2002-07-15 lArrived
max
nikolay
2002-07-15: Arrived
2002-07-15
Arrived
karaev
nikolay
2002-07-15
Arrived
hajt
[serov ■
nikolay arkady
2002-07-15
2002-07-16
Arrived
Departed alone
jklein [ilyin [karaev
max nikolay nikolay
[2002-07-16
2002-07-16
2002-07-16
pep arted alone Departed alone Departed alone
jhajt
nikolay
2002-07-16
Departed alone
[serov
rarkady
2002-07-17
Arrived with cargo
jklein
max;
2002-07-17
Arrived with cargo
Поиск по нескольким таблицам можно организовать с использованием таких запросов:
$stroka = "SELECT newtable.патеЗ, namel, data, rematk FROM newt able, event;";
Результат показан на рис. 5.43.
Получаем информацию о базах данных и таблицах
Для того чтобы в случае необходимости (вы забыли имена баз данных) узнать, какие базы данных существуют на сервере MySQL, можно воспользоваться таким запросом: $stroka = "show databases;";
Еще раз напомним, что необходимо исправить в файле, где расположен запрос, параметр $1, равный числу столбцов, выдаваемых сервером по запросу, установив новое значение. Результат показан на рис. 5.44.
аЫ1|Г//МсЛпйГ/<шФ^php -MiCaositfl!^
J Зд8**^ -Дранка Вил -febpewtHr^- Саг^иг 'Дп;
J ^',-4,-^^) .
J Назад . спг<с,л Останов.. Обновить
J Ддрес|у http //Iocalhost/cgi-bin/mysql7 php
Query: show databases;
Resource id #2Rows number: 4
mysql ■ newdb newdbli
test
Рис. 5.44. Базы данных на сервере MySQL
Можно воспользоваться функцией database о, с помощью которой можно получить название текущей базы данных:
$stroka = "SELECT DATABASE();";
На рис. 5.45 показан результат, выведенный в окно браузера.
Если на момент выполнения функции database () база данных еще не выбрана, то результат функции будет пустым.
] Адрес |gj http://localhost/cgi-bin/mysql7.php
; Query: SELECT DATABASE();
Resource id #2Rows number: 1 .
i newdb I
Рис. 5.45. Функция database ()
Для того чтобы узнать, какие таблицы включены в выбранную базу данных, используем запрос: $stroka = "SHOW TABLES;";
Выведенная информация представлена на рис. 5.46.
'Э httpV/localhosVcgHain/m^^
]-^айду-‘Дравка. Вид^ Избранное Сервис j
.^Наэад- -^Вг-ере'»- '•, Останов... Обновить Ддрес|§) http://localhost/cgi-bin/mysql7.php
Query: SHOW TABLES;i
Resource id #2Rows number: 3■
event ;
newt able i;
Ipet I;
Рис. 5.46. Структура базы данных newdb
Чтобы получить описание таблицы, воспользуемся запросом, приведенным в файле mysq!7.php.
j Файл mysq!7.php
<?php
$c=mysql_connect("localhost:3306", "olymp", "vad");
mysql_select_db("newdb", $с);
$stroka = "DESCRIBE event;";
echo "Query: ".$stroka."<P>";
echo $result = mysql_query($stroka);
$noro=mysql_num_rows($result);
$nofields=mysql_num_fields($result);
echo "Rows number: ",$noro."<P>";
echo '<table border=l>';
while ($row = mysql_fetch_array ($result)) {
echo '<tr>';
for ($1=0; $1 < $nofields; $1++)
{ echo '<td>';
echo $row[$l]." </tdxtd>";
) echo "</trxtr>";
}
echo '</table>';
Здесь мы слегка изменили файл, вставив функцию mysqi_num_fieids (), чтобы далее нам не пришлось уделять специальное внимание тому, сколько столбцов будет в итоге. Результат отображен на рис. 5.47.
5 http//loctilhosVcqibm/mysql7php - Microsoft!
Senn,, Дреека Вид 4збрепное .Cgpanc I
p’JHaaaa^'" 'Вггёр=д'ь / 'Останов... .Обновить
Дсрвс|^http://localhosVcgi-bin/mysql?.php ;
Query: DESCRIBE event;
Resource id #2Rows number: 4
YES;YES^ YESlYES;YES^ YESlname! ^varchar (20)
YES;
YES^ YESl
YES;
YES^ YESl
! data ' jdale \ type |varchar(15) irematk vai'chai’(255)
Некоторые классические примеры
Классический пример из пособия, приведенного в документации по MySQL:
CREATE TABLE shop (
article INT(4) UNSIGNEDZEROFILLDEFAULT'0000'NOTNULL,
dealer CHAR(20)DEFAULT''NOTNULL,
price DOUBLE(16,2)DEFAULT'0.00'NOTNULL,
PRIMARY KEY(article, dealer));'
INSERT INTO shop VALUES
(1,'A',3.45),(1,'B',3.99),(2,'A',10.99),(3,'B',1.45),(3, 'C , 1.69), (3,’D',1.25),(4,'D',19.95);
Обычный MySQL запрос выглядит так:
SELECT * FROM shop;
■3 http://localhost/cgrbin/mysql? php - Microsoft Internet Explorer
| Miw11iM«- комков ^рвие .^ipasvn -., .-.|[
irV; -»./'d’ГУ'" ^-:" ■ 6-.. ST'
<j Наэад. . Ь «^лОстанов- Обновить .Домой ■ Поиск Избрани Журнал [, Почта • Печать Правка _ .ОРЯТЛ
^Дпрес[у7чр^ооа1н(^^ Э
Query: CREATE TABLE shop (article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL, dealer CHAR(20)
DEFAULT "NOT NULL, price DOUBLE(16,2) DEFAULT '0.00' NOT NULL, PRIMARY KEY(article, dealer));
IQuery: INSERTINTO shop VALUES (1,'A',3.45),(1,’B’,3.99),(2,'A', 10.99),(З.В', 1.45),(3,’C, 1.69),(3,’D’, 1.25),
(4,'D',19.95);
IQuery: SELECT * FROM shop;.
Resource id #2Rows number: 7
0001 [a 3.45 : I
0001 В 3.99 1 I
0002 A 10.99 !
0003 [C [L69 !
(0003 D 1.25 |
000-1 D 3 95 |
Рис. 5.48. Пример запросов
В PHP варианте мы его запишем так:
$stroka = "CREATE TABLE shop (article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL, dealer CHAR(20) DEFAULT '' NOT NULL, price DOUBLE(16,2)
DEFAULT '0.00' NOT NULL, PRIMARY KEY(article, dealer));";
echo "Query: ".$stroka."<P>";
echo $result = mysql_query($stroka);
$stroke = "INSERT INTO shop VALUES
(1,'A',3.45), (1,'B',3.99), (2, 'A', 10.99), (3, 'B*, 1.45), (3, 'C , 1.69), (3, 'D', 1.25),(4,'D',19.95);";
echo "Query: ",$stroka."<P>";
echo $result = mysql_query($stroka);
$stroka = "SELECT * FROM shop;";
Результат таких запросов показан на рис. 5.48.
Выбор максимального значения
$stroka = "SELECT MAX(article) AS article FROM shop";
Результат можно увидеть на рис. 5.49.
■I Адрес jy http://localhost/cgi-bin/mysq!7.php
Query: SELECT MAX( article) AS article FROM shop
Resource id #2Rows number: 1
1
Рис. 5.49. Выбираем максимальное значение
Строка, содержащая максимальное значение из определенного столбца
Это задача по поиску, например, наиболее дорогого товара. В MySQL такая задача распадается на два шага:
Нахождение максимальной цены с использованием запроса SELECT.
Использование полученного значения цены в новом запросе, например:
SELECT article, dealer, price
FROM shop
WHERE price=19.95
Другой способ решения задачи — отсортировать в убывающем порядке результат по цене и взять первую строку результата с использованием условия limit: SELECT article, dealer, price
FROM shop
ORDER BY price DESC
LIMIT 1
В PHP варианте этот запрос выглядит так:
$stroka = "SELECT article, dealer, price FROM shop ORDER BY price DESC LIMIT 1";
Если есть несколько единиц товара с одинаковой максимальной ценой, то этот запрос вернет только один из них.
Результат выполнения запроса показан на рис. 5.50.
•2 http://localhost/cgi-bin/mysql7.php - Microsoft Internet Explorer
I $®22 1.^®ка Эйд 'Й^ж^деч QgpipiC -Cfiptona--, - " • „•' ^ ~/
j , Назад -’;n'«ot'5 _ Останов... Обновить Домой , Поиск . Избранн... Журнал Почта
||^ре.в[й7й7/71оса1мс^^^~"
Query: SELECT article, dealer, price FROM shop ORDER BY price DESC LIMIT 1
Resource id #2Rows number: 1
0004 ;D~ 119795 j
Рис. 5.50. Выбираем самый дорогой товар
1ее***я*««**й№1иа|№вв8«8»1111яев»я«м|е№<шея1адая«™«н*»дая|яе1№*й№я»««иве*б»*®*»адм1*йь«*«еием«*№«я1е*адя»«я|ее<№^^
l-^ httpV/localhost/cgi-bin/mysql7.php - Microsoft Internet Exp
lorer|
1 файл ' Правка Вид ' Избранное-. Сервис Вправка
Наэад " Ureoetf-. Останов... ^Обновить Домой
3lid^,4
' - Поиск1 i Избранн..1,' Журнал | Пс
Адресjy http//localhosVcgi-bm/mysql7 php
Query:
Resour
0001
;0002
. 10003
l0004
SELEC
ce id #
3.99 i
10.99
1.69“
19.95
JT article, MAX(price) AS price FROM shop GROUP BY article;
2Rows number: 4‘
Еще один вариант запроса:
$stroka = "SELECT article, MAX(price) AS price FROM shop GROUP BY article;";
Результат продемонстрирован на рис. 5.51.
MySQL позволяет создавать пользовательские переменные. В таких переменных можно хранить промежуточные значения, не прибегая к необходимости хранить их где-то средствами программы PHP или другими способами.
$strokaO = "select @min_jorice:=min(price), @max_jorice:=max (price) from shop;";
$stroka = "select * from shop where price=@min_jorice or price=@max_jorice;";
На рис. 5.52 показан результат выполнения такого запроса.
Query: select * from shop where price=@min_price or price=@max_price;
Resource id #3Rows number: 2
0003! D 1.25
0004 D 19.95
Рис. 5.52. Запрос с использованием пользовательских переменных
На протяжении всего раздела мы поступали не самым оптимальным способом: каждый раз меняли содержимое PHP-файла вручную. Чтобы оптимизировать процесс, удобнее создать HTML-файл с формой, куда записывается запрос, а затем передать запрос основному PHP-файлу нажатием кнопки. Простейшая форма может быть описана в виде файла mysqlquery.html:
! Файл mysqlquery.html
<html>
<head>
<title>MySQL Query From </title>
<body>
<hl>My SQL Query GORM.</H1>
<р>Пожалуйста, введите ваш запрос
<P><form action ='http://localhost/cgi-bin/mysql8.php'>
<input type=text name="query">
<input type=submit>
</form>
</body>
</html>
В окне браузера мы увидим картинку, показанную на рис. 5.53.
Рис. 5.53. Запрос передается серверу посредством HTML-форм
Файл с PHP-программой немного будет изменен (файл mysqI8.php).
Файл mysql8.php
<?php $c=mysql_connect("localhost:3306", "olymp", "vad"); mysql_select_db("newdb",$c);
echo "Query: ".$query."<P>";
echo $result = mysql_query($query);
$noro=mysql_num_rows($result);
$nofields=mysql_num_fields($result); echo " Rows number: ",$noro."<P>"; echo '<table border=l>';
while ($row = mysql_fetch_array ($result)) {
echo '<tr>';
for ($1=0; $1 < $nofields; $1++) { echo '<td>';
echo $row[$l]." </tdxtd>";
}
echo "</trxtr>";
)
echo '</table>';
После отправки запроса сервер через секунду-другую возвратит результат (рис. 5.54)..
]6дрес(5] hUp:Mocalho$t/cgt-bin/mysql8.php?query=$elect+Mrom+evenl£3B
Query: select * from event;
Resource id #2 Rows number: 8
klein[2002-07-15FirstArrived■
Klein[2002-07-16SecondDeparted alone\
Klein2002-07-17FirstArrived with cargo;
Karaev2002-07-16ThirdAwaiting’
Hajt2002-07-17Second[Departed with cargo
Serovi'2002-07-10iother
Ilyin12020-02-07other
Ilyin : 12020-02-07 Fourth admitted'
Рис. 5.54. Скрипт выполнен
Работа с сетью
Язык PHP позволяет работать с сокетами. Посредством сокетов мы имеем возможность соединяться с серверами по протоколу TCP. Это означает, в частности, что сокет может быть использован, например, для формирования почтовых сообщений на более низком уровне, чем это позволяет функция mail о. С помощью сокетов на языке PHP мы можем в пару десятков строк написать HTTP прокси-сервер, который будет фильтровать и анализировать запросы каким угодно образом, а также скрывать клиентский IP, поскольку обращение к НТТР-серверам (Web-серверам) будет осуществляться от имени проксисервера с его IP, за которым не будет виден конечный клиентский адрес.
Сокет можно открыть с помощью функции f sockopen (). Эта функция возвращает указатель ресурса, который может быть использован в других функциях. Чтобы записать строку в сокет, удобно использовать функцию fputs (), аргументами которой являются указатель ресурса и строка, передающаяся сокету, а также длина передаваемой строки. Пример файла- заготовки для создания прокси-сервера показан ниже — файл soc.php.
i Файл soc.php:
<?php
$fp = fsockopen ("127.0.0.1", 80, $errno, $errstr, 130);
if (!$fp) {
echo "$errstr ($errno)<br>\n";
} else {
$string="GET / \n \n";
fputs ($fp, $string);
while (!feof($fp)) {
echo fgets ($fp, 1024);
}
fclose ($fp);
}
Здесь скрипт посылает HTTP-запрос через сокет, получает ответ и возвращает его браузеру. Необходимо помнить, что в этом примере не учтена возможность возникновения конфликтов HTTP-заголовков. НТТР-заголовок может быть сгенерирован несколько раз. Первый раз по запросу скрипта заголовок будет получен от сервера, к которому обратился скрипт, а второй раз заголовок будет создан ресурсами PHP на компьютере, где расположен скрипт. Чтобы не получилось дублирования заголовков, можно проанализировать полученный через сокет ответ, создать заголовок в соответствии с полученным ответом, а исходный — уничтожить.
Работа с изображениям
Чтобы работать с изображениями, необходимо подключить библиотеку php_gd.dll в файле php.ini и убедиться в том, что эта библиотека в момент выполнения PHP-программы будет доступна. Для этого можно запустить PHP-программу в консольном режиме, и если библиотека не может быть загружена, то появится сообщение об ошибке. Файл php.ini должен быть изменен таким образом, чтобы он содержал строчку (рис. 5.55):
extension=php_gd.dll;
| ^ php.ini - Блокнот
-|D|X|
: Note that it should be the name of the module only; no directory inform;*1 ; needs to go here. Specify the location of the extension with the ; extension_dir directive above.
;Windows Extensions ;Note that MySQL and ODBC support is now built in, so no dll is needed for
;extension:php_bz2.dl1 ; extension=php_ctype.dll
;extension=php_cpdf.dll.
;extension=php_curl.dll ; extension:php_cybercash.dll ;extension=php_db.dll ;extension:php_dba.dll ;extension:php_dbase.dll ;extension:php_domxml.dll ;extension:php_dotnet.dll ; extension:php_exif.dll ;extension:php_fdf.dll ; extension:php_filepro.dll |extension:php_gd.dll।
Рис. 5.55, Исправления в файле php.ini
Сейчас мы можем написать простой PHP-скрипт, разместив его в файле image l.php, который будет выглядеть так:
; Файл imagel.php:
<?php
header ("Content-type: image/png");
Sim = @ImageCreate (250, 150)
or die ("Cannot Initialize new GD image stream"); $background_color = ImageColorAllocate ($im, 235, 235, 235); $text_color = ImageColorAllocate (Sim, 133, 14, 91);
Imagestring (Sim, 15, 45, 15, "Text in an image", $text_color); ImagePng (Sim) ;
?>
Обратившись к этому файлу, расположенному в каталоге cgi-bin на локальном сервере, получим в окне браузера картинку, показанную на рис. 5.56. Заметим, что PHP-скрипт выводит заголовок:
header ("Content-type: image/png");
Это значит, что наш браузер получает изображение напрямую, а не как ссылку. Пользователь не сможет посмотреть пришедший HTML-код, его просто нет.
Рис. 5.56. Браузер отобразил простой рисунок, созданный средствами PHP
Аргументами функции imagestring () являются указатель на рисунок $1т; координаты первого символа текста надписи; строка, которая будет выведена в качестве надписи на рисунке; $text_coior — цвет, которым будет сделана эта надпись. Цвет предварительно необходимо задать при помощи функции imageCoiorAiiocate (), аргументами которой являются (кроме указателя на ресурс рисунка) три компонента цвета в системе RGB. Каждому цвету, определенному с помощью такой функции, в соответствие ставится переменная.
Более сложные надписи позволяет делать функция imageTTFText (), пример приведен в файле image2.php:
Файл image2.php .. ■/
<?php
header ("Content-type: image/png");
$im = @ImageCreate (250, 150)
or die ("Cannot Initialize new GD image stream");
$background_color = ImageCoiorAiiocate ($im, 205, 205, 205);
$text_color = ImageCoiorAiiocate ($im, 133, 14, 91);
Imagestring ($im, 15, 45, 15, "Text in an image", $text_color);
$black = ImageCoiorAiiocate ($im, 0, 0, 0);
$white = ImageColorAllocate ($im, 255, 255, 255);
ImageTTFText ($im, 20, 25, 50, 120, $white, "c:/windows/fonts/arial.ttf", "Testing... Omega: Ω");
ImagePng ($im) ;
ImageDestroy ($im) ;
?>
Результат показан на рис. 5.57, где текст выведен под наклоном. Текст может быть выведен под любым углом.
"Э h«pV?k№tilh<,sMciy t>in/rmag«2f ..■ .' . :io >• ЛОИ
р^айн Лравкг -Вий Избранное Сервис Snpseh» jДарес[^jTittpT/iocalhost^^Перехоа IJ
Text in an image
Рис. 5.57. Более сложная работа с текстом на рисунке
Аргументами функции ImageTTFText () являются идентификатор ресурса рисунка $1т; размер шрифта; угол в градусах по отношению к горизонтали против часовой стрелки; координаты первого символа строки; цвет символов строки; файл, в котором хранится шрифт; строка текста, который будет выведен на рисунке.
Еще один пример с этой функцией (см. рис. 5.58):
ImageTTFText ($im, 15, 25, 50, 120, $white, "с:/windows/fonts/arial.ttf", "Testing... Omega: Ω");
ImageTTFText ($im, 18, 180, 200, 130, $black, "c:/windows/fonts/arial.ttf",
'"Upside down.");
Функции для работы с изображениями позволяют считывать готовый рисунок, а затем его редактировать, например, наносить надписи (рис. 5.59).
'з1 http://localhost/cgi-bin/image3.php - Mictowll Inter
l] »3г..- Правка • Bw Марание Сдаие £лраа$~ ^REEH |::^дрй!й||й httpV/localhost/cgi-bin/image3.php ■* | г** Переход '1 Links ”l] »3г..- Правка • Bw Марание Сдаие £лраа$~ ^REEH |::^дрй!й||й httpV/localhost/cgi-bin/image3.php ■* | г** Переход '1 Links ”Text in an imageText in an imageимор apisdn
l] »3г..- Правка • Bw Марание Сдаие £лраа$~ ^REEH |::^дрй!й||й httpV/localhost/cgi-bin/image3.php ■* | г** Переход '1 Links ”
l] »3г..- Правка • Bw Марание Сдаие £лраа$~ ^REEH |::^дрй!й||й httpV/localhost/cgi-bin/image3.php ■* | г** Переход '1 Links ”
Text in an image
Text in an image
Рис. 5.59. Редактируем уже существующий рисунокРис. 5.59. Редактируем уже существующий рисунокРис. 5.58. Текст перевернули "вверх ногами"
Рис. 5.59. Редактируем уже существующий рисунок
Рис. 5.59. Редактируем уже существующий рисунок
Код скрипта:■•
<?php
header ("Content-type: image/jpeg");
$im = @ImageCreateFromJPEG("l.jpg") or die ("Cannot Initialize new GD image stream");
$background_color = ImageColorAllocate ($im, 205, 205, 205);
$text_color = ImageColorAllocate ($im, 133, 14, 91);
ImageString ($im, 15, 45, 15, "Text in an image", $text_color);
$black = ImageColorClosest ($im, 255, 255, 255);
ImageTTFText ($im, 50, 25, 10, 320, $black, "c:/windows/fonts/arial.ttf", "Text with non-zero angle");
ImageJPEG($im);
ImageDestroy($im);
?>
Передача файла серверу
Чтобы передать файл серверу вместе с HTML-формой, необходимо использовать элемент <input type=fiie>. HTML-форма должна содержать описание атрибута enctype="muitipart/form-data". Скрипт, который будет обрабатывать эту форму, также должен быть специальным образом подготовлен. Рассмотрим файл fileupload.html.
[ Файл fileupload.html
<html>
<head>
<titlex/title>
</head>
<body bgcolor="#FEF8C0">
<h2 align="center"xfont color="#EC2F97">N</fontXfont color="#83E2D9">e</fontxfont color="#223344">w</font>
<form enctype="multipart/form-data" action="fileupload.php" method="post">
<tr><td>Choose file here.
<input type=file name="userfile">
</tdxtdx/td> </tr>
Введите имя файла для сохранения
<input type=text name="fname">
<input type=submit value="Upload your file">
</td>
</tr>
</table>
</form>
</html>
Файл обрабатывающего скрипта — это файл fileupload.php.
Файл fileupload.php ,
<?php
$date = date("Y-m-d");
$time = date("G:i:s");
$ip=$REMOTE_ADDR;
if (is_uploaded_file($userfile)) {
copy($userfile, "./images/".$fname); $p=l;} else ( echo "Mistake found"; } ?>
Группы функций языка PHP
В языке PHP используется большой набор функций, которые позволяют создавать весьма гибкие программы. Мы не ставим целью описать подробно все функции языка PHP, для этого существует документация. Здесь мы перечислим основные группы функций языка PHP:
функции для работы с сервером Apache;
функции для работы с массивами;
функции для работы с математическими функциями произвольной точности;
функции сжатия Bzip2;
функции для работы с календарем;
функции обработки кредитных карт;
функции для поддержки СОМ в Windows;
функции для работы с классами и объектами;
функции для работы с форматом PDF — ClibPDF;
функции для работы с библиотекой CURL;
функции для обработки кредитных карт Credit Mutuel CyberMUT;
функции для работы с типами символов;
функции баз данных Dbm;
функции для работы со временем и датами;
функции для работы с базами данных dBase;
функции для работы с базами данных DBM;
функции баз данных dbx;
функции для работы с базами данных DB++;
функции для работы с каталогами;
функции для работы с объектной моделью DOM XML;
функции обработки ошибок;
функции для работы с базами данных FrontBase;
функции для работы с базами данных filePro;
функции для работы с файловой системой;
функции для работы с формами PDF документа;
функции управления FTP;
функции для работы с функциями;
функции многоязыковой поддержки Gettext;
функции поддержки целых произвольной длины GMP;
функции для работы с протоколом HTTP;
функции для работы с информационной системой Hyperwave;
функции конвертации из одной кодировки в другую icon;
функции для работы с рисунками;
почтовые функции IMAP, POP3 и NNTP;
функции для работы с базами данных Informix;
функции для работы с базами данных InterBase;
функции для работы с базами данных Ingres II;
функции для работы с чатом IRC;
функции Java;
функции работы с почтой;
математические функции;
функции календаря MCAL;
функции шифрования;
функции для работы с базами данных Microsoft SQL;
функции для работы с Flash;
поисковые функции mnoGoSearch;
функции для работы с базами данных mSQL;
функции для работы с базами данных MySQL;
функции для работы с сетью;
функции баз данных ODBC;
функции для работы с базами данных Oracle 8;
функции для работы с кодировками openSSL;
функции для работы с Oracle;
функции базы данных Ovrimos;
функции управления выводом;
функции для работы с PDF;
функции проведения платежей через систему Verisign;
функции информации о PHP;
функции для работы с POSIX;
функции для работы с базами данных PostgreSQL;
функции вызова программ;
функции печати;
функции проверки написания слов;
функции для работы с кодировками Recode;
функции для работы с регулярными выражениями;
функции для работы с объектами CORBA;
функции для работы с семафорами и памятью;
функции для работы с базами данных SESAM;
функции для работы с сессиями;
функции для работы с памятью;
функции для работы с Shockwave Flash;
функции для работы с сокетами;
функции для работы со строками;
функции для работы с базами данных Sybase;
функции для работы с URL;
функции для работы с переменными;
функции для работы с парсером XML;
функции преобразования XML документа XSLT;
функции YAZ для работы с протоколом Z39.50;
функции для работы с административными возможностями "желтых страниц" YP/NIS;
функции доступа к архивным файлам Zip;
функции сжатия Zlib.
PHP и ASP
В заключение данной главы упомянем утилиту asp2php. С ее помощью можно преобразовывать ASP-файлы в файлы PHP. Файл asp 1.asp (пример этого файла см. в гл. 4) с помощью утилиты asp2.php легко преобразуется в файл aspl.php.
Файл aspl.php
<html>'
<head>
<title>First ASP Page.</title>
</head>
<body>
<H1 align=center>This is our first ASP script page.</hl>
<P>Green font text is script generated text:
<font color=green size=+2>
<?■
print "Kak pogoda horosha! — This is instead of <b> Hello world</b>l";
?>
</font>
</body>
</html>
Браузер получит точно такой же HTML-код, как и при обработке файла aspl.asp.
Аналогичным образом файл asp2.asp (пример этого файла см. в гл. 4) преобразуется в файл asp2.php.
i Файл asp2.phpi
<? // asp2php (vbscript) converted ?>
<HTML>■
<HEAD>
<TITLE>Form Data Processing</TITLE>
</HEAD>
<BODY BGCOLOR="White" TOPMARGIN="10" LEFTMARGIN="10">
<FONT SIZE="4" FACE="ARIAL, HELVETICA">
<B>Form Posting</BX/FONTXBR>
<HR>
<P>This page will take the information entered in the form fields, and use the POST method to send the data to an ASP page.
<FORM NAME=Forml METHOD=Post ACTI0N="asp2.php"> First Name: <INPUT TYPE=Text NAME=fname><P> Last Name: <INPUT TYPE=Text NAME=lnameXP> CINPUT TYPE=Submit VALUE="Submit">
</FORM>
<HR>
<b>Hello, <i>
<? print $HTTP_POST_VARS["fname"] ; ?>
<? print $HTTP_POST_VARS["Iname"];?>
</i>
, you are welcome!</b>
</BODY>
</HTML>
Он вполне адекватно обрабатывается сервером.
Однако не следует преувеличивать возможности утилиты asp2.php. Вот пример оригинального файла mail.asp.
i Файл mail.asp■...|
<%
Set Mail = Server.CreateObject("Persits.MailSender")
Mail.Host = "blackhole"
Mail.Port =26
Mail.From = "from@host.com"
Mail.FromName = "Races Administration"
Mail.AddAddress Request.Querystring("address")
Mail.Subject = "User Registration"
Mail.Body = Re
quest .Querystring("string")+"&active="+Request.Querystring("active")
On Error Resume Next
Mail.Send
If Err <> 0 Then
Response.Write "An error occurred: " & Err.Description
End If
Response.Write "<script language='javascript'>document.location.href= 'http://olymp/auction/message.html'</script>"
//Response.Write Mail.Body
%>
В результате работы asp2.php получается что-то невразумительное (файл mailasp.php).
Файл mailasp.php
// $Mail is of type "Persits.MailSender"
$Mail.$Host="blackhole" ;
$Mail.$Port=26;
$Mail.$From="from@host.com";
$Mail.$FromName="Races Administration";
$Mail.$AddAddress$HTTP_GET_VARS["address"];
$Mail.$Subject="User Registration";
$Mail.$Body=$HTTP_GET_VARS["string"]+"&active="+$HTTP_GET_VARS["active"]; $On$Error$Resume$Next;
$Mail.$Send;
if ($Err!=0) {
print "An error occurred: ".$Err.$Description; }
print "<script language='javascript'>document.location.href=
'http://olymp/auction/message.html'</script>";
print $Mail.$Body;
He всегда можно использовать, казалось бы, простые решения. Вероятно, легче будет написать скрипт заново.
Глава 6
Самостоятельные
Java-приложения
Язык Java предоставляет удобный механизм создания Интернет-приложе- ний. Общая схема программирования такова. Создается программный код на языке Java. Код компилируется (компилятором javac), при этом получается платформенно-независимый класс Java. Созданный Java-код мы запоминаем в файле с расширением Java, скажем, name.java. После компиляции такого файла из командной строки, при помощи инструкции javac name.java, получим java-класс name.class. Этот, скомпилированный на любой платформе код может также благополучно работать на любой платформе. Для того чтобы java-класс можно было запустить как работающую программу, необходимо иметь на той машине, где будет работать программа, среду исполнения Java или виртуальную машину Java. Runtime environment — среда исполнения Java служит посредником между скомпилированным java- классом и операционной системой.
Приложения, написанные при помощи языка Java и предназначенные для работы в Интернете, могут исполняться как на клиентской машине (это апплеты, встроенные в HTML-страницу), так и на серверной стороне. Существует специальная технология создания легких серверных приложений на языке Java. Такие приложения называются сервлетами. Основная особенность создания апплетов, с рассмотрения которых мы начнем эту главу, состоит в том, что апплет строится на классе, который наследуется от класса Applet. Заметим, что имя файла следует называть точно так же, каким именем назван основной класс апплета. Это правило касается и других программ. Для выполнения апплетов, их необходимо загрузить в браузер или использовать специальную среду. Для выполнения апплета в браузере не обязательно устанавливать независимую среду исполнения Java на компьютер.
Апплеты
Апплеты — это небольшие Java-приложения, работающие в клиентском приложении, в браузере. Скомпилированный байт-код апплета может храниться по любому адресу в сети Интернет.
Первый апплет
В этой главе мы будем создавать несложные примеры с использованием языка Java. Необходимо установить Java2 SDK; пакет можно получить на сайте производителя (размер пакета около 40 Мбайт).
Перейдем к примеру. Возьмем какой-нибудь готовый Java-код апплета и скомпилируем его. Пусть это будет файл Simple.java:
import java.applet.Applet;
import java.awt.Graphics;
public class Simple extends Applet (
StringBuffer buffer;
public void init() {
buffer = new StringBuffer();
addltem("initializing... ") ;
}
public void start() (
addItem("We are starting... ") ;
}
public void stop!) {
additem("stopping... ");
}
public void destroy!) {
additem("preparing for unloading...");
}
void additem(String newWord) {
System.out.printin(newWord);
buffer.append(newWord);
repaint();
}
public void paint(Graphics g) {
//Рисуем прямоугольник вокруг области апплета.
g.drawRect(О, О, size().width — 1, size().height — 1);
//Выводим текущую строку в прямоугольник,g.drawstring(buffer.toString() , 5, 15);
}
}
В командной строке выполним javac Simple.java (рис. 6.1).
Рис. 6.1. Компилируем класс Java в командной строке
Компилятор создает файл класса Simple.class, в котором содержится выполняемая в среде исполнения Java скомпилированная программа, работающая в любой операционной системе. Следует помнить, что этот класс является апплетом. Чтобы его выполнить, мы воспользуемся браузером.
Напишем простой HTML-файл (на этот раз мы пренебрежем чистотой стиля и правилами хорошего тона) simple. HTML:
<applet code='Simple.class'>
В ярлыке апплета указываем местоположение класса апплета. Загружаем файл в браузер. Апплет работает (рис. 6.2).
Если внимательно присмотреться к загружаемой странице, то можно заметить, что в первые мгновения после загрузки HTML-текста, апплет еще не виден, но через несколько мгновений он появляется. После загрузки апплет инициализирует себя, а затем "запускается", начинает работать. При переходе на другую страницу апплет останавливается, затем осуществляется окончательное удаление апплета.
Как построен апплет
Апплет, который рассматривался в предыдущем разделе, имеет такую структуру: public class Simple extends Applet {
public void init() { . . . } public void start() { . . . } public void stop() { . . . } public void destroy() { . . . }
}
Как и все прочие апплеты, Simple является подклассом класса Applet. В нем переопределены методы класса Applet, соответствующие основным событиям жизненного цикла апплета:
□ метод init
инициализирует апплет после его загрузки;
метод start
запускает апплет;
метод stop
останавливает выполнение апплета;
метод destroy
производит зачистку перед выгрузкой страницы.
Вовсе необязательно переопределять эти методы, многие апплеты не нуждаются в этом вовсе.
Методы для прорисовки и для обработки событий
В апплете simple используется метод paint, при помощи которого происходит вывод текста в окне браузера:
class Simple extends Applet {
public void paint(Graphics g) { . . . }
}
Метод paint — это один из двух методов, используемых для осуществления графического вывода, которые могут быть переопределены:
paint — это базовый метод графического вывода; большинство апплетов используют именно этот метод для осуществления вывода в браузере;
update — еще один метод графического вывода, при помощи которого можно "обогатить" графику.
Апплеты наследуют набор методов для обработки событий из класса Component. Класс component содержит описания нескольких методов, например, таких как action И mouseDown, при помощи которых можно обрабатывать определенные типы событий. Существует метод, относящийся КО всем событиям, — метод handleEvent.
Чтобы программа смогла "прореагировать" на событие, необходимо переопределить соответствующий событию метод или же переопределить метод handleEvent. Вот, например, код апплета, в котором происходит действие в ответ на щелчок мыши:
import java.awt.Event;
public boolean mouseDown(Event event, int x, int y) { additem("click!... ") ; return true;
Изменим файл Simple.java, перепишем его в Simplel.java: import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Event;
public class Simplel extends Applet { StringBuffer buffer;
public void init() {
buffer = new StringBuffer() ;
addltemC'initializing. . . ") ;
}
public void start () { additem("starting... ");
}
public void stop() { additem("stopping... ") ;
}
public void destroy() {
additem("preparing for unloading...");
}
void addItem(String newWord) { System.out.printin(newWord); buffer.append(newWord); repaint () ;
}'
public void paint(Graphics g) { //Прямоугольник вокруг апплета
g.drawRect(0, 0, size().width — 1, size().height — 1) ;
//Строка в прямоугольнике
g.drawstring(buffer.toString(), 5, 15); }
public boolean mouseDown(Event event, int x, int y) { additem("clickI... ") ;
return true;
} }
Создадим файл Simplel.html:
<applet code='Simplel.class' width=700>
и загрузим его в браузер, после чего щелкнем несколько раз на изображении апплета. С каждым новым щелчком в апплете будет появляться надпись Click (рис. 6.3).
Рис. 6.3. Обрабатываем события в апплете
Графические элементы
В апплетах существует возможность использовать набор заранее подготовленных элементов пользовательского интерфейса, таких как кнопки, текстовые поля, списки и т. п. Вот список этих компонентов:
КНОПКИ Buttons (j ava . awt. Button);
поля для галочек Checkboxes (java. awt. Checkbox);
однострочные текстовые поля (java.awt.TextField);
текстовые ПОЛЯ многострочные (java.awt.TextArea);
метки Labels (java. awt. Label);
СПИСКИ Lists (java.awt.List);
выпадающие СПИСКИ ДЛЯ выбора (java. awt. Choice);
ползунки И ПОЛОСЫ прокрутки (java.awt.Scrollbar);
ЗОНЫ для рисования (java. awt. Canvas);
меню (java.awt.Menu, java.awt.Menuitem, java.awt.CheckboxMenuItem);
контейнеры (java.awt.Panel, java.awt.Window И Подклассы).
Компоненты пользовательского интерфейса в апплетах
Класс Applet создан на основе класса Container. Вот некоторые методы класса Container.
Метод add
Вставляет тот или иной компонент класса component.
Метод remove
Удаляет компонент.
Метод setLayout
Задает конфигурацию апплета. Рассмотрим в примере нередактируемый текст (файл Simple2.java):
import java.awt.TextField;
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Event;
public class Simple2 extends Applet {
TextField field;
public void init() { //Создаем текстовое поле field = new TextFieldO;
field.setEditable(false);
//Задаем параметры поля setLayout(new java.awt.GridLayout(1,0));
//Вставляем поле в апплет add(field);
validate();
addltemfYesinitializing... Write whatever you want");
}
void addltem(String newWord) { //Вставляем строку в StringBuffer;
String t = field.getTextO;
System.out.printin(newWord); field.setText(t + newWord); repaint();
}
}
В окне браузера апплет будет выглядеть так, как показано на рис. 6.4.
'^C:\idk1.3.1\bin\simpiie2.htfnl - Microsoft 1гйётеГЁ ._ WWplI
-Fie Edit View Favorites Tools Help
Address [^ C \idk1 31 kbin\simple2 hlml
Yesritializing,,. Write whatever you want
Рис. 6.4. Текст выведен в нередактируемом текстовом поле
Возможности апплетов
Апплеты не должны допускать возможность осуществления несанкционированных действий. Поэтому существует ряд ограничений, накладываемых на апплеты, которые объясняются соображениями безопасности:
апплет не может загружать библиотеки или определять методы native;
апплет не может читать файлы и писать файлы на хосте, который выполняет этот апплет;
апплет не может создавать сетевые соединения, кроме соединения с хостом, с которого апплет был загружен;
апплет не может запустить программу на том компьютере, где он выполняется;
апплет не может читать некоторые системные свойства;
окно апплета выглядит по-иному, чем окно приложения.
Каждый браузер имеет объект менеджера безопасности securityManager, который отвечает за политику безопасности. Если этот менеджер обнаруживает нарушение политики безопасности, то он вызывает исключение SecurityException. Апплет может перехватить это исключение и прореагировать надлежащим образом.
Пакет java.applet предоставляет ряд возможностей, которыми не обладают обычные приложения. Так, апплеты могут легко воспроизводить звук. Вот список некоторых возможностей, специально включенных в пакет для разработки апплетов, которые выгодно отличают апплеты от обычных программ:
апплеты, как правило, могут создавать сетевое соединение с хостом, откуда они были загружены;
апплеты, исполняемые в браузере, могут взаимодействовать с HTML- документом;
апплеты могут вызывать методы public других апплетов, расположенных на той же самой страничке;
апплеты, загруженные из локальной файловой системы (из каталога, ука- ■ занного в CLASSPATH), не обладают ограничениями апплетов, загруженных из сети;
несмотря на то, что почти все апплеты прекращают работу при уходе со странички, они вовсе не обязаны этого делать.
Далее мы рассмотрим некоторые классические примеры, часто используемые при работе с апплетами. Для более подробного изучения возможностей, доступных при создании апплетов, рекомендуем обратиться к документации по программированию на языке Java.
Работа с апплетами
Отображение документов в браузере
Если появляется необходимость отобразить в браузере некоторый HTML- документ с помощью апплета, то это несложно сделать. Требуется всего лишь указать браузеру, что нужно отобразить тот или иной текст.
Используем методы Appletcontext и showDocument. Второй метод имеет два варианта:
public void showDocument(java.net.URL url);
public void showDocument(java.net.URL url, String targetWindow).
Вариант с одним аргументом попросту сообщает адрес документа, который должен быть загружен в браузер, во втором варианте указывается помимо адреса документа и имя окна, в которое должен быть загружен документ с указанным адресом. Аргумент targetwindow может иметь такие значения: □ "„blank"
отображает документ в новом окне, у которого нет собственного имени;
"windowName"
отображает документ в окне с именем windowName. При необходимости, если окна с таким именем не существует, создается новое окно; .
"„self"
отображает документ в том же окне и фрейме, которые содержат апплет;
"„parent"
отображает документ в том же окне, где расположен апплет, но в родительском фрейме. Если родительский фрейм отсутствует, то работает так же, как "„self";
"„top"
отображает документ в том же окне, где расположен апплет, но в самом старшем, корневом фрейме.
urlWindow = new URLWindow(getAppletContext()) ;
class URLWindow extends Frame {
public URLWindow(Appletcontext appletcontext) {
this.appletcontext = appletcontext;
public boolean action(Event event, Object o) {
String urlString = /* сюда поместим строку */; URL url = null;
try (
url = new URL(urlString) ;
} catch (MalformedURLException e) (
. . . //Информация об ошибке...
}
if (url ! = null) ( if (/* без указания окна */) ( appletcontext.showDocument(url) ;
} else {
appletcontext.showDocument(url, /* какое окно? */);
}
Пишем полный код апплета и сохраняем его в файле Simple3.java:
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.net.URL;
import java.net.MalformedURLException;
public class Simple3 extends Applet implements ActionListener (
URLWindow urlWindow;
public void init() (
Button button = new Button("Покажи-ка документ,
но вначале новое окно!");
button.addActionListener(this);
add(button);
urlWindow = new URLWindow(getAppletContext());
urlWindow.pack ();
public void destroy() {
urlWindow.setVisible(false); urlWindow = null;
}
public void actionPerformed(ActionEvent event) { urlWindow.setVisible(true);
class URLWindow extends Frame implements ActionListener { TextField urlField;
Choice choice;
Appletcontext appletcontext;
public URLWindow(Appletcontext appletContext) { super("Теперь покажи сам документ!");
this.appletcontext = appletcontext;
GridBagLayout gridBag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); setLayout(gridBag);
Label labell = new Label("URL для документа, что надо показать:", Label.RIGHT);
gridBag.setconstraints(labell, c); add(labell);
urlField = new TextField("http://www.e-olymp.com/", 40); urlField.addActionListener(this);
c.gridwidth = GridBagConstraints.REMAINDER;
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1.0;
gridBag.setconstraints(urlField, c);
add(urlField);
Label label2 = new Label("В каком окне или фрейме показывать:", Label.RIGHT);
с.gridwidth = 1;
c.weightx = 0.0;
gridBag.setconstraints(label2, c);
add(label2);.
choice = new Choice();
choice.additem("По выбору браузера");
choice.additem("My Window");
choice.addltem("_blank"); //Новое окно
choice.addltem("_self"); // В то же окно
choice.additem("_parent");
choice.addltem("_top");
c.fill = GridBagConstraints.NONE;
c.gridwidth = GridBagConstraints.REMAINDER;
c.anchor = GridBagConstraints.WEST;
gridBag.setconstraints(choice, c);
add(choice) ;
Button button = new Button("Теперь покажет сам документ"); button.addActionListener(this);
c.weighty =1.0;
c.ipadx = 10;
c.ipady = 10;
c.insets = new Insets(5,0,0,0) ;
c.anchor = GridBagConstraints.SOUTH;
gridBag.setconstraints(button, c);
add(button) ;
addWindowListener(new WindowAdapter() {
public void windowclosing(WindowEvent event) ( setvisible(false);
}
});
String urlString = urlField.getText ();
URL url = null;
try {
url = new URL(urlString);
} catch (MalformedURLException e) {
System.err.printin("Malformed URL: " + urlString);
if (url != null) {.
if (choice.getSelectedlndex() == 0) { appletcontext.showDocument(url);
} else {
appletcontext.showDocument(url, choice.getSelectedltemO ); }
Компилируем (команда javac Simple3.java) и загружаем в браузер (рис. 6.5).
Нажимаем кнопку Покажи-ка документ, но вначале новое окно!. Появляется новое окно с предложением ввести URL и имя окна для вывода этого URL (рис. 6.6).
Вводим URL и имя окна и нажимаем кнопку показа документа. Документ появляется в указанном окне (рис. 6.7).
[^ Файл Правка Вид Навигаций Закладки -Лочта Чзт Новости Окно Справка' , '. ‘'. ' w|51 х|
Создать Печать Найти Список Наэад ■ I'ЯкУ software
The fastest browser on earth!
■ Обновить Рлесед Домой'•.
oTD S^| Hle://localhost/E:/jdkl.3.1/bin/simple3.htmlД ^^ y I <Поискc Google > *| $ * 1100% ^|
Покэжи-ка документ, но вначале новоеокно||
Рис. 6.5. Апплет в окне браузера
|^Теперь покажи сам документ!
ЯН^Е КЗ 1
URL для документа, что надо показать:|Ьйр:/|Шда.е-о1утр.сот/
В каком окне или фрейме локазывать:|по выбору броузера jJ Теп®:"ь пока^ сам документ j
(Java Applet Window ЯЯ ^ЯЯЯЯ^ЯЯЯ:
Рис. 6.6. Окно выбора URL
^ SetsbarSeivcM - Microsattlnieinel О|^
•' *^"'Л i}pds<<3 £нд И^н^ое Стране ^^зг^' *■г ,‘ /,.
л Назад . ,kiP№i Рстановигь . Обновить ^Домой ’ j Поиск Избранное ’ Журнал, L - Почта Печать ' хЯ
ЙДрв^Й http:/'/localhost/™3;'^fieWM^iфМпЙ^
iiSAMBAR TECHNOLOGIES
i
i
Sambar Server F5.0 Beta 5
Search ToolsSearch ToolsSite Search Help ISAPI Search Tool Perl Search Tool .Site Search Help ISAPI Search Tool Perl Search Tool .WWW ResourcesWWW ResourcesWorld Wide Webr Consortium -'' NCSAHTTPd ' Apache ■ Doctor HTML ■ Net craft Survey^ ГОТОВО 7 'x J _ . • _ ' <World Wide Webr Consortium -'' NCSAHTTPd ' Apache ■ Doctor HTML ■ Net craft Survey^ ГОТОВО 7 'x J _ . • _ ' <Sambar Server
Search Tools
Search Tools
Site Search Help ISAPI Search Tool Perl Search Tool .
Site Search Help ISAPI Search Tool Perl Search Tool .
WWW Resources
WWW Resources
World Wide Webr Consortium -'' NCSAHTTPd ' Apache ■ Doctor HTML ■ Net craft Survey
^ ГОТОВО 7 'x J _ . • _ ' <
World Wide Webr Consortium -'' NCSAHTTPd ' Apache ■ Doctor HTML ■ Net craft Survey
^ ГОТОВО 7 'x J _ . • _ ' <
Pro Version■
Documentation
Security Suggestions■
Frequently Asked Questions
Sambar Server Samples
System
Administration
The System Administration page-
provides basic site management. By. :
default, the username is ’admin’ and-.;
TT» --£7*1 ®'Мб$гиаяи«гре<»гь. ^
Рис. 6.7. Документ отображен в окне браузера
Пересылка сообщений от одного апплета другому
Апплеты могут обмениваться сообщениями друг с другом, но при этом соблюдаются следующие предосторожности, установленные из соображений безопасности:
часто устанавливается требование, что связывающиеся друг с другом апплеты должны быть загружены с одного и того же сервера;
часто задается требование, чтобы апплеты находились в пределах одного и того же каталога сервера;
апплеты должны быть запущены в пределах одной страницы в одном и том же окне браузера.
Некоторые браузеры позволяют осуществлять вызовы методов других апплетов даже в том случае, если апплет расположен на другой странице того же браузера. Чтобы передать сообщение от одного апплета к другому, необходимо, чтобы апплеты нашли друг друга. Апплет может найти другой апплет либо по имени, используя метод Appletcontext getAppiet, либо путем нахождения всех апплетов с использованием метода Appletcontext getAppiets. Тот и другой метод возвращает апплету один или несколько объектов Applet. После того как требуемый апплет найден, вызывающий апплет может использовать все необходимые методы.
Метод getAppiet— находим апплет по имени
Метод getAppiet просматривает все апплеты на текущей странице и проверяет их имена. По умолчанию апплет не будет иметь имени. Чтобы апплет имел имя, его нужно указать в HTML-коде.
Можно указать значение атрибута name внутри ярлыка <appiet>, например, так:
<APPLET CODEBASE=example/ CODE=Sender.class
WIDTH=450
HEIGHT=200
NAME="buddy">
</applet>-
Можно указать имя апплета, задав значение параметра name:
<APPLET CODEBASE=example/ CODE=Receiver.class
WIDTH=450
HEIGHT=35>
<PARAM NAME="name" value="old pal">
</applet>
Используем текст примера, создадим апплет, который будет принимать сообщения, класс апплета назовем Receiver.java:
import java.applet.*;
import java.awt.*;
private final String waitingMessage = "Waiting for a message..."; private Label label = new Label(waitingMessage, Label.RIGHT);
public void init() { add(label);
add(new Button("Clear"));
add(new Label("(My name is " + getParameter("name") + ".)", Label.LEFT));
validate();
}■
public boolean action(Event event, Object o) { label.setText(waitingMessage);
repaint () ; return false;
}
public void processRequestFrom(String senderName) (
label.setText("Received message from " + senderName + "I"); repaint();
}
public void paint(Graphics g) (
g.drawRect (0, 0, size().width — 1, size ().height — 1); }
public String getAppletlnfo() (
return "Receiver (named " + getParameter("name") + ") Our testing service"; }
}
Создадим апплет, который находит все апплеты на текущей странице и отображает их имена. Назовем класс апплета GetApplets.java: import java.applet.*; import java.awt.*; import java.awt.event.*;
import java.util.Enumeration;
public class GetApplets extends Applet implements ActionListener ( private TextArea textArea;
private String newline;
Button b = new Button("Click to call — Calling for getAppletsO"); b.addActionListener(this);
setLayout(new BorderLayout()) ;
add("North", b) ;
textArea = new TextArea(5, 40);
textArea.setEditable(false);
add("Center", textArea);
newline = System.getProperty("line.separator"); }
public void actionPerformed(ActionEvent event) { printApplets();
public String getAppletlnfo() ( return "GetApplets exclusively for educational purposes";
}
public void printApplets() {
//Нумератор будет содержать все апплеты текущей страницы //включая этот апплет
Enumeration е = getAppletContextО .getApplets();
textArea.append("Results of getAppletsO:" + newline);
while (e.hasMoreElements()) (
Applet applet = (Applet)e.nextElement();
String info = ((Applet)applet).getAppletlnfo();
if (info != null) (
textArea.append("- " + info + newline);
} else (
textArea.append("- "
+ applet.getClass().getName() + newline);
}
textArea. append ("" + newline + newline);
Сейчас поместим оба апплета на одну HTML-страницу, причем апплет, получающий сообщения, поместим дважды, указав для каждой копии свое имя (файл sendreceive.html):
<APPLET code=Receiver.class height=35 width=450>
<PARAM NAME="name" VALUE="old">
<PARAM NAME=”code" VALUE="Receiver.class">
<PARAM NAME="height" VALUE="35">
<PARAM NAME="width" VALUE="450">
</APPLET>
<APPLET code=Receiver.class height=35 width=450>
<PARAM NAME="name" VALUE="new">
<PARAM NAME="code" VALUE="Receiver.class">
<PARAM NAME="height" VALUE="35">
<PARAM NAME="width" VALUE="450">
</APPLET>
<APPLET code=GetApplets.class height=150 width=400>
<PARAM NAME="code" VALUE="GetApplets.class">
<PARAM NAME="height" VALUE="150">
<PARAM NAME="width" VALUE="400">
</APLET>
Загрузим эту страницу в браузер и нажмем кнопку Click to call — Calling for getApplets (). В окне первого апплета появятся сообщения о найденных апплетах (рис. 6.8).
Рис. 6.8. Работает апплет, который ищет все апплеты на данной странице
Создадим апплет, посылающий сообщения (файл Sender.java):
import java.applet.*;
import java.awt.*;
import java.util.Enumeration;
public class Sender extends Applet {
private String myName;
private TextField nameField;
private TextArea status;
public void init() {
GridBagLayout gridBag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints();
setLayout(gridBag);
Label receiverLabel = new Label("Receiver name:", Label.RIGHT); gridBag.setconstraints(receiverLabel, c);
add(receiverLabel);
nameField = new TextField(getParameter("RECEIVERNAME"), 10); c.fill = GridBagConstraints.HORIZONTAL;
gridBag.setconstraints(nameField, c); add(nameField);
Button button = new Button("Send message"); c.gridwidth = GridBagConstraints.REMAINDER; c.anchor = GridBagConstraints.WEST;
c.fill = GridBagConstraints.NONE;
gridBag.setconstraints(button, c); add(button);
status = new TextArea(5, 60);
status.setEditable(false);
c.anchor = GridBagConstraints.CENTER;
c.fill = GridBagConstraints.BOTH;
c.weightx = 1.0;
c.weighty = 1.0;
gridBag.setconstraints(status, c);
add(status);
myName = getParameter("NAME");
Label senderLabel = new Label("(My name is " + myName + ".)", Label.CENTER);
c.weightx = 0.0;
c.weighty = 0.0;
gridBag.setConstraints(senderLabel, c);
add(senderLabel);
validate();
}
public boolean action(Event event, Object o) {
Applet receiver = null;
String receiverName = nameField.getText();
receiver = getAppletContext().getApplet(receiverName);
if (receiver != null) {
if (((receiver instanceof Receiver)) { status.appendText("Found applet named " + receiverName + ", "
+ "but it's not a Receiver object.\n");
} else { status.appendText("Found applet named " + receiverName + ".\n"
+ " Sending message to it.\n");
((Receiver)receiver).processRequestFrom(myName); }
} else {
status.appendText("Couldn't find any applet named " + receiverName + ".\n");
}
return false;
public Insets insets() { return new Insets(3,3,3,3) ;
}
public void paint(Graphics g) {
g.drawRect(0, 0, size().width — 1, size().height — 1); }
public String getAppletlnfo() ( return "Our testing sender applet";
}
Вставим апплет в HTML-страницу, которая описывается при помощи файла sendreceivel.html:
<APPLET code=Receiver.class height=35 width=450>
<PARAM NAME="name" VALUE="old">
<PARAM NAME="code" VALUE="Receiver.class">
<PARAM NAME="height" VALUE="35">
<PARAM NAME="width" VALUE="450">
</APPLET>
<APPLET code=Receiver.class height=35 width=450>
<PARAM NAME="name" VALUE="new">
<PARAM NAME="code" VALUE="Receiver.class">
<PARAM NAME="height" VALUE="35">
<PARAM NAME="width" VALUE="450">
</APPLET>
<APPLET code=GetApplets.class height=150 width=400>
<PARAM NAME="code" VALUE="GetApplets.class">
<PARAM NAME="height" VALUE="150">
<PARAM NAME="width" VALUE="400">
</APPLET>
<PXAPPLET code=Sender.class height=200 name=SenderName width=450XPARAM NAME="receiverName" VALUE="old">
<PARAM NAME="code" VALUE="Sender.class">
<PARAM NAME="height" VALUE="200">
<PARAM NAME="name" V7VLUE="SenderName">
<PARAM NAME="width" VALUE="450">
</APPLET>
Загрузим страницу в браузер. Мы увидим четыре апплета, как показано на рис. 6.9.
Рис. 6.9. Четыре апплета: два приемника, апплет для поиска и апплет для передачи в исходном состоянии
Рис. 6.10. Посылаем сообщение апплету old
Нажмем в апплете для передачи кнопку Send. Апплет выдаст надпись о том, что сообщение апплету old послано, в свою очередь, апплет old сообщит нам, что получил сообщение от апплета с именем SenderName (рис. 6.10).
Сменим имя апплета-получателя в апплете SenderName, укажем имя new и нажмем кнопку посылки сообщения. Апплет напишет, что послал сообщение апплету new. А апплет new сообщит о том, что сообщение принято (рис. 6.11).
Рис. 6.11. Посылаем сообщение апплету new
Как мы убедились, обмен сообщениями между апплетами — задача не слишком сложная.
Звук в апплетах
В java-апплетах существует возможность поддерживать работу со звуком. Для этого используются класс Applet и интерфейс AudioClip. Далее мы рассмотрим некоторые методы класса Applet. Как правило, аргументами
методов являются два параметра — базовый URL, который можно получить при помощи getDocumentBase или getCodeBase, и имя звукового файла.
Метод getAudioClip (вариант 1)
public AudioClip getAudioClip(URL url)
Возвращает объект AudioClip по указанному в качестве аргумента url пути. Метод работает сразу, и результат не зависит от того, существует или нет аудиофайл. Данные загружаются только при попытке воспроизвести файл.
Метод getAudioClip (вариант 2)
public AudioClip getAudioClip(URL url, String name)
Отличается от предыдущего метода только тем, что аргумент URL задает базовый URL, а в строке указывается имя файла.
Интерфейс AudioClip содержит следующие методы:
loop — начало воспроизведения клипа в цикле (повторяющееся воспроизведение);
play — начало однократного воспроизведения файла;
stop — остановка воспроизведения (работает и с однократным, и с многократным воспроизведением в цикле).
Как получить из апплета системные свойства
При помощи апплета можно прочесть некоторые системные свойства, узнать окружение, в котором работает апплет. Свойства, которые может читать апплет, приведены в табл. 6.1.
Таблица 6.1. Системные свойства, получаемые из апплета
Свойство
Назначение
"file.separator"
Знак разделителя в записи файлов, например "Г
"java.class.version"
Версия Java-класса
"java.vendor"
Владелец данной реализации Java
"java.vendor.url"
URL-владелец данной реализации Java
"java.version"
Версия Java
"line.separator"
Разделитель строк
"os.arch"
Архитектура операционной системы
"os.name"
Название операционной системы
"path.separator"
Разделитель при указании пути, например ":"
Для чтения системных свойств используется метод getProperty, например: String newline = System.getProperty("line.separator");
Из соображения безопасности, чтение некоторых системных свойств запрещено (табл. 6.2).
Таблица 6.2. Системные свойства, недоступные апплету
Свойство
Значение
"java.class.path"
Значение classpath
"java.home"
Каталог, куда установлен Java
"user.dir"
Текущий рабочий каталог
"user.home"
Домашний каталог
"user.name"
Имя пользователя
Рассмотрим пример, файл Properties.java.
Файл Properties.java
import java.awt.*; import java.applet.*;
public class Properties extends Applet implements Runnable { String[] propertyNames = {"file.separator", "line.separator", "path.separator", "java.class.version", "java.vendor", "java.vendor.url", "java.version", "os.name", "os.arch", "os.version"};
final int numProperties = propertyNames.length; Label[] values;
public void init() {
//Set up the layout.
GridBagLayout gridbag = new GridBagLayout();
setLayout(gridbag);
GridBagConstraints labelconstraints = new GridBagConstraints();
GridBagConstraints valueconstraints = new GridBagConstraints();
labelconstraints.anchor = GridBagConstraints.WEST; labelconstraints.ipadx = 10;
valueconstraints.fill = GridBagConstraints.HORIZONTAL; valueconstraints.gridwidth = GridBagConstraints.REMAINDER;
valueconstraints.weightx = 1.0; //Extra space to values column.
//Создаем массивы Labels.
Label[] names = new Label[numProperties];
values = new Label[numProperties];
String firstValue = "not read yet";
for (int i = 0; i < numProperties; i++) { names[i] = new Label(propertyNames[i]); gridbag.setconstraints(names[i], labelconstraints); add(names[i]) ;
values[i] = new Label(firstValue);
gridbag.setconstraints(values[i], valueconstraints); add(values[i] ) ;
}
new Thread(this, "Loading System Properties").start(); }
public void run() ( String value = null;
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
//Пауза, чтобы пользователь успел прочитать строку по умолчанию, pause(3000);
for (int i = 0; i < numProperties; i++) ( //Пауза для выразительности.
pause(250);
try (
value = System.getProperty(propertyNames[i]); values[i] .setText(value);
} catch (SecurityException e) { values[i].setText("Could not read: " + "SECURITY EXCEPTION!");
synchronized void pause(int millis) { try {
wait(millis);
} catch (InterruptedException e) { }
} }
Скомпилируем класс Properties.java и загрузим страницу properties.html в браузер.
I Файл properties.html.■ ■i
<P><APPLET code=Properties.class height=400 width=950>
</APPLET>
В разных браузерах системные свойства будут различными. Для Internet Explorer результат работы апплета показан на рис. 6.12. Для Netscape Navigator результат будет другой, он отображен на рис. 6.13.
3 CAjdkl 3.1 \bin\properties.html - Microsoft I... НВ Bl
F8e Edit View Favorite» Tools Help
Adrress |«<F\jdk1.3.1 \bin\properties.html y| ^Go
file.separator S
path separator iava.class. version java, vendor .java vendor, url java, version os.name /'os. archos. versionpath separator iava.class. version java, vendor .java vendor, url java, version os.name /'os. archos. versionKne. separator
path separator iava.class. version java, vendor .
java vendor, url java, version os.name /'
os. arch
os. version
path separator iava.class. version java, vendor .
java vendor, url java, version os.name /'
os. arch
os. version
453’
Mictosul; Cc.p http //www mcrosoft com/ ВИЙ»
WindowsNT - ’ x86 ''■
Вй111О1Яв
Рис. 6.12. Системные свойства, полученные с помощью апплета, в Internet Explorer
^ Netscape
Файл Правка gm Переиси Компоненты £правка.
Н*^’3 ■^<53.К*
.;ас..'Ьте,у-чОбновитьДомойПоискNetscape- Печать
I S^t' Закладки ^ Адрес: Jfile ///Cl/idkl 3.1 /bm/properties html
■•i Д Instant Message !§ Members ^| WebMai §] Connections J^ BoJoo
file.separator
line.separator
□□
path.separator
java.class.version
45.3
java.vendor
Netscape Communications Corporation
java.vendor.url
http://home.netscape.com/
java.version
1.1.5
os.name
Windows 95
os.arch
x86
os.version
4.10
Рис. 6.13. Системные свойства, полученные с помощью апплета,в Netscape Navigator
Работа с потоками в апплетах
В апплетах бывает удобно использовать потоки (threads). Чтобы рассказать, как это делается, приведем стандартный пример (файл Treads.java).
Файл Threads.java
import java.applet.Applet; import java.awt.Graphics; import java.awt.TextArea; import java.awt.GridLayout;
public class Threads extends Applet {
80) ;80) ;TextArea display = new TextArea(1,
80) ;
80) ;
public void init() {
//Создание текстовой области (нередактируемая). display = new TextArea(1, 80);
display.setEditable(false);
//Задаем максимально широкую текстовую область.
setLayout(new GridLayout(1,0));
//Вставляем текстовую область в апплет.
add(display);
validate();
additem("init: " + threadinfo(Thread.currentThread())); }
public void start () {
additem("start: " + threadinfo(Thread.currentThread())); }
public void stop() (
additem("stop: " + threadinfo(Thread.currentThread())); }
public void destroy() (
addltem("destroy: " + threadinfo(Thread.currentThread())); }
String threadinfo(Thread t) (
return "thread™" + t.getName() + ", "
+ "thread group™" + t.getThreadGroup().getName(); }
void additem(String newWord) (
System.out.printin(newWord);
display.appendText(newWord + "\n");
display.repaint();
}''
}
Скомпилированный файл вставляется в HTML-страницу при помощи кода файла threads.html.
I Файл threads.html
<html>
<title>
' Threads — Потоки
</title>
<body>
<hl>
Работа с потоками
</hl>
<applet code="Threads.class" width=450 height=100>
</applet>
<applet code="Threads.class" width=450 height=100>
</applet>
</body>
</html>
В браузере мы получаем соответствующую картинку (рис. 6.14).
Рис. 6.14. Апплет и потоки
Сеть и апплеты
Работу с сетью мы также проиллюстрируем на стандартном примере. Для этого потребуется четыре файла. Файлы сервера (их нужно скомпилировать, а затем запустить сервер) приведены ниже.
Серверный файл QuoteServer.java
class Quoteserver {
public static void main(String[] args) { new QuoteServerThread().start();
)
Серверный класс QuoteServerThread.java■
import java.io.*;
import java.net.*; import java.util.*;
class QuoteServerThread extends Thread { private Datagramsocket socket = null;
private BufferedReader qfs = null; private boolean moreQuotes = true;
QuoteServerThread() {
super("QuoteServer");
try {
socket = new Datagramsocket();
System.out.println("QuoteServer listening on port: " + socket.getLocalPort() ) ;
} catch (java.io.IQException e) {
System.err.printin("Could not create datagram socket."); ) this.openlnputFile();
}
public void run() { if (socket == null)
return;
while (moreQuotes) { try {
byte[] buf = new byte[256];
DatagramPacket packet;
InetAddress address;
int port;
String dString = null;
// Получить запрос
packet = new DatagramPacket(buf, 256);
socket.receive(packet);.
address = packet.getAddress();
port = packet.getPort ();
// Послать запрос if (qfs == null)
dString = new Date().toString(); else
dString = getNextQuote();
buf = dString.getBytes();
packet = new DatagramPacket(buf, buf.length, address, port); socket.send(packet);
} catch (lOException e) {
System.err.printin("lOException: " + e) ;
moreQuotes = false;
e.printStackTrace (); }
socket.close ();
}
private void openlnputFile () {
try {
qfs = new BufferedReader(new InputStreamReader (new FileInputStreamCone-liners.txt") )) ;
} catch (java.io.FileNotFoundException e) { System.err.printin("Could not open quote file.
Serving time instead.");
private String getNextQuote() (
String returnvalue = null;
try (
if ((returnvalue = qfs.readLine()) == null) ( qfs.close();
moreQuotes = false;
returnvalue = "No more quotes. Goodbye.";
}
} catch (TOException e) (
returnvalue = "lOException occurred in server.";
}.
return returnvalue;
}
; Клиентский апплет QuoteClientAppletjava
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.*;
public class QuoteClientApplet extends Applet implements ActionListener ( boolean DEBUG = false;
InetAddress address;
TextField portField;
Label display;
Datagramsocket socket;
public void init() { // Инициализация сети String host = getCodeBase().getHost();
try (
address = InetAddress.getByName(host);
} catch (UnknownHostException e) {
System.out.println("Couldn't get Internet address: Unknown host"); // Ошибка, однако
}.
try { socket = new Datagramsocket();
} catch (lOException e) {
System.out.println("Couldn't create new Datagramsocket"); return;
}
GridBagLayout gridBag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints(); setLayout(gridBag);
Label 11 = new Label("Quote of the Moment:", Label.CENTER);
c.anchor = GridBagConstraints.SOUTH;
c.gridwidth = GridBagConstraints.REMAINDER;
gridBag.setconstraints(11, c) ;
add (11) ;
display = new Label("(no quote received yet)", Label.CENTER);
c.anchor = GridBagConstraints.NORTH;
c.weightx = 1.0;
c.fill = GridBagConstraints.HORIZONTAL;: gridBag.setconstraints(display, c) ;
add(display);
Label 12 = new Label("Enter the port (on host " + host + ") to send the request to:", Label.RIGHT);
c.anchor = GridBagConstraints.SOUTH;
c.gridwidth = 1;
c.weightx = 0.0;
c.weighty = 1.0;
c.fill = GridBagConstraints.NONE;
gridBag.setconstraints(12, c) ;
add(12);
portField = new TextField(6);
gridBag.setconstraints(portField, c); add(portField);
Button button = new Button("Send");
gridBag.setconstraints(button, c); add(button);
portField.addActionListener(this);
button.addActionListener(this);
public Insets getlnsets() { return new Insets(4,4,5,5);
public void paint(Graphics g) {
Dimension d = getSizeO;
Color bg = getBackground() ;
g.setColor(bg);
g.draw3DRect(0, 0, d.width — 1, 'd.height — 1, true); g.draw3DRect(3, 3, d.width — 7, d.height — 7, false);
void dolt(int port) { DatagramPacket packet;
byte[] sendBuf = new byte[256];
packet = new DatagramPacket(sendBuf, 256, address, port);
try { // Запрос послать . if (DEBUG) {
System.out.printin("Applet about to send packet to address + address + " at port " + port);
socket.send(packet);
if (DEBUG) {
System.out.printin("Applet sent packet.");
} catch (lOException e) (
System.out.printin("Applet socket.send failed:");
e.printStackTrace (); return;
packet = new DatagramPacket(sendBuf, 256);
try ( // Ответ получить if (DEBUG) {
System.out.printin("Applet about to call socket.receive()." }
socket.receive(packet);
if (DEBUG) {
System.out.printin("Applet returned from socket.receive()."
} catch (lOException e) (
System.out.printin("Applet socket.receive failed:");
e.printStackTrace (); return;
}
String received = new String(packet.getData());
if (DEBUG) (
System.out.printin("Quote of the Moment: " + received);
}
display.setText(received);
public void actionPerformed(ActionEvent event) { int port;
try (
port = Integer.parseInt(portField.getText());
dolt(port);
} catch (NumberFormatException е) { // Ошибка, однако }
}
Текстовый файл, содержащий цитаты, one-liners.txt (библиотека цитат).
| Файл one-liners.txt
Life is wonderful. Without it we'd all be dead.
Daddy, why doesn’t this magnet pick up this floppy disk? Give me ambiguity or give me something else.
I.R.S.: We've got what it takes to take what you've got! We are born naked, wet and hungry. Then things get worse. Make it idiot proof and someone will make a better idiot. He who laughs last thinks slowest!'
Always remember you're unique, just like everyone else. "More hay, Trigger?" "No thanks, Roy, I'm stuffed!" A flashlight is a case for holding dead batteries. Lottery: A tax on people who are bad at math. Error, no keyboard — press Fl to continue.
There's too much blood in my caffeine system.
Artificial Intelligence usually beats real stupidity. Hard work has a future payoff. Laziness pays off now. "Very funny, Scotty. Now beam down my clothes." Puritanism: The haunting fear that someone, somewhere may be happy. Consciousness: that annoying time between naps.
Don't take life too seriously, you won't get out alive. I don't suffer from insanity. I enjoy every minute of it. Better to understand a little than to misunderstand a lot. The gene pool could use a little chlorine.' When there's a will, I want to be in it.
Okay, who put a "stop payment" on my reality check? We have enough youth, how about a fountain of SMART? Programming is an art form that fights back. "Daddy, what does FORMATTING DRIVE C mean?"
All wiyht. Rho sritched mg kegtops awound? My mail reader can beat up your mail reader.
Never forget: 2+2=5 for extremely large values of 2.
Nobody has ever, ever, EVER learned all of WordPerfect. To define recursion, we must first define recursion.
Good programming is 99% sweat and 1% coffee.
Home is where you hang your @
The E-mail of the species is more deadly than the mail. A journey of a thousand sites begins with a single click. You can't teach a new mouse old clicks.
Great groups from little icons grow.
Speak softly and carry a cellular phone. C:\ is the root of all directories.
Don't put all your hypes in one home page.
Pentium wise; pen and paper foolish.
The modem is the message.
Too many clicks spoil the browse.
The geek shall inherit the earth. A chat has nine lives.
Don't byte off more than you can view.
Fax is stranger than fiction.
What boots up must come down.
Windows will never cease. (ed. oh sure...) In Gates we trust. (ed. yeah right....) Virtual reality is its own reward.
Modulation in all things.
A user and his leisure time are soon parted.
There's no place like http://www.home.com
Know what to expect before you connect.
Oh, what a tangled website we weave when first we practice.
Speed thrills.•
Give a man a fish and you feed him for a day; teach him to use the Net and he won't bother you for weeks.■
Компилируем классы сервера и клиентского апплета: QuoteServeThread.java, QuoteServer.java и QuoteClientApplet.java (рис. 6.15).
с* Командная строка ИИ £31
6
Е:\jdkl.3.l\bin>javac QuoteServerThread.javaЦ
E:\jdk1.3.l\bin>javac QuoteServer.java■
QuoteServer.java:7: cannot resolve symbol■
symbol : class QuoteServerThread■
location: class QuoteServer■
new QuoteServerThread!).start();■
1 error■
E:\jdk1.3.l\bin>set classpath=ZclasspathZ;e:\jdkl.3.l\binИ
E: \ jdk 1.3. 1ЛЫn> javac QuoteServer. javaИ
E:\jdk1.3.l\bin>javac Quoted i ent Applet . java■
E:\jdkl.3.l\bin>■
It! :: :: : - — Z -—J' J
Рис. 6.15. Компилируем классы сервера и клиентского апплета
Теперь нам необходимо подготовить HTML-страницу. Рассмотрим файл networking.html.
■ Файл networking.html
<нтмь>
<TITLE>
QuoteClientApplet
</TITLE>
<BODY>
<APPLET CODE=QuoteClientApplet.class WIDTH=500 HEIGHT=100>
</APPLET>
</BODY>
</HTML>
Загружаем документ networking.html, появляется окно апплета, в которое нужно ввести номер порта. Обратившись к серверу с указанием этого порта, мы получим цитату. Чтобы узнать номер порта, необходимо запустить сервер (рис. 6.16). Сервер запущен, номер порта известен. Вводим этот номер в окно апплета.(рис. 6.17). Апплет получает цитату.
Рис. 6.16. Стартуем сервер
Рис. 6.17. Апплет связывается с сервером
Примеры апплетов
Апплеты предоставляют богатый выбор возможностей обогащения клиентского HTML-документа, ведь при создании апплетов используется мощный язык Java. Апплет можно создать один раз и использовать его сколь угодно часто и много. Существуют библиотеки апплетов. Сейчас мы рассмотрим несколько примеров полезных в работе апплетов.
Некоторые примеры апплетов принадлежат компании Sun. При использовании таких апплетов следует выполнять условия их распространения, предъявляемые этой компанией:
* Copyright (с) Sun Microsystems, Inc. All Rights Reserved.
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
* modify and redistribute this software in source and binary code form,
* provided that i) this copyright notice and license appear on all copies of
* the software; and ii) Licensee does not utilize the software in a manner
* which is disparaging to Sun.
* This software is provided "AS IS,” without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
* This software is not designed or intended for use in on-line control of
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
* the design, construction, operation or maintenance of any nuclear
* facility. Licensee represents and warrants that it will not use or
* redistribute the Software for such purposes.
*/
График
Этот апплет служит для отображения графиков на клиентской странице. Параметры могут быть изменены в HTML-коде страницы:
<HTML> ■'
<head>
<Ь1Ь1е>график</Ь1Ь1е>
</head>
<body>
<Ы>График</Ы>
<hr>
<Р>График горизонтально<Р>
<applet codebase="." code="Chart.class" width=351 height=115>
<param name=c2_color value="green">
<param name=c2_label value="MeTKa 2">
<param name=cl_style value="striped">
<param name=c4 value="12">
<param name=c3 value="17">
<param name=c2 value="40">
<param name=c4_color value="yellow">
<param name=cl value="10">
<param name=c4_label value="MeTKa4">
<param name=title value-''Подпись под графиком">
<param name=c3_style value="striped">
<param name=columns value="4">
<param name=cl_color value="blue">
<param name=cl_label value="MeTKa 1">
<param name=c3_color value="magenta">
<param name=c3_label value="MeTKa 3">
<param name=c2_style value="solid">
<param name=orientation value="horizontal">
<param name=c4_style value="solid">
<param name=scale value="5">•
alt="Your browser understands the <APPLET> tag but isn't running the applet, for some reason."
Your browser is completely ignoring the <APPLET> tag!
</applet>
<hr>
<Р>График вертикально<Р>
<applet codebase="." code="Chart.class" width=251 height=275>
<param name=c2_color value="green">
<param name=c2_label value="MeTKa 2">
<param name=cl_style value="striped">
<param name=c4 value="12">
<param name=c3 value="17">
<param name=c2 value="40">
<param name=c4_color value="yellow">
<param name=cl value="10">
<param name=c4_label value="MeTKa 4">
<param name=title уа1ие="Подпись под графиком">
<param name=c3_style value="striped">
<param name=columns value="4">
<param name=cl_color value="blue">
<param name=cl_label value="MeTKa 1">
<param name=c3_color value="magenta">
<param name=c3_label value="MeTKa 3">
<param name=c2_style value="solid">
<param name=orientation value="vertical">
<param name=c4_style value="solid">
<param name=scale value="5">
alt="Your browser understands the <APPLET>
tag but isn't running the applet, for some reason."
Your browser is completely ignoring the <APPLET> tag!
</applet>
<hr>
</body>
</HTML>
В окне браузера график выглядит многоцветным (рис. 6.18).
Рис. 6.18. Апплет для отображения графиков
Код апплета приведен ниже:
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.io.*;
import java.lang.*;
import java.net.URL;
public class Chart extends java.applet.Applet { static final int VERTICAL = 0;
static final int HORIZONTAL = 1;
static final int SOLID = 0;
static final int STRIPED = 1;
int
orientation-
String
title;
Font
titleFont;
FontMetricstitleFontMetrics;
int
titleHeight = 15;
int
columns;
int
values[];
Object Object int
colors[]; labels[]; styles[];
int
scale = 10;
int
maxLabelWidth = 0;
int
barwidth;
int
barSpacing = 10;
int
max = 0;-
public synchronized void init() (
String rs;
titleFont = new java.awt.Font("Courier", Font.BOLD, 12); titleFontMetrics = getFontMetrics(titleFont);
title = getParameter("title") ;
if (title == null) (
title = "Chart";
}
rs = getParameter("columns");
if (rs == null) ( columns = 5;
} else (
columns = Integer.parselnt(rs) ;
}
rs = getParameter("scale") ;
if (rs == null) { scale = 10;
} else ( scale = Integer.parselnt(rs);
}
rs = getParameter("orientation");
if (rs == null) { orientation = VERTICAL;
} else if (rs.toLowerCase().equals("vertical")) { orientation = VERTICAL;
} else if (rs.toLowerCase().equals("horizontal")) { orientation = HORIZONTAL;
} else { orientation = VERTICAL;
}
values = new int[columns];
colors = new Color[columns];
labels.= new String[columns];
styles = new int[columns];
for (int i=0; i < columns; i++) {
// разбор значений столбца
rs = getParameter("С" + (i+1)) ;
if (rs != null) {
try {
values[i] = Integer.parselnt(rs) ;
} catch (NumberFormatException e) { values[i] = 0;
}
if (values[i] > max) { max = values[i];
}
// разбор меток столбца
rs = getParameter("C" + (i+1) + "„label");
labels[i] = (rs == null) ? ”” : rs;
maxLabelWidth =
Math.max(titleFontMetrics.stringwidth((String)(labels[i])), maxLabelWidth);
// разбор стилей панели
rs = getParameter("С" + (i+1) + "„style");
if (rs == null || rs.toLowerCase().equals("solid")) { styles[i] = SOLID;
} else if (rs.toLowerCase().equals("striped")) { styles[i] = STRIPED;
} else {
styles[i] = SOLID;
}
// разбор значений цветов
rs = getParameter("С" + (i+1) + "„color");
if (rs 1= null) {
if (rs.equals("red")) {
colors[i] = Color.red;
} else if (rs.equals("green")) { colors[i] = Color.green;
} else if (rs.equals("blue")) { colors[i] = Color.blue;
} else if (rs.equals("pink")) { colors[i] = Color.pink;
} else if (rs.equals("orange")) { colors[i] = Color.orange;
} else if (rs.equals("magenta")) { colors[i] = Color.magenta;
} else if (rs.equals("cyan")) { colors[i] = Color.cyan;
} else if (rs.equals("white")) { colors[i] = Color.white;
} else if (rs.equals("yellow")) { colors[i] = Color.yellow;
} else if (rs.equals("gray")) ( colors[i] = Color.gray;
} else if (rs.equals("darkGray")) ( colors[i] = Color.darkGray;
) else { colors[i] = Color.gray;
}
} else { colors[i] = Color.gray;
}
}
switch (orientation) {
case VERTICAL:
default:
barWidth = maxLabelWidth;
resize(Math.max(columns * (barWidth + barSpacing), titleFontMetrics.stringwidth(title)) + titleFont.getSize() + 5, (max * scale) + (2 * titleFont.getSize()) + 5 + titleFont.getSize () ) ;
break;
case HORIZONTAL:
barWidth = titleFont.getSize();
resize(Math.max((max * scale) +
titleFontMetrics.stringwidth("" + max),titleFontMetrics.stringwidth(title)) +maxLabelWidth + 5,(columns * (barWidth + barSpacing)) +titleFont.getSize () + 10);
break;
public synchronized void paint(Graphics g) { int i, j;
int ex, cy;
char 1[] = new char[l);
// вывод заголовка
g.setColor(Color.black) ;
= titleFontMetrics.stringwidth(title);
g. setFont(titleFont);
g.drawstring(title, Math.max((getsize().width — i)/2, 0), getsize().height — titleFontMetrics.getDescent());
for (i=0; i < columns; i++) { switch (orientation) {
case VERTICAL: default:
// выбор следующей координаты X для отображения метки // для этого используется значение getSizeO .width.
ex = (Math.max((barWidth + barSpacing),maxLabelWidth) * i) + barSpacing;
// отображение по центру панели
ex += Math.max((getsize().width — (columns * (barWidth + (2 * barSpacing))))/2,0);
// выбор следующей координаты Y с использованием значения
// getSizeO .height.
су = getsize().height — (values[i] * scale) — 1 — (2 * titleFont.getsize());
// рисуем метку g.setColor(Color.black); g.drawstring((String)labels[i], ex, getsize().height — titleFont.getsize() — titleFontMetrics.getDescent());
// рисуем тень
if (colors[i] == Color.black) { g.setColor(Color.gray);
}
g.fillRect(ex +5, cy — 3, barWidth, (values[i] * scale)); // рисуем панель с заданным цветом g.setcolor((Color)(colors[i])); switch (styles[i]) { case SOLID: default:
g.fillRect(ex, cy, barWidth, (values[i] * scale)); break;
case STRIPED:
int steps = (values[i] * scale) / 2; int ys;
for (j=0; j < steps; j++) ( ys = cy + (2 * j);
g.drawLine(ex, ys, ex + barWidth, ys);
}
} break;
}
g.drawstring("" + values[i], ex,
cy — titleFontMetrics.getDescent()); break;
case HORIZONTAL:
// задаем координату Y
cy = ((barWidth + barSpacing) * i) + barspacing;
// задаем координату X (значение getSize().width) // для самой широкой метки сх = maxLabelWidth + 1;
сх += Math.max((getSize().width — (maxLabelWidth + 1 + titleFontMetrics.stringwidth("" +
max) +
(max * scale))) / 2, 0);
// рисуем метку с тенью g.setColor(Color.black);
g.drawstring((String)labels[i], ex — maxLabelWidth — 1, cy + titleFontMetrics.getAscent());
if (colors[i] = Color.black) ( g.setColor(Color.gray);
}
g.fillRect(ex + 3,
cy + 5, (values[i] * scale), barWidth);
// рисуем панель заданным цветом
g.setcolor((Color)(colors[i])) ; switch (styles[i]) { case SOLID: default:
g.fillRect(ex, cy, (values[i] * scale), barWidth);
break;
case STRIPED:
int steps = (values[i] * scale) / 2; int ys;
for (j=0; j < steps; j++) {
ys = ex + (2 * j);
g.drawLine(ys, cy, ys, cy + barWidth);
break;
g.drawstring("" + values[i],
ex + (values[i] * scale) + 3,
cy + titleFontMetrics.getAscentO);
break;
}
public String getAppletlnfo() {
return "Title: Bar Chart \nAuthor: Sami Shaio \nA simple bar chart demo."; }
public String[][] getParameterlnfo() {
String[][] info = {
{"title", "string", "The title of bar graph. Default is 'Chart'"}, {"scale", "int", "The scale of the bar graph. Default is 10."}, {"columns", "int", "The number of columns/rows. Default is 5."}, {"orientation", "{VERTICAL, HORIZONTAL}", "The orienation of the bar graph. Default is VERTICAL."},
("с#", "int", "Subsitute a number for #. The value/size of bar #. Default is 0."},
("c#_label", "string", "The label for bar #. Default is no label."},
("c#_style", "(SOLID, STRIPED}", "The style of bar #. Default is SOLID."},
("c#_color", "(RED, GREEN, BLUE, PINK, ORANGE, MAGENTA, CYAN, WHITE, YELLOW, GRAY, DARKGRAY}", "The color of bar #. Default is GRAY."}
};
return info;
}■
}■
Часы
Этот апплет имеет три параметра:
<applet code="Clock2.class" width=170 height=150>
<param name=bgcolor value="000000">
<param name=fgcolorl value="ff0000">
<param name=fgcolor2 value="ffOOff">
</applet>
В качестве параметров задается цвет фона, первый основной цвет — цвет часовой и минутной стрелок, второй основной цвет — цвет цифр и цвет секундной стрелки. Часы "живые", они идут, отсчитывая секунду за секундой (рис. 6.19).
Рис. 6.19. В действительности часы идут
Код апплета приводится ниже:
import java.util.*;
import java.awt.*;
import java.applet.*;
import java.text.*;
public class Clock2 extends Applet implements Runnable {
Thread timer;// Поток отображения часов
int lastxs, lastys, lastxm,
lastym, lastxh, lastyh; // Массивы для рисования стрелок SimpleDateFormat formatter; // Формат даты String lastdate;// Строка отображения даты
Font clockFaceFont; // Шрифт отображения цифр на часах Date currentDate;// Дата
Color handColor;// Цвет минутной и часовой стрелок
Color numbercolor;// Цвет цифр и секундной стрелки
public void init() {
int x,y;
lastxs = lastys = lastxm = lastym = lastxh = lastyh = 0;
formatter = new SimpleDateFormat ("EEE МММ dd hh:mm:ss yyyy", Locale. getDefault());
currentDate = new Date();
lastdate = formatter.format(currentDate);
clockFaceFont = new Font("Serif", Font.PLAIN, 14);
handColor = Color.blue;
numberColor = Color.darkGray;
try { '
setBackground(new
Color(Integer.parselnt(getParameter("bgcolor"),16)));
) catch (Exception E) { )
try {
handColor = new
Color(Integer.parselnt(getParameter("fgcolorl"),16));
} catch (Exception E) { )
try {
numberColor = new
Color(Integer.parselnt(getParameter("fgcolor2"),16));
) catch (Exception E) { )
resize(300,300);// Задаем размер часов
}
// Отображение точек в пределах 45 градусов, затем повторения
public void plotpoints(int x0, int yO, int x, int y, Graphics g) {
g.drawLine(xO+x,y0+y,x0+x,yO+y) ;
g.drawLine(xO+y,y0+x,x0+y,yO+x);
g.drawLine(xO+y,yO-х,xO+y,yO-х);
g.drawLine(xO+x,yO-у,xO+x,yO-y);
g.drawLine(xO-x,y0-y,x0-x,yO-y);
g.drawLine(x0-y,y0-x,x0-y,yO-х);
g.drawLine(xO-y,yO+x,xO-y,yO+x);
g.drawLine(xO-x,y0+y,x0-x,yO+y); }
public void circle(int xO, int yO, int r, Graphics g) { int x,y;
float d;
x=0;
y=r; '
d=5/4-r;
plotpoints(xO,yO,x,y,g);
while (y>x){ if (d<0) {
d=d+2*x+3;
x++; } else (
d=d+2*(x-y)+5;
x++; y--; } plotpoints(xO,yO,x,y,g); } } // Рисование — основная часть программы public void paint(Graphics g) {
int xh, yh, xm, ут, xs, ys, s = 0, m = 10, h = 10, xcenter, ycenter;
String today;
currentDate = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("s",Locale.getDefault());
try {
s = Integer.parselnt(formatter.format(currentDate));
} catch (NumberFormatException n) { s = 0;
}
formatter.applyPattern("m"); try { m = Integer.parselnt(formatter.format(currentDate));
} catch (NumberFormatException n) { m = 10;
}
formatter.applyPattern("h"); try {
h = Integer.parselnt(formatter.format(currentDate));
} catch (NumberFormatException n) { h = 10;
}
formatter.applyPattern("EEE МММ dd HH:mm:ss yyyy");
today = formatter.format(currentDate);
xcenter=80;
ycenter=55;
xs =(int)(Math.cos(s*3.14f/30—3.14f/2)*45+xcenter);
ys =(int)(Math.sin(s*3.14f/30—3.14f/2)*45+ycenter);
xm =(int)(Math.cos(m*3.14f/30—3.14f/2)*40+xcenter);
ym =(int)(Math.sin(m*3.14f/30—3.14f/2)*40+ycenter);
xh = (int)(Math.cos((h*30 + m/2) * 3.14f/180 — 3.14f/2) * 30 + xcenter);
yh = (int)(Math.sin((h*30 + m/2) * 3.14f/180 — 3.14f/2) * 30 + ycenter); // Рисование окружности и цифр g.setFont(clockFaceFont);■
g.setColor(handcolor); circle(xcenter,ycenter,50,g);
g.setColor(numbercolor);
g.drawstring("9",xcenter-45,ycenter+3);
g.drawstring("3",xcenter+40,ycenter+3);
g.drawstring("12",xcenter-5,ycenter-37);
g.drawstring("6",xcenter-3,ycenter+45);
// Стирание и перерисовка
g.setColor(getBackground());
if (xs != lastxs |J ys != lastys) (
g.drawLine(xcenter, ycenter, lastxs, lastys); g.drawstring(lastdate, 5, 125);
if (xm != lastxm || ym ! = lastym) (
g.drawLine(xcenter, ycenter-1, lastxm, lastym);
g.drawLine(xcenter-1, ycenter, lastxm, lastym); } if (xh != lastxh | | yh != lastyh) (
g,drawLine(xcenter, ycenter-1, lastxh, lastyh);
g.drawLine(xcenter-1, ycenter, lastxh, lastyh); } g.setColor(numbercolor);
g.drawstring("", 5, 125);
g.drawstring(today, 5, 125);
g.drawLine(xcenter, ycenter, xs, ys);
g.setColor(handColor) ;
g.drawLine(xcenter, ycenter-1, xm, ym) ;
g.drawLine(xcenter-1, ycenter, xm, ym) ;
g.drawLine(xcenter, ycenter-1, xh, yh);
g.drawLine(xcenter-1, ycenter, xh, yh) ; lastxs=xs; lastys=ys; lastxm=xm; lastym=ym; lastxh=xh; lastyh=yh;
lastdate = today; currentDate=null;
public void start() (
timer = new Thread(this); timer.start();
public void stop() { timer = null;
public void run() {
Thread me = Thread.currentThread();
while (timer == me) ( try (
Thread.currentThread().sleep(100);
} catch (InterruptedException e) ( }
repaint();
} }
public void update(Graphics g) ( paint(g);
}
public String getAppletlnfo() ( return "Title: A Clock \n";
}
public String{][] getParameterlnfo() (
String[]{] info = (
{"bgcolor", "hexadecimal RGB number", "The background color. Default is the color of your browser."},
{"fgcolorl", "hexadecimal RGB number", "The color of the hands and dial. Default is blue."},
("fgcolor2", "hexadecimal RGB number", "The color of the seconds hand and numbers. Default is dark gray."}
};
return info;
} }
Простой график
Это очень простой, но не менее полезный апплет. С его помощью можно выводить график прямо в окно браузера. Java-код выглядит следующим образом:
import java.awt.Graphics;
public class GraphApplet extends java.applet.Applet (
double f(double x) {
return (Math.cos(x/5) + Math.sin(x/7) + 2) * getSize().height / 4; }
public void paint(Graphics g) {
for (int x = 0 ; x < getSize().width ; x++) { g.drawLine(x, (int)f(x), x + 1, (int)f(x + 1));
} } public String getAppletlnfo() { return "Draws a sin graph."; }
}
В окне браузера мы видим графики фукнций (рис. 6.20).
Рис. 6.20. Апплет для отображения графиков аналитических функций
Легковесная таблица, заполняемая пользователем в браузере
Этот апплет замечателен тем, что использует средства пакета awt для создания заполняемой пользователем таблицы. Апплет не требует больших системных ресурсов, как при использовании пакета swing. Текст апплета:
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.lang.*;
import java.net.*;
public class Spreadsheet
extends Applet.
implements MouseListener, KeyListener {
String
Font
title; titleFont;
Color
cellColor;
Color
inputcolor;
int
cellwidth = 100;
int
cellHeight = 15;'
int
titleHeight = 15;
int
rowLabelWidth = 15;
Font
inputFont;
boolean
isStopped = false;
boolean
fullUpdate = true;
int
rows ;
int
columns;
int
currentKey = -1;
int
selectedRow = -1;
int
selectedColumn = -1;
Spreadsheetinput inputArea;
Cell
cells [][];
Cell
current = null;
public synchronized void init() {
String rs;
cellColor = Color.white;
inputcolor = new Color(100, 100, 225);
inputFont = new Font("Courier", Font.PLAIN, 10); titleFont = new Font("Courier", Font.BOLD, 12); title = getParameter("title"); if (title == null) ( title = "Spreadsheet";
}
rs = getParameter("rows");
if (rs == null) { rows = 9;
} else { rows = Integer.parselnt(rs);
}
rs = getParameter("columns");
if (rs == null) { columns = 5;
} else { columns = Integer.parselnt(rs);
}
cells = new Cell[rows][columns];
char 1[] = new char[l];
for (int i=0; i < rows; i++) {
for (int j=0; j < columns; j++) {■
cells [i] [j] = new Cell(this, Color.lightGray, Color.black, cellColor, cellwidth — 2, cellHeight — 2) ;
l[0] = (char)((int)'a' + j);
rs = getParameter("" + new String(l) + (i+1)); if (rs != null) {
cells[i][ j ].setUnparsedValue(rs); }
}
}
Dimension d = getSizef);
inputArea = new SpreadsheetInput(null, this, d.width — 2, cellHeight — 1, inputColor, Color.white); resize(columns * cellwidth + rowLabelWidth,
(rows + 3) * cellHeight + titleHeight);.
addMouseListener(this); addKeyListener(this); } public void setCurrentValue(float val) { if (selectedRow == -1 || selectedColumn == -1) { return; } cells[selectedRow][selectedColumn].setvalue(val); repaint(); } public void stop() { isStopped = true; } public void start() { isStopped = false; } public void destroy() ( for (int i=0; i < rows; i++) ( for (int j=0; j < columns; j++) ( if (cells[i][j].type == Cell.URL) { cells[i][j].updaterThread.stop(); } } } }
public void setCurrentValue(int type, String val) { if (selectedRow == -1 || selectedColumn == -1) ( return;
}
cells[selectedRow][selectedColumn].setvalue(type, val) ; repaint();
public void update(Graphics g) {
if (1 fullUpdate) {
int ex, cy;
g.setFont(titleFont);
for (int i=0; i < rows; i++) {
for (int j=0; j < columns; j++) {
if (cells[i][j].needRedisplay) {
ex = (j * cellwidth) + 2 + rowLabelWidth;
cy = ( (i+1) * cellHeight) + 2 + titleHeight;
cells [i] [j].paint(g, ex, cy);
}
}
}
} else {
paint(g);
fullUpdate = false;
}
}
public void recalculate() {
int i, j;
for (i=0; i < rows; i++) {
for (j=0; j < columns; j++) {
if (cells[i][j) 1= null && cells[i][j].type == Cell.FORMULA) { cells[i][j].setRawValue(evaluateFormula(cells[i][j].parseRoot)); cells[i][j].needRedisplay = true;
}
}
}
repaint();
}
public float evaluateFormula(Node n) {
float val = O.Of;
if (n == null) {
return val;
)
switch (n.type) ( case Node.OP:
val = evaluateFormula(n.left);
switch (n.op) ( case '+':
val += evaluateFormula(n.right); break;
case '* ' :
val *= evaluateFormula(n.right); break;
case '-':
val -= evaluateFormula(n.right);
break;
case '/':
val /= evaluateFormula(n.right); break;
break;
case Node.VALUE: return n.value;
case Node.CELL: if (n == null) ( ) else (
if (cells[n.row][n.column] == null) ( ) else (
return cells[n.row][n.column].value; )
) )
return val; )
public synchronized void paint(Graphics g) ( int i, j;
int ex, cy;
char 1[] = new char[l];
Dimension d = getSizeO;
g.setFont(titleFont);
i = g.getFontMetrics().stringwidth(title);
g.drawstring((title == null) ? "Spreadsheet" : title, (d.width — i) /2, 12);
g.setColor(inputColor);
g.fillRect(0, cellHeight, d.width, cellHeight); g.setFont(titleFont);
for (i=0; i < rows+1; i++) {
cy = (i+2) * cellHeight;
g.setColor(getBackground());
g.draw3DRect(0, cy, d.width, 2, true);
if (i < rows) {
g.setColor(Color.red);
g.drawstring("" + (i+1), 2, cy + 12); }
}
g.setColor(Color.red);
cy = (rows+3) * cellHeight + (cellHeight / 2);
for (i=0; i < columns; i++) {
ex = i * cellwidth;
g.setColor(getBackground());
g.draw3DRect(ex + rowLabelWidth,
* cellHeight, 1, d.height, true);
if (i < columns) {
g.setColor(Color.red);
l[0] = (char)((int)'A' + i);
g.drawstring(new String(1),
ex + rowLabelWidth + (cellwidth / 2), cy) ;
} ■
for (i=0; i < rows; i++) {
for (j=0; j < columns; j++) {
ex = (j * cellwidth) + 2 + rowLabelWidth;
cy = ( (1+1) * cellHeight) + 2 + titleHeight; if (cells[i][j] != null) {
cells [i] [j].paint(g, ex, cy) ;
}
}
}
g.setColor(getBackground());
g.draw3DRect(0, titleHeight, d.width, d.height — titleHeight, false);
inputArea.paint(g, 1, titleHeight + 1);
}
//обработка событий
public void mouseClicked(MouseEvent e) (}
public void mousePressed(MouseEvent e) (
int x = e.getX();
int у = e.getY();
Cell cell;
if (y < (titleHeight + cellHeight)) { selectedRow = -1;
if (y <= titleHeight && current != null) { current.deselect() ;
current = null;
}
e.consume ();
}
if (x < rowLabelWidth) { selectedRow = -1;
if (current != null) {
current.deselect() ; current = null;
е. consume () ;
selectedRow = ((у — cellHeight — titleHeight) / cellHeight); selectedColumn = (x — rowLabelWidth) / cellwidth;
if (selectedRow > rows || selectedColumn >= columns) {
selectedRow = -1;
if (current != null) { current.deselect();
current = null; }
} else {
if (selectedRow >= rows) { selectedRow = -1;
if (current 1= null) { current.deselect(); current = null;
}
e.consume();
}
cell = cells[selectedRow][selectedColumn];
inputArea.setText(new String(cell.getPrintString())); if (current 1= null) { current.deselect ();
}
current = cell;
current.select ();
requestFocus();
fullUpdate = true; repaint();
}
e.consume();
}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void keyPressed(KeyEvent e) { }
public void keyTyped(KeyEvent e) {
fullUpdate=true;
InputArea.processKey(e);
e.consume (); }
public void keyReleased(KeyEvent e) {}
public String getAppletlnfo() {
return "Title: Spreadsheet \nAuthor: Sami Shaio \nA simple spread sheet."; }
public String[][] getParameterlnfo() {
String[][] info = {
("title", "string", "The title of the spread sheet. Default is 'Spreadsheet'"}, ("rows", "int", "The number of rows. Default is 9."},
("columns", "int", "The number of columns. Default is 5."} };
return info; }
class CellUpdater extends Thread { Cell target;
Inputstream datastream = null;
StreamTokenizer tokenstream;
public CellUpdater(Cell c) { super("cell updater"); target = c;
public void run() {
try {
datastream = new URL(target.app.getDocumentBase(), target.getValueString()).openStream();
tokenstream = new StreamTokenizer(new BufferedReader (new InputStreamReader(datastream)));
tokenstream.eolIsSignifleant(false);
while (true) {
switch (tokenstream.nextToken()) { case StreamTokenizer,TT_EOF:
datastream.close(); return; default:'
break;
case StreamTokenizer,TT__NUMBER:
target.setTransientValue((float)tokenstream.nval) ;
if (1 target.app.isStopped 4 4 I target.paused) { target.app.repaint ();
} break;
}
try { Thread.sleep (2000);
} catch (InterruptedException e) { break;
} catch (lOException e) { return;
}
class Cell {
public static final int VALUE = 0;
public static final int LABEL = 1;
public static final int URL = 2; public static final int FORMULA = 3;
Node parseRoot;
boolean needRedisplay; boolean selected = false; boolean transientvalue = false;
public int type = Cell.VALUE; Stringvaluestring = "";
Stringprintstring = "v";
float value;
Color bgColor;
Color fgColor;
Color highlightcolor; intwidth;
intheight;
Spreadsheet app; CellUpdater updaterThread; boolean paused = false;'
public Cell(Spreadsheet app,
Color bgColor, Color fgColor, Color highlightcolor, int width, int height) { this.app = app; this.bgColor = bgColor; this.fgColor = fgColor; this.highlightcolor = highlightcolor; this.width = width; this.height = height; needRedisplay = true;
}
public void setRawValue(float f) { valuestring = Float.toString(f) ; value = f;
}
public void setvalue(float f) ( setRawValue(f);
printstring = "v" + valuestring;
type = Cell.VALUE;
paused = false; app.recalculate (); needRedisplay = true; }
public void setTransientValue(float f) ( transientvalue = true; value = f;
needRedisplay = true; app.recalculate();
}
public void setUnparsedValue(String s) ( switch (s.charAt(O)) ( case 'v': setValue(Cell.VALUE, s.substring(1)); break; case 'f': setValue(Cell.FORMULA, s.substring(1)); break; case '1' :
setValue(Cell.LABEL, s.substring (1) ); break; case 'u': setValue(Cell.URL, s.substring(1)); break;
/ *
* Анализируем формулу по следующим правилам синтаксиса:
★ value -> cell * value -> <number>
* op -> '+' | '** I V I '-'
* cell -> <letter><number>
*/
public String parseFormula(String formula, Node node) ( String subformula;
String restFormula; float value; ~ int length = formula.length();
Node left;
Node right; char op;
if (formula — null) ( return null;
}'
subformula = parseValue(formula, node);
if (subformula == null || subformula.length() == 0) ( return null;
}
if (subformula == formula) ( return formula;
}
switch (op = subformula.charAt(0)) { case 0:
return null;
case ') ':
return subformula; case ' +':
case ' * 1 :.
case '-':
case ' / ' :
restFormula = subformula.substring(1);
subformula = parseValue(restFormula, right=new Node()); if (subformula != restFormula) ( left = new Node(node);
node.left = left; node.right = right;
node, op = op;
node.type = Node.OP; return subformula;
} else {■
return formula;
}
default:
return formula;
public String parseValue(String formula, Node node) { char c = formula.charAt(0);
String subformula;
String restFormula;
float value;
int row;
int column;
restFormula = formula;
if (c == ' (') (
restFormula = formula.substring(1);
subformula = parseFormula(restFormula, node);
if (subformula = null ||
subformula.length() == restFormula.length()) { return formula;
} else if (1 (subformula.charAt(0) ==')')) { return formula;
}
restFormula = subformula;
} else if (c >= 'O' && c <= '9') {
int i ;
for (i=0; i < formula.length(); i++) {
c = formula.charAt(i);
if ((c < '0' I| c > '91) && c != '.') { break;
}
}
try {
value = Float.valueOf(formula.substrings, i)).floatvalue();
} catch (NumberFormatException e) ( return formula;
}
node.type = Node.VALUE;
node.value = value;
restFormula = formula.substring(i);
//" rest = " + restFormula);
return restFormula;
} else if (c >= 'A' && c <= 'Z') ( int i ;
column = c — 'A';•
restFormula = formula.substring(1) ;
for (i=0; i < restFormula.length (); i++) ( c = restFormula.charAt(i);
if (c < 'O' || c > 1 91) ( break;
}
}
row = Float.valueOf(restFormula.substring(0, i)).intValue();
node.row = row — 1;
node.column = column;
node.type = Node.CELL;
if (i == restFormula.length()) ( restFormula = null;
} else (
restFormula = restFormula.substring(i);
if (restFormula.charAt(0) == 0) ( return null;
}
}
return restFormula;
}
public void setvalue(int type, String s) ( paused = false;
if (this.type == Cell.URL) (
updaterThread.stop(); updaterThread = null;
valuestring = new String(s);
this.type = type;
needRedisplay = true;
switch (type) {
case Cell.VALUE:
setvalue(Float.valueOf(s).floatvalue());
break;
case Cell.LABEL:
printstring = "1" + valuestring;
break;
case Cell.URL:
printstring = "u” + valuestring;
updaterThread = new CellUpdater(this);
updaterThread.start();
break;
case Cell.FORMULA:
parseFormula(valuestring, parseRoot = new NodeO); printstring = "f" + valuestring;
break;
app.recalculate();
public String getValueString() ( return valuestring;
public String getPrintString() { return printstring;
public void select() { selected = true;
paused = true;
public void deselect() (
selected = falser- paused = false; needRedisplay = true;■
app.repaint();
}
public void paint(Graphics g, int x, int y) { if (selected) {
g.setColor(highlightcolor); ) else {
g.setColor(bgColor); }
g.fillRect(x, y, width — 1, height); if (valuestring != null) ( switch (type) {
case Cell.VALUE:
case Cell.LABEL:
g.setColor(fgColor); break; case Cell.FORMULA: g.setColor(Color.red) ; break; case Cell.URL:
g.setColor(Color.blue); break;
} if (transientvalue)(
g.drawString("" + value, x, у + (height / 2) + 5); } else {
if (valuestring.length() >14) { g.drawstring(valuestring.substring (0, 14), x, у + (height /2) +5) ;
} else { g.drawstring(valuestring, x, у + (height / 2) + 5);
} } } needRedisplay = false;
class Node {
public static final int OP = 0; public static final int VALUE = 1; public static final int CELL = 2;
int type;
Nodeleft;
Noderight;
introw;
intcolumn;
floatvalue;
char op;
public Node O { left = null; right = null; value = 0; row = -1; column = -1; op = 0;
type = Node.VALUE; } public Node(Node n) { left = n.left; right = n.right; value = n.value; row = n.row; column = n.column; op = n.op; type = n.type;
}
public void indent(int ind) { for (int i = 0; i < ind; i++) {
System.out.print(" "); } } public void print(int indentLevel) {
char 1[] = new char[l];
indent(indentLevel);
System.out.println("NODE type=" + type);
indent(indentLevel);
switch (type) (
case Node.VALUE:
System.out.println(" value=" + value);
break;
case Node.CELL:
l[0] = (char)((int)'A' + column);
System.out.printin(" cell=" + new String(l) + (row+1)); break; case Node.OP:
System.out.printin(" op=" + op);
left.print(indentLevel + 3);
right.print(indentLevel + 3) ; break;
}■
}.
}
class InputField (
intmaxchars = 50;
intcursorPos = 0;
Applet app;
Stringsval;
charbuffer!];
intnChars;
intwidth;
intheight;■
ColorbgColor;
ColorfgColor;
public InputField(String initValue, Applet app, int width, int height, Color bgColor, Color fgColor) { this.width = width;
this.height = height;
this.bgColor = bgColor;
this.fgColor = fgColor;
this.app = app;
buffer = new char[maxchars];
nChars = 0;
if (initValue 1= null) {
initValue.getChars(0, initValue.length(), this.buffer, 0); nChars = initValue.length();
}
sval = initValue;
}
public void setText(String val) {
int i;
for (i=0; i < maxchars; i++) {
buffer[i] = 0;
}
sval = new String(val);
if (val = null) {
sval = "";
nChars = 0;
buffer[0] = 0;
} else {
sval.getChars(0, sval.length(), buffer, 0);
nChars = val.length();
sval = new String(buffer);
public String getValueO { return sval;
}
public void paint(Graphics g, int x, int y) { g.setColor(bgColor);
g.fillRect(x, y, width, height);
if (sval != null) {
g.setColor(fgColor);
g.drawstring(sval, x, у + (height / 2) + 3);
public void processKey(KeyEvent e) {
char ch = e.getKeyChar();
if (nChars < maxchars) { switch (ch) { case '\b’: // delete
—nChars;
if (nChars < 0) { nChars = 0;
}
buffer[nChars] = 0;
sval = new String(new String(buffer));
break;
case ' \n' : selected();
break;
default:
if (ch >= '0') {
buffer[nChars++] = ch;
sval = new String(new String(buffer)); }
break;
}
}
app.repaint();
}
public void keyReleased(KeyEvent e) { }
public void selected() { }
}
class Spreadsheetinput extends InputField {
public Spreadsheetinput(String initValue, Spreadsheet app, int width,
int height,
Color bgColor, Color fgColor) { super(initValue, app, width, height, bgColor, fgColor); }
public void selected() ( float f;
switch (sval.charAt(0)) (
case 'v':
String s= sval.substring(1);
try {
int i ;
for (i = 0; i < s.lengthO; i++) ( char c = s.charAt(i); if (c < 'O' H c > '9')
break;
}
s = s.substring(0, i) ;
f = Float.valueOf(s).floatvalue();
((Spreadsheet)app).setCurrentValue(f);
} catch (NumberFormatException e) (
System.out.printin("Not a float: 1" + s + "'"); } break;
case '11:
((Spreadsheet)app).setCurrentValue(Cell.LABEL, sval.substring(l)); break;
case 'u':
((Spreadsheet)app).setCurrentValue(Cell.URL, sval.substring(1)); break;
case 'f':
((Spreadsheet)app).setCurrentValue(Cell.FORMULA, sval.substring(1)); break;
}
Ий вИй вВ окне браузера мы увидим таблицу, в которую можно записывать данные (рис. 6.21).
Ий в
Ий в
^ Таблица - Microsoft Internet Explorer
Filo Edt View Favontes Tools Help
Таблица, которая заполняется
пользователем
Рис. 6.21. Таблица, заполняемая пользователемРис. 6.21. Таблица, заполняемая пользователем
Рис. 6.21. Таблица, заполняемая пользователем
Рис. 6.21. Таблица, заполняемая пользователем
Сервлеты
Предыдущий раздел мы закончили примером сетевого приложения. В нем клиентский апплет связывался с сервером. При работе с апплетами необходимо дополнительное приложение — браузер, который поддерживает работоспособность апплета.
Технология Java позволят создавать небольшие программы, которые исполняются на сервере и называются сервлеты. Объем книги не позволяет подробно остановиться на том, как устроены сервлеты. Для того чтобы сервлет работал, необходимо установить один из серверных пакетов, с которыми может работать Java-апплет. Пакет JSDK (Java Servlet Development Kit) можно найти на сайте http://java.sun.com/products/servlet/archive.html, пакет Tomcat — на сайте http://jakarta.apache.org/tomcat.
Если вы работаете с Windows, то рекомендуем вам установить Windows NT, либо какую-либо иную операционную систему Windows, использующую технологию Windows NT. Получив JSDK, следует установить его (предварительно распаковав) в каком-либо каталоге, назовем его JSDK. После этого, если на машине установлен JDK (J2SDK) и задан к нему путь, можно запустить сервер, который будет работать с сервлетами. Если сервер запущен на порте 8080 (что задано в файле default.cfg) и метод был изменен, то после
того, как сервер стартовал (см. рис. 6.22), можно обратиться к нему по сети или с того же самого компьютера из браузера. Перед запуском сервера необходимо убедиться в том, что установлены необходимые переменные окружения.
Рис. 6.22. Запускаем сервер из пакета Java Servlet Development KitРис. 6.22. Запускаем сервер из пакета Java Servlet Development Kit
Рис. 6.22. Запускаем сервер из пакета Java Servlet Development Kit
Рис. 6.22. Запускаем сервер из пакета Java Servlet Development Kit
◄Back◄Back>. оw wавf'w-*d - ReloadHomeHotistPrntNew>. оw wавf'w-*d - ReloadHomeHotistPrntNewYou're supposed to be up to your elbows In alligators.You're supposed to be up to your elbows In alligators.
◄
Back
◄
Back
>. оw wав
f'w-*d - ReloadHomeHotistPrntNew
>. оw wав
f'w-*d - ReloadHomeHotistPrntNew
You're supposed to be up to your elbows In alligators.
You're supposed to be up to your elbows In alligators.
t Opera -1 Java(tm) Servlet Development Kit ]
Q Me" Edit View Nes*HUon Bookmarks E-m# Messaging News Window Help
^] ^|| ^Oule '»«. h^] ^|| ^Oule '»«. h■ ^^Ю^^'I bttp://focehMt:8080/
^] ^|| ^Oule '»«. h
^] ^|| ^Oule '»«. h
Java™ Servlet Development Kit
Version 2.1
This is the reference implementation of the Java™ Servlet Specification version 2.1 available from Sun Microsystems, Inc.
This is the default page for the server. This page is located in your document root. Your document root is located at:
♦ <install_di r>/webpages
Documentation:
♦ API Documentation
Examples:
Feedback should be directed to: servlet-feedback@sun com
In order to promote the Servlet API and to bring a diverse group of users together to talk about servlets, we've created the servlet-interest list. To subscribe to the mailing list, send a message to listserv@java.sun.com with the following message body:
subscribe servlet-interest <Your Full Name>
Q'ht^^wabikc^com/wwp?.;.! ^http://www.lrv^cu’nai.co...|rpjjava(tm) Servlet Deve.
Рис. 6.23. Обращаемся к серверу пакета Java Servlet Development Kit
Если не установлены серверные пути к серверным классам, то файл startserver.bat (именно к нему необходимо обратиться для запуска сервера) запишет необходимый путь сам. Тем не менее, путь в переменной path должен содержать каталог, в котором расположен установленный пакет JDK. После этого в браузере пишем http://localhost:8080 и получаем ответ сервера (рис. 6.23).
Сервлеты предоставляют механизм выполнения серверных задач. Рассмотрим пример создания простейшего сервлета, напишем файл FirstServlet.java: import javax.servlet.http.*; import javax.servlet.★; import java.io.*;
public class FirstServlet extends HttpServlet { public void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, lOException {
Printwriter out;
String title = "Our First Servlet";
// Тип ответа
response.setContentType("text/html");
// Данные ответа
out = response.getWriter();
out .printIn ("<HTMLXHEADXTITLE>") ;
out.printin(title);
out .printin ("</TITLEX/HEADXBODY>") ;
out.println("<Hl>" + title + "</Hl>");
out.println("<P align=center>This is our first servlet.");
out. print In ("</BODYX/HTML> ") ;
out.close();
)
)'
Скомпилируем класс. Сейчас мы не будем вдаваться в детали конфигурирования и администрирования Web-сервера, входящего в пакет JSDK. Мы используем установки, заданные по умолчанию, будем копировать скомпилированный Java-класс в каталог JSDK\examples\web-inf\servlets. При обращении
к классу сервлета из браузера (в нашем случае это FirstServlet), указываем такой адрес: http://localhost:8080/examples/servlet/FirstServlet. Отметьте, что здесь указан каталог servlet, но не servlets (так сконфигурирован сервер по умолчанию). В окне браузера получаем ответ, сгенерированный сервлетом (рис. 6.24).
НИВНИВOut First Servlet - Microsoft Internet Explorer
НИВ
НИВ
I Fie Edit View Fevailes Tools Help
Address Жhttp://localho$t:8080/example$/$ervlet/Fir$tServlet
Our First Servlet
This is our first servlet.
Рис. 6.24. Браузер получил ответ нашего первого сервлета
Если мы изменим содержимое файла FirstServlet.java, то после того, как новый класс FirstServlet.class будет скомпилирован, необходимо перезапустить сервер, иначе браузер на свой новый запрос получит ответ на запрос от старого класса.
Структура API для создания сервлетов с использованием JSDK
При создании нашего первого сервлета мы использовали такие инструкции: import javax.servlet.http.*; import javax.servlet.*;
API для программирования сервлетов JSDK включает в себя два пакета: javax.servlet.http и javax.servlet.
Пакет javax.servlet.http
Интерфейсы
Рассмотрим интерфейсы пакета javax.servlet.http'.
HttpServletRequest
Интерфейс создан на основе интерфейса ServletRequest. Добавляет объекту, передаваемому сервлету, дополнительные функции;
HttpServletResponse
Содержит описания ответов, которые сервлет посылает клиенту по протоколу HTTP;
HttpSession
Содержит функции для работы с сессиями, т. е. для идентификации пользователя при обращении к различным страницам сайта;
HttpSessionBindingListener
Сообщает объекту о том, связан или не связан он с сессией;
HttpSessionContext
Не используется, начиная с версии 2.1.
Классы
Ниже приведены классы пакета javax.servlet.http'.
Cookie
Создает cookies — небольшие информационные блоки, которые посылаются сервлетом браузеру в HTTP-заголовках. Браузер сохраняет их. Позже cookies могут быть отправлены браузером серверу;
HttpServlet
Абстрактный класс, который можно использовать для создания подкласса при написании HTTP-сервлета. Класс используется для обработки запросов и формирования ответов;
HttpSessionBindingEvent
Класс события посылается объекту, который имплементирует класс HttpSessionBindingListener;
HttpUtils
Содержит коллекцию методов, часто используемых при создании НТТР- сервлетов."
Пакет javax.servlet
Интерфейсы
Рассмотрим интерфейсы пакета javax.servlet.
RequestDispatcher
Определяет объект, получающий запросы от клиента и передающий их различным ресурсам сервера, таким как, например, сервлет, файл HTML, файл JSP и т. п.;
Servlet
Содержит методы, которые должны быть имплементированы во всех сервлетах;
ServletConfig
Определяет объект конфигурации сервлета;
ServletContext
Определяет набор методов, используемых сервлетом для "общения" с машиной, исполняющей сервлет. Например, для получения типа MIME того или иного файла, нахождения других сервлетов, выполняющихся на сервере, записи логов сервлета и т. п.;
ServletRequest
Определяет объект, который используется машиной, выполняющей сервлет для передачи информации о клиентском запросе;
ServletResponse
Посылает данные от сервлета клиенту;
SingleThreadModel
Используется для однопоточных сервлетов, выполняющих только один запрос в каждый конкретный момент времени.
Классы
Классы пакета javax.servlet.
GenericServlet
Определяет сервлет, независимо от протокола;
ServletlnputStream
Создает поток ввода для чтения двоичных данных от клиентского запроса;
ServletOutputStream
Создает поток вывода для вывода двоичных данных от сервлета клиенту.
Иерархия интерфейсов
Рассмотрим иерархию интерфейсов:
java.util.EventListener;
javax.servlet.http.HttpSessionBindingListener;
javax.servlet.http.HttpSession;
javax.servlet.http.HttpSessionContext;
javax.servlet.RequestDispatcher;
javax.servlet.Servlet;
javax.servlet.ServletConfig;
javax.servlet.ServletContext;
javax.servlet.ServletRequest;
javax.servlet.http.HttpServletRequest;
javax.servlet.ServletResponse;
javax.servlet.http.HttpServletResponse;
javax.servlet.SingleThreadModel.
Иерархия классов
Ниже приводится иерархия классов:
class java.lang.Object
class javax.servlet.http.Cookie (implements java.lang.Cloneable)
class java.util.Eventobject (implements java.io.Serializable)
class javax.servlet.http.HttpSessionBindingEvent
class javax.servlet.GenericServlet
(implements java.io.Serial!zable, javax.servlet.Servlet, javax.servlet.ServletConfig)
class javax.servlet.http.HttpServlet (implements java.io.Serializable)
class javax.servlet.http.HttpUtils
class java.io.Inputstream
class javax.servlet.ServletlnputStream
class java.io.Outputstream
class javax.servlet.ServletOutputStream
class java.lang.Throwable (implements java.io.Serializable)
class java.lang.Exception
class javax.servlet.ServletException
class javax.servlet.UnavailableException
Как создавать апплет
Ответ может быть весьма прост: возьмите подходящий пример, измените в нем все, что вас не устраивает. Далее мы рассмотрим некоторые примеры, в которых используются наиболее часто встречающиеся при написании апплетов методы.
Работа с Cookeis
Рассмотрим стандартный пример по работе с Cookies (Cookie 1.java): import java.io.*; import java.text.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Cookiel extends HttpServlet {
ResourceBundle rb = ResourceBundle.getBundle("Localstrings");
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws lOException, ServletException {
response.setContentType("text/html");
Printwriter out = response.getWriter();
out.println("<html>");
out.println("<body>"); out.println("<head>");
String title = rb.getString("cookies.title"); out.println("<title>" + title + "</title>"); out.println("</head>"); out.println("<body>");
out.println("<h3>" + title + "</h3>");
Cookie[] cookies = request.getCookies(); if (cookies.length > 0) (
out.printin(rb.getString("cookies.cookies") + "<br>");
for (int i = 0; i < cookies.length; i++) (
Cookie cookie = cookies[i];
out.print("Cookie Name: " + cookie.getName() + "<br>");
out.println(" Cookie Value: " + cookie.getValue() + "<br><br>");
}
} else (
out.println(rb.getString("cookies.no-cookies"));
}
String cookieName = request.getParameter("cookiename");
String cookieValue = request.getParameter("cookievalue");
if (cookieName ! = null && cookieValue != null) {
Cookie cookie = new Cookie(cookieName, cookieValue);
response.addCookie(cookie);
out.printin("<P>");
out.printin(rb.getString("cookies.set") + "<br>");
out.print (rb.getStringfcookies.name") + " " + cookieName + "<br>");
out.print(rb.getStringfcookies.value") + " " + cookieValue); }
out.println("<P>");
out.printin(rb.getString("cookies.make-cookie") + "<br>");
out.print("<form action=\"");
out.printin("CookieExampleV method=POST>");
out.print(rb.getString("cookies.name") + " ");
out.println("<input type=text length=20 name=cookiename><br>");
out.print(rb.getString("cookies.value") + " ");
out.println("<input type=text length=20 name=cookievaluexbr>"); out.printin("<input type=submit></form>");
out.printin("</body>");
out.println("</html>");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws lOException, ServletException
{
doGet(request, response);
} } Обратимся к сервлету из браузера (рис. 6.25). Мы узнаем, какие Cookies заданы в браузере.
3 Cookies F sample •• Microsoft Internet I xplotei[ f Jt-f
Address |5f http://localhost:80^etop^So j-lw«’^
; Cookies Example
; Your browser is sending the following cookies:■
: Cookie Name: ScriptLanguagePreference^
; Cookie Value: JScript
: Cookie Name: Componentpreference.
i Cookie Value: VB5
: Create a cookie to send to your browser
■ Name: |i
i Value: |I
:Submit Query |_
Рис. 6.25. Работаем c Cookies
Полученные от клиентского браузера Cookies разбираются в следующем фрагменте Java-кода:
Cookie[] cookies = request.getCookies();
if (cookies.length > 0) {
out.printin(rb.getString("cookies.cookies") + "<br>");
for (int i = 0; i < cookies.length; i++) (
Cookie cookie = cookies[i];
out.print("Cookie Name: " + cookie.getName() + "<br>");
out.println(" Cookie Value: " + cookie.getValue() + "<brxbr>") ;
)
Этот же пример полезен для того, чтобы уяснить способы обработки HTML-форм. Соответствующие строки Java-кода выглядят так:
String cookieName = request.getParameter("cookiename");
String cookieValue = request.getParameter("cookievalue");
В скобках в качестве параметров метода getParameter указаны имена элементов <input> в HTML-форме. Здесь форма посылается с использованием метода get, поэтому в нашем примере мы переопределяем метод doGet. Если форма посылается методом post, необходимо переопределить метод doPost Класса HttpServlet.
Чтение HTTP-заголовков
В предыдущем примере мы рассматривали способ работы с Cookies. Сейчас мы будем читать все HTTP-заголовки, передаваемые сервлету (класс Headerl): import java.io.*;
import java.text.*;
import java.util.*;
import javax.servlet. *;
import javax.servlet.http. *;
public class Headerl extends HttpServlet {
ResourceBundle rb = ResourceBundle.getBundle("Localstrings");
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws lOException, ServletException
(
response.setContentType("text/html");
Printwriter out = response.getWriter();
out.printin("<html>");
out.println("<body bgcolor=\"white\">");
out.printIn("<head>");
String title = rb.getString("requestheader.title"); out.printin("<title>" + title + "</title>"); out.printin("</head>"); out.println("<body>");
out.printin("<h3>" + title + "</h3>");
out.printin("<table border=0>");'
Enumeration e = request.getHeaderNames(); while (e.hasMoreElements()) {
String headerName = (String)e.nextElement();
String headervalue = request.getHeader(headerName);
out.printin("<tr><td bgcolor=\"#CCCCCC\">" + headerName); out.println("</td><td>" + headervalue + "</tdx/tr>") ;
out.printin("</table>");
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws lOException, ServletException
(
doGet(request, response);
}
}
В браузере мы видим ответ, полученный от сервлета, в котором указаны все заголовки (рис. 6.26).
'21 Rei|uest Header Example - Mietosofl Internet Fxplefet
^|Й httpV/localhosLSOaO/enamptes/servlet/HeadeH
Request Header Example
Accept"Accept". iimage/gif) image/x-xbitmap, image/jpeg, image/pjpeg,.. application/vnd.ms-excel, application/msword,
Accept"
Accept"
t^ application/vnd.ms-powerpoint, */*
Accept- LanguageAccept- Language*4 en-usI*4 en-usIAccept-EncodingAccept-Encoding4 gap, deflate4 gap, deflate
Accept- Language
Accept- Language
*4 en-us
I
*4 en-us
I
Accept-
Encoding
Accept-
Encoding
4 gap, deflate
4 gap, deflate
User-Ager-tiMozilla/4.0 (compatible; MSB 6.0; Windows NT 5.0)
Host '- • localhosiSOSO
Connection Keep-Alive
Cookie " ScriptLanguagePreference=JScript;
_ ComponentPreference=VB5
Рис. 6.26. Работа с HTTP-заголовками
Пример прост и понятен без объяснений.
Общая информация
Напомним, что даже при работе с Windows, при обращении к апплетам, следует точно соблюдать названия с учетом регистра написания букв, иначе возникнет ошибка. Если, например, вместо http://Iocalhost:8080/exmaples/ servlet/Cookiel мы укажем, скажем, http://localhost:8080/exmaples/servlet/ cookie 1, то сервер выдаст ошибку (рис. 6.27).
'3hUp://localhost:8080/exampl^- Microsoft Internet Explorer'3hUp://localhost:8080/exampl^- Microsoft Internet ExplorerAddtets [5] http: //localhost. 8080/examples/sef vlet/cookie1Addtets [5] http: //localhost. 8080/examples/sef vlet/cookie1ни вни в_*] ^Gj Links_*] ^Gj Links
'3hUp://localhost:8080/exampl^- Microsoft Internet Explorer
'3hUp://localhost:8080/exampl^- Microsoft Internet Explorer
Addtets [5] http: //localhost. 8080/examples/sef vlet/cookie1
Addtets [5] http: //localhost. 8080/examples/sef vlet/cookie1
ни в
ни в
_*] ^Gj Links
_*] ^Gj Links
Error: 500
Internal Servlet Error:
java.lang.NoClassDefFoundError: cookiel (wrong name:java.lang.NoClassDefFoundError: cookiel (wrong name:at at at at at at atat at at at at at atjava.lang.ClassLoader.defineClassO(Native java.lang.ClassLoader.defineClass(Unknown java.lang.ClassLoader.defineClass(Unknownjava.lang.ClassLoader.defineClassO(Native java.lang.ClassLoader.defineClass(Unknown java.lang.ClassLoader.defineClass(UnknownCookiel) Hethod) Source) Source)Cookiel) Hethod) Source) Source)at at at atat at at atcom.sun.web.core.ServletLoader.loadclass(ServletLoader.java:111) com.sun.web.core.ServletLoader.loadServlet(ServletLoader.java:30) com.sun.web.core.ServletUrapper.loadServlet(ServletUrapper.java:81) com.sun.web.core.ServletUrapper.handleRequest(ServletUrapper.java:109) com.sun.web.core.InvokerServlet.service(InvokerServlet.java:169) javax.servlet.http.HttpServlet.service(HttpServlet.java:840)com.sun.web.core.ServletUrapper.handleRequest(ServletUrapper.java:140) com.sun.web.core.Context.handleRequest(Context.java:375)com.sun.web.server.ConnectionHandler.run(ConnectionHandler.java:135)com.sun.web.core.ServletLoader.loadclass(ServletLoader.java:111) com.sun.web.core.ServletLoader.loadServlet(ServletLoader.java:30) com.sun.web.core.ServletUrapper.loadServlet(ServletUrapper.java:81) com.sun.web.core.ServletUrapper.handleRequest(ServletUrapper.java:109) com.sun.web.core.InvokerServlet.service(InvokerServlet.java:169) javax.servlet.http.HttpServlet.service(HttpServlet.java:840)com.sun.web.core.ServletUrapper.handleRequest(ServletUrapper.java:140) com.sun.web.core.Context.handleRequest(Context.java:375)com.sun.web.server.ConnectionHandler.run(ConnectionHandler.java:135)
java.lang.NoClassDefFoundError: cookiel (wrong name:
java.lang.NoClassDefFoundError: cookiel (wrong name:
at at at at at at at
at at at at at at at
java.lang.ClassLoader.defineClassO(Native java.lang.ClassLoader.defineClass(Unknown java.lang.ClassLoader.defineClass(Unknown
java.lang.ClassLoader.defineClassO(Native java.lang.ClassLoader.defineClass(Unknown java.lang.ClassLoader.defineClass(Unknown
Cookiel) Hethod) Source) Source)
Cookiel) Hethod) Source) Source)
at at at at
at at at at
com.sun.web.core.ServletLoader.loadclass(ServletLoader.java:111) com.sun.web.core.ServletLoader.loadServlet(ServletLoader.java:30) com.sun.web.core.ServletUrapper.loadServlet(ServletUrapper.java:81) com.sun.web.core.ServletUrapper.handleRequest(ServletUrapper.java:109) com.sun.web.core.InvokerServlet.service(InvokerServlet.java:169) javax.servlet.http.HttpServlet.service(HttpServlet.java:840)
com.sun.web.core.ServletUrapper.handleRequest(ServletUrapper.java:140) com.sun.web.core.Context.handleRequest(Context.java:375)
com.sun.web.server.ConnectionHandler.run(ConnectionHandler.java:135)
com.sun.web.core.ServletLoader.loadclass(ServletLoader.java:111) com.sun.web.core.ServletLoader.loadServlet(ServletLoader.java:30) com.sun.web.core.ServletUrapper.loadServlet(ServletUrapper.java:81) com.sun.web.core.ServletUrapper.handleRequest(ServletUrapper.java:109) com.sun.web.core.InvokerServlet.service(InvokerServlet.java:169) javax.servlet.http.HttpServlet.service(HttpServlet.java:840)
com.sun.web.core.ServletUrapper.handleRequest(ServletUrapper.java:140) com.sun.web.core.Context.handleRequest(Context.java:375)
com.sun.web.server.ConnectionHandler.run(ConnectionHandler.java:135)
Рис. 6.27. Соблюдайте регистр при написании имен сервлетов
А вот сервлет для получения общей информации:
import java.io.lOException;
import java.util.Enumeration;
import javax.servlet.*;
import javax.servlet.http.*;
public class Info extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, lOException
{
ServletConfig config = getServletConfig();
ServletOutputStream out = response.getOutputStream();
out.printin("Snoop Servlet");
out.printin();
out.println("Init Parameters");
Enumeration e = config.getlnitParameterNames();
while (e.hasMoreElements()) {
String key = (String)e.nextElement();
String value = config.getlnitParameter(key);
out.println("" + key + " = " + value);
}
out.printIn();
out.printin("Context attributes:");
ServletContext context = config.getServletContext();
Enumeration enum = context.getAttributeNames(); while (enum.hasMoreElements()) {
String key = (String)enum.nextElement();
Object value = context.getAttribute(key); out.printin("" + key + " = " + value);
} out.println();
out.println("javax.servlet.Servlet methods"); out.println();.
out.printin("Attribute names in this request:"); e = request.getAttributeNames(); while (e.hasMoreElements()) { String key = (String)e.nextElement(); Object value = request.getAttribute(key); out.println("" + key + " = " + value);
}
out.println();
out.printin("Protocol: " + request.getProtocol()); out.println("Scheme: " + request.getScheme());
out.println("Server Name: " + request.getServerName());
out.println("Server Port: " + request.getServerPort()); out.println("Server Info: " + getServletConfig().
getServletContext().getServerlnfо());
out.println("Remote Addr: " + request.getRemoteAddr()); out.printIn("Remote Host: " + request.getRemoteHost());
out.printin("Character Encoding: " + request.getCharacterEncoding()); out.println("Content Length: " + request.getContentLength());
out.println("Content Type: "+ request.getContentType()); out.println();
out.println("Parameter names in this request"); e = request.getParameterNames(); while (e.hasMoreElements()) {
String key = (String)e.nextElement();
String[] values = request.getParameterValues(key);
out.print("" + key + " = ");
for(int i = 0; i < values.length; i++) { out.print(values[i] + " ");
}
out.printin();
}
out.printing ;
out.printin("javax.servlet.http.HttpServletRequest methods"); out.println();
out.printin("Headers in this request");
e = request.getHeaderNames();
while (e.hasMoreElements()) {
String key = (String)e.nextElement();
String value = request.getHeader(key) ; out.println("" + key + " : " + value);
} out.printin();
out.println("Cookies in this request");
Cookie[] cookies = request.getCookies();
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
out.printin("" + cookie.getName() + " = " + cookie.getValue());
}
out.printin();
out.printin("Auth Type: " + request.getAuthType()); out.println("HTTP Method: " + request.getMethod()); out.println("Path Info: " + request.getPathlnfo()) ; out.printin("Path Trans: " + request.getPathTranslated()); out.println("Query String: " + request.getQueryString()); out.println("Remote User: " + request.getRemoteUser()); out.println("Session Id: " + request.getRequestedSessionld()); out.printin("Request URI: " + request.getRequestURI());
out.println("Servlet Path: " + request.getServletPath());
out.println();
out.println("Session Information");
HttpSession session = request.getSession(true); out.printin("Created: " + session.getCreationTime());
out.printin("ID: " + session.getld());
out.printin("Last Accessed: " + session.getLastAccessedTime());
out.printin("Max Inactive Interval: " + session.getMaxInactivelnterval());
out.println();
out.printin("Values: ");
String[] valueNames = session.getValueNames();
for (int i = 0; i < valueNames.length; i++) { out.println("" + valueNames[i] + " = " +
session.getValue(valueNames[i]));
out.println();
}
}
Мы рассмотрели базовые возможности, используемые при создании сервлетов. Для дальнейшей работы рекомендуем вам использовать документацию по сервлетам.
Глава 7
CGI-приложения на языке C++
Эта глава посвящена рассмотрению методов создания самостоятельных скомпилированных CGI-приложений на языке C++. Для создания таких приложений необходимо написать код на C++, скомпилировать его, получив самостоятельный ехе-файл, разместить этот файл на Web-сервере, обратиться к этому файлу с клиента через Web-сервер. Программа будет выполнена на сервере и, в соответствии с результатом ее работы, клиентский браузер получит тот или иной ответ. Для простоты работы с CGI полезно использовать уже существующие библиотеки. В нашем случае мы воспользуемся достаточно компактной и удобной библиотекой cgic (ее можно найти по адресу http://www.boutell.com/cgic).
Первое приложение
Начнем сразу с примера, предполагая, что у вас установлен компилятор C++, например, C++ в составе Microsoft Visual Studio 6 (вы можете использовать любой другой компилятор C++). Рассмотрим пример, приведенный в составе библиотеки cgic, — файл cgictest.c. Откроем Visual C++, загрузим файл cgitest.c и попытаемся его скомпилировать. Что получится? Ни одной ошибки, компиляция прошла успешно (рис. 7.1).
Попробуем создать выполняемый файл. Строим cgictest.exe. Получаем огромное количество ошибок (рис. 7.2). Это и неудивительно, файл cgictes.c даже не содержит функции main О. Чего-то не хватает. Нам не хватает библиотеки, файла cgic.c. Вставим его в проект (рис. 7.3, 7.4).
Пытаемся создать cgictest.exe — ошибок нет! В случае, если появляются какие-либо недоразумения, их вы можете устранить сами, они будут связаны с настройками C++. Запускаем cgictest.exe из консоли. Получаем ответ программы (рис. 7.5).
инв
■V 11 - Microsoft Visual C++ - fcgictestcj
ДД
«, include < stdio. h >
<#inc.Lude "cgic.h#
. cbat
jj[ iAIi global rrefrbert, 51|1
WWorkspace TV 1 projects)
B® 11 lie»
B-^j Source Fiet ■ ' - f^l cgicleti.c[ ; - £1 Header Fiet : Q] Resource Fiet Ш (^J External Dependencies
< »1«С1м^»н|.ДЯ»У|мГ
Compiling
Name(); Address(). Hungryf); Temperature(); Frogs();
Color(); Flavors(); NonExButtons() ; RadioButtons();
"З* '■*
"23
фол гы в?
Jint cgiMain() {
;#if DEBUG
■;/• Load a saved CGI scenario if we’re debugging */
cgiReadEnvironnent("/home/bcutell/public_htnl/capcgi.dat")
’“Xendi f
* cgiHeaderContentType("text/html");
* fprintf(cgiOut. "<HTML><HEAD>\n");
-Son/iguration: fl - WinSf fiebug-
cgictest.obj - 0 error(s), 0 varning(s)
Build/D^ugA &BdtiN! X. ^"^-ЗАЯе^А.ЖОеЬмазгяУ ' fill 1
Ree*
Рис. 7.1. Пример после компиляции
’.. 11 - Microsoft Visual C++ • (cgictest.cj
j®№ E» y«w Imei Er=ied 8*t Io*"№*w H* '" ^|is на I ^«l^t^W.^!*!
ИГ
HI ♦N->«™
BBB
Зя ’ I Iteез* га Д
wWorkspace'11': 1 proiect(s]
A ® 11 filet
В • ^j Source Files
-d«l
vXinclude <stdio.h> „^Xinc.lude "cgic.h*
В
! • b^l cgicte$t.c[ EJ Header Fks EJ Resource Fiet ED External Dependenciet
kstw/iawpj Wbwf
w
Linking... cgictest.obj cgictest.obj cgictest.obj cgictest.obj cgictest.obj cgictest.obj cgictest.obj cgictest.obj cgictest.obj cgictest.obj cgictest.obj cgictest.obj cgictest.obj
Name();
Address();
Hungry();
Temperature();
Frogs();
Color();
Flavors();
NonExButtons();
RadioButtons();
int cgiMainO {K/»
.;#if DEBUG
’■»../• Load a saved CGI scenario if we’re debugging *z^.i
' *' cgiReadEnvironment("/home/boutell/public html/capcqi.dat") ;Jy hlit- ‘/In
ii igurat ion": 11" - 'ttinSi Sebug-
LNK2001 LNK2001 LNK2001 LNK2001 LNK2001 LNK2001 LNK200I LNK2001 LNK2001 LNK2001 LNK2001 LNK2001 LNK2001
unresolved unresolved unresolved unresolved unresolved unresolved unresolved unresolved unresolved unresolved unresolved unresolved unresolved
external
external
external external external external external external external external external
symbol symbol symbol symbol symbol symbol symbol symbol symbol symbol symbol symbol symbol
LIBCD.lib(crtO.obj) : error LNK2001: unresolved external
„cgiOut
_og i HeaderContentType „cgiFormStringNoNevlines _ogiFormString
_og i FormCheckboxSingle _cgiFormDoub1eBounded _og i FormIn teger „cgiFormSeleotSingle „cgiFormSelectMultiple „cgiFormRadio „cgiStringArrayFree „cgiFormStringMultiple „ogi FormCheckboxMult i p1e symbol „main
Debug/ll.exe : fatal error LNK1120: 14 unresolved externalsyj:'
iguration
ug-
it
*ч^'Л*Л:*1К
)пмН>ем|Ьгд№вГ1]
пгг
tag.
иэ«№Едзз№
syxbol syxbol
syxbol
LIBCD.lib(crtD.obj) Debug/ll.exe : fata
rrror LHK1120: 14 unresolved externals
error LNK2001: unresolved external
Рис. 7.3. Вставляем файл библиотеки в проект
work tpscsi 1,1 @511 filet ^" Source Fiet
:03 Heeder Fiet
Ш ^ Ekternei Dependence»
Linking... cgictest.obj cgictest.obj egictest.obj ogictest.obj cgictest.obj cgictest.obj cgictest.obj cgictest.obj cgictest.obj cgictest.obj cgictest.obj cgictest.obj cgictest.obj
Color();
Flavors();
NonExButtons(): RadioButtons();
iCint cgiHain() {
/Vif DEBUG
/* Load a saved CGI scenario if
ve're debugging "
LHK2001: LNK2001: LNK2001; LNK2001: LNK2DD1: LHK2001: LBK2001: LNK2001: LNK2001:
LNK2001: LNK2001: LNK2001: LKK2001:
unresolved unresolved unresolved unresolved unresolved unresolved unresolved unresolved unresolved unresolved unresolved unresolved unresolved
external external external external external external external external external external external external external
syxbol syxbol syxbol
syxbol syxbol syxbol
„cgiOut
_cgiHeaderContentТуpe _cgi ForaStringNoHev1ines _cgiFornString
_cgiForxCheckboxSing1e _cgiForxDoubleBounded _cgiForжInteger „cgiForxSelectSingle _cgiForxSelectMultiple _cgiFormRadio _cgi S t r ing krrayFгее _cgi Forм3tringMu11 i ple _cgiForaCheckboxMult i p1e syxbol _xain
® Workspace 'cgictest': 1 proj
Н Д cgictest files |
i Щ cgic.c:
i® cgictest.c
a О External Dependence
Рис. 7.5. Пробный пример работает в консоли
Здесь мы можем видеть, что в первой строке ответ содержит сообщение:
Content-type: test/html;
Это имеет важное значение и определено в спецификации CGI (типы заголовков важны при программировании на любом языке). В дальнейшем мы еще остановимся на более подробном их рассмотрении.
Пойдем далее, установим полученное приложение на сервера Sambar в каталоге cgi-bin и обратимся к нему из браузера, указав адрес http://Iocalhost/cgi- bin/cgictest.exe. На рис. 7.6 показан ответ программы, выведенный в пользовательский браузер. В качестве ответа программа выводит данные, заданные по умолчанию.
Настоящий пример создан с учетом обработки HTML-формы, которая располагается в файле testform.html, приложенном к библиотеке. Откроем файл testform.html в редакторе SlickEdit и заменим в строке 7 адрес CGI- приложения, которое будет обрабатывать форму. Зададим свой адрес http://localhost/cgi-bin/cgictest.exe. Если ваш Web-сервер расположен на другом компьютере, а не на рабочем, то напишите соответствующий подходящий URL, где вы расположите файл cgictest.exe.
cgic test
Name fetched, result code: cgiFormSuccess Name: Читатель Петров Address:
Мне нравится программировать для Интернета. Я от этого получаю удовольствие, а
Гт Hungry!
Му temperature is 98.600000.
I have eaten 1 frogs.
I am: Red
My favorite ice cream flavors are:
♦ walnut
Votes (method 1):
My preferred candidates are:
. A
Votes (method 2):
My preferred candidates are:
Jlzt. ‘
Рис. 7.6. Тестовая программа ответила
CGI-C Test Form
Text Field containing Plaintext
|читыель Петров Your Name
Multiple-Line Text Field
Мне нравится программировать для Интернета. Я от этого получаю удовольствие, а затем буду промессхоналом
Checkbox
р Hungry,;'
Text Field containing a Numeric Value
[9B.6'Blood Temperature (80.0-120.0)-
Text Field containing an Integer Value
@’r5i^~'”" ГГ--".""Т--Т'-р^ОHSSMe«(ГТ„.Г7
Сейчас мы можем проверить работоспособность созданного простого Ин- тернет-приложения полностью. Загрузим в браузер страницу testform.html и заполним произвольной информацией предложенные элементы формы (рис. 7.7).
Программа cgictest.exe обработала запрос успешно и вернула результат (рис. 7.8).
3* test - Microsoft internet Е яркие»НЕВ
I Ч '- I. .'.U.< t .■ IЩ
]&ip6djii^ht^Mocaihost/c^
cgic test
Name fetched, result code: cgiFormSuccess
Name: Читатель Петров
Address:
Мне нравится программирована. Я еще не
I'm Hungry!
Му temperature is 98.600000.
I have eaten 1 frogs.
I am: Red
My favorite ice cream flavors are:.
■ walnut
Votes (method 1):
My preferred candidates are:
Рис. 7.8. Результат обработан
Последовательность создания CGI-приложения на C++
Подведем первые итоги. Для того чтобы создать работающее в Интернете CGI-приложение на C++, необходимо иметь работающий Web-сервер, который бы позволял выполнять на нем ехе-файлы. Программы должны компилироваться для той платформы, на которой установлен Web-сервер. В нашем случае это Windows.
Чтобы создать CGI ехе-программу, необходимо написать ее код, скомпилировать код, скомпилировать код библиотеки cgic.c, построить исполняемый ехе-файл. На этом этапе основным является знание правил построения пользовательского кода CGI-программ на C++ с использованием конкретной CGI-библиотеки. Существует большое количество CGI-библиотек. Их задача — облегчить процесс создания CGI-приложений. Библиотеки позволяют не вдаваться в детали спецификации CGI, а, зная общие принципы работы CGI, использовать те или иные функциональные возможности, реализованные CGI-библиотекой. Далее в книге мы еще не раз будем оказываться в такой ситуации, когда та или иная стандартная спецификация будет реализована средствами некоторого стандартного продукта. Для того чтобы иметь возможность пользоваться преимуществами описанной в спецификации модели, достаточно познакомиться с деталями ее реализации и использовать возможности этого продукта при создании приложений. Так, например, модель CORBA представляется непростой. Но если использовать ту или иную ее реализацию, то работа с CORBA станет несравненно более легкой и обозримой, нам не надо будет заново воплощать все механизмы, описанные в спецификации, а достаточно будет пользоваться уже готовыми инструментами.
После того как CGI-приложение создано, мы размещаем его на работающем Web-сервере.
В этой главе мы остановимся на рассмотрении способов работы с одной реализацией описания CGI для работы с языком C++ — с библиотекой cgic. Завершим просмотр примера клиентского HTML-файла, ознакомившись с его структурой. Код приведен ниже.
i HTML-клиент для обращения к CGI-приложению■ ■
<html>
<head>
<title>CGI-C Test Form</title>
</head> .
<body>
<hl>CGI-C Test Form</hl>
<form method="POST" action="http://localhost/cgi-bin/cgictest.exe"> <p>
Text Field containing Plaintext
<P>.
<input type="text" name="name">Your Name
<p>
Multiple-Line Text Field<p>
<textarea NAME="address" ROWS=4 COLS=40>
Default contents go here.
</textarea>
<p>
Checkbox
<p>
<input type="checkbox" name="hungry" checked>Hungry
<p>
Text Field containing a Numeric Value
<p>
<input type="text" name="temperature" value="98.6">
Blood Temperature (80.0-120.0)
<p>
Text Field containing an Integer Value
<p>
<input type="text" name="frogs" value="l">
Frogs Eaten
<p>
Single-SELECT
<br>
<select name="colors">
<option value="Red">Red
<option value="Green">Green
<option value="Blue">Blue
</select>
<br>
Multiple-SELECT
<br>
<select name="flavors" multiple>
<option value="pistachio">Pistachio
<option value="walnut">Walnut
<option value="creme">Creme
</select>
<p>Exclusive Radio Button Group: Age of Truck in Years
<input type="radio" name:="age" ма1ие="1">1
<input type="radio" name="age" value="2">2
<input type="radio" name="age" value="3" checked>3
<input type="radio" name="age" value="4">4
<p>Nonexclusive Checkbox Group: Voting for Zero through Four Candidates
<input type="checkbox" name="vote" value="A">A
<input type="checkbox" name="vote" value="B">B
<input type="checkbox" name="vote" value="C">C
<input type="checkbox" name="vote" value="D">D
<P>'
<input type="submit" name="submitl" value="Submit Request">
<input type="reset" value="Reset Request">
</form>
</body>'
</html>
Очевидно, что в данном примере нет ничего особенного, на что следовало бы обратить внимание. Мы видим обычные элементы формы, типы этих элементов ответственны за способ их графического отображения в окне браузера, элементы имеют имена, которым соответствуют значения. Пары name-values передаются серверному приложению cgictest.cgi. Основной наш интерес концентрируется на файле cgictest.c.
Код в файле cgictest.c:
#include <stdio.h>
#include "cgic.h"
void Name();.
void Address(); void Hungry(); void Temperature(); void Frogs(); void Color();
void Flavors();
void NonExButtons(); void RadioButtons();
int cgiMain() {
#if DEBUG
/* Загрузка сохраненного сценария для отладки */
cgiReadEnvironment("/home/boutell/public_html/capcgi.dat");
#endif
cgiHeaderContentType("text/html");
fprintf (cgiOut, "<HTMLXHEAD>\n") ;
fprintf(cgiOut, "<TITLE>cgic test</TITLE></HEAD>\n");
"<BODYXHl>cgic test</Hl>\n") ;"<BODYXHl>cgic test</Hl>\n") ;"</BODYx/HTML>\n");"</BODYx/HTML>\n");fprintf(cgiOut,
"<BODYXHl>cgic test</Hl>\n") ;
"<BODYXHl>cgic test</Hl>\n") ;
"</BODYx/HTML>\n");
"</BODYx/HTML>\n");
Name();
Address();
Hungry();
Temperature ();
Frogs () ;
Color () ;
Flavors();
NonExButtons(); RadioButtons(); fprintf(cgiOut, return 0;
void Name () {
char name[81];
int result = cgiFormStringNoNewlines("name", name, 81);
switch (result) (
case egiFormSuccess:
fprintf(cgiOut, "Name fetched, result code: cgiFormSuccess<br>\n"); break;
case cgiFormTruncated:
fprintf(cgiOut, "Name fetched,
result code: cgiFormTruncated<br>\n");
break;
case cgiFormEmpty:
fprintf(cgiOut, "Name fetched, result code: cgiFormEmpty<br>\n");
break;
case cgiFormNotFound:
fprintf(cgiOut, "Name fetched,
result code: cgiFormNotFound<br>\n");
break;
case cgiFormMemory:
fprintf(cgiOut, "Name fetched, result code: cgiFormMemory<br>\n");
break;
default:
fprintf(cgiOut, "Name fetched, unexpected result code: %s\n", result);
break;
fprintf(cgiOut, "Name: %s<BR>\n", name);
)'
void Address() (
char address[241];
cgiFormString("address", address, 241);
fprintf(cgiOut, "Address: <PRE>\n%s</PRE>\n", address); }
void Hungry() {
if (cgiFormCheckboxSingle("hungry") == cgiFormSuccess) { fprintf(cgiOut, "I'm Hungry!<BR>\n");
} else {
fprintf(cgiOut, "I'm Not Hungry!<BR>\n");
} }
void Temperature() { double temperature;
cgiFormDoubleBounded("temperature", Stemperature, 80.0, 120.0, 98.6);
fprintf(cgiOut, "My temperature is %f.<BR>\n", temperature); }
void Frogs() {
int frogsEaten;
cgiFormlnteger("frogs", &frogsEaten, 0) ;
fprintf(cgiOut, "I have eaten %d frogs.<BR>\n", frogsEaten); }
char *colors[] = {■
"Red",
"Green", "Blue" };
void Color() {
int colorchoice;
cgiFormSelectSingle("colors", colors, 3, &colorChoice, 0);
fprintf(cgiOut, "I am: %s<BR>\n", colors[colorchoice]);
char *flavors[] = {
"pistachio",
"walnut",
"creme"
);
void. Flavors () {
int flavorchoices[3];
int i;
int result;
int invalid;
result = cgiFormSelectMultiple("flavors", flavors, 3, flavorchoices, Sinvalid);
if (result == cgiFormNotFound) {
fprintf(cgiOut, "I hate ice cream.<p>\n");
} else {
fprintf(cgiOut, "My favorite ice cream flavors are:\n");
fprintf(cgiOut, "<ul>\n");
for (i=0; (i < 3) ; i++) {
if (flavorchoices[i]) {
fprintf(cgiOut, "<li>%s\n", flavors[i]);
}'
}
fprintf(cgiOut, "</ul>\n");
char *ages[] = {
"2",
"3",
"4"
);
void RadioButtons() {
int ageChoice;
char ageText[10];
/* Метод #1: проверка допустимых ответов.
При коротком списке допустимых ответов этот метод достаточно хорош, ответы могут быть заданы как исчерпывающий перечень. */
cgiFormRadio("age", ages, 4, SageChoice, 0);
fprintf(cgiOut, "Age of Truck:%s (method #l)<BR>\n",
ages[ageChoice]);
/* Метод #2: получаем строку. Метод полезен, когда требуется проверка нестандартным способом. В случае числовой информации, вместо функции cgi- FormString используются функции cgiFormlnteger и cgiFormDouble.
*/
cgiFormString("age", ageText, 10);
fprintf(cgiOut, "Age of Truck: %s (method #2)<BR>\n", ageText);
}
char *votes[] = (
"A",
"B",
"C",
"D"
};
void NonExButtons() {
int votechoices [4];
int i ;
int result;
int invalid;
char **responses;
/* Метод #1: проверка допустимых значений. Это хороший подход, так как недопустимые значения должны быть проигнорированы. */
fprintf(cgiOut, "Votes (method l):<BR>\n");
result = cgiFormCheckboxMultiple("vote", votes, 4,
voteChoices, &invalid);
if (result == cgiFormNotFound) ('
fprintf(cgiOut, "I hate them all!<p>\n");
} else {
fprintf(cgiOut, "Му preferred candidates are:\n");
fprintf(cgiOut, "<ul>\n");
for (i=0; (i < 4); i++) { if (voteChoices[i]) { fprintf(cgiOut, "<li>%s\n", votes[i]);
} } fprintf(cgiOut, "</ul>\n");
}
/* Метод #2: получаем все имена.
Этот метод может быть полезен тогда, когда требуется дополнительная обработка полученной информации. */
fprintf(cgiOut, "Votes (method 2):<BR>\n");
result = cgiFormStringMultiple("vote", Sresponses);
if (result == cgiFormNotFound) {
fprintf(cgiOut, "I hate them all!<p>\n");
} else {
int i = 0;
fprintf(cgiOut, "My preferred candidates are:\n");
fprintf(cgiOut, "<ul>\n");
while (responses [i]) { fprintf(cgiOut, "<li>%s\n", responses[i]);
}
fprintf(cgiOut, "</ul>\n");
}
/* Следует убедиться в том, что ненужные строки удаляются, иначе произойдет утечка памяти. Можно вызвать метод free() - он освободит массив, но не очистит память от отдельной строки. Чтобы произвести зачистку полностью, следует использовать функцию cgiStringArrayFree(). */ cgiStringArrayFree(responses);
}
Важно, что код создаваемой программы не содержит функцию Main о. Main о расположена в библиотеке cgic.c. Вместо нее создаваемый файл содержит функцию cgiMainO. Файл примера включает инструкцию вставки библиотечного файла cgic.h. В нем описаны основные переменные, используемые в библиотеке.
Файл cgic.h
/* Это библиотека CGI_C, разработанная Thomas Boutell, версия 1.0. Библиотека представляет собой качественный программный интерфейс, позволяющий эффективно решать задачи CGI-программирования. */
/* Вставляем только один раз! */
#ifndef CGI_C
#define CGI_C 1
/* Вставляем библиотеку стандартного ввода-вывода. */
#include <stdio.h>
/* Задаем переменные окружения. Вместо вызова функции getenv(), разработчику следует пользоваться именно этими переменными, которые представляют собой строки (с завершающими строки нулями, как это и положено) . Такая строка может быть пустой, но она не может быть null. Эти переменные позволяют с легкостью сохранять текущее окружение. */
extern char
*cgiServerSoftware;
extern char
*cgiServerName;
extern char
*cgiGateway!nterface
extern char
*cgiServerProtocol;
extern char
*cgiServerPort;
extern char
*cgiRequestMethod;
extern char
*cgiPath!nfo;
extern char
*cgi PathTranslated;
extern char
*cgiScriptName;
extern char
*cgiQueryString;
extern char
*egiRemoteHost;
extern char
*cgiRemoteAddr;
extern char
*cgiAuthType;
extern char
*cgiRemoteUser;
extern char
*cgiRemote!dent;
extern char
*cgiContentType;
extern char
*cgiAccept;
extern char
*cgiUserAgent;
extern char
*cgiReferrer;
/* Определение введено для того, чтобы учесть ошибку написания, обнаруженную в спецификации HTTP/CGI. */
#define cgiReferer cgiReferrer
/* Количество полученных байтов. */
extern int cgiContentLength;
/* Указатель на поток вывода CGI. Первой должна быть использована функция cgiHeader, которая посылает заголовки, затем происходит вывод HTML-кода. */
extern FILE *cgiOut;
/* Указатель на поток ввода CGI. В 99% случаев этот поток не используется. Но иногда, скажем, для обработки форм, передаваемых приложению, он может оказаться полезным. */
extern FILE *cgiln;
/* Вероятные коды, возвращаемые функциями семейства cgiForm (см. ниже). */
typedef enum {
cgiFormSuccess,
cgiFormTruncated,
cgiFormBadType,
cgiFormEmpty,
cgiFormNotFound,
cgiForr.Cons trained,
cgiFormNoSuchChoice, cgiFormMemory
} cgiFormResultType;
/* Функция для получения данных из форм (см. также файл cgic.html). */
extern cgiFormResultType cgiFormString(
char *name, char *result, int max);
extern cgiFormResultType cgiFormStringNoNewlines(
char *name, char ^result, int max);
extern cgiFormResultType cgiFormStringSpaceNeeded( char *name, int *length);
extern cgiFormResultType cgiFormStringMultiple( char *name, char ***ptrToStringArray);
extern void cgiStringArrayFree(char **stringArray);
extern cgiFormResultType cgiFormlnteger( char *name, int *result, int defaultV);
extern cgiFormResultType cgiFormlntegerBounded(
char *name, int *result, int min, int max, int defaultV);
extern cgiFormResultType cgiFormDouble( char *name, double *result, double defaultV);
extern cgiFormResultType cgiFormDoubleBounded( char *name, double *result, double min, double max, double defaultV);
extern cgiFormResultType cgiFormSelectSingle( char *name, char **choicesText, int choicesTotal, int *result, int defaultV);
extern cgiFormResultType cgiFormSelectMultiple( char *name, char **choicesText, int choicesTotal, int *result, int *invalid);
extern cgiFormResultType cgiFormCheckboxSingle( char *name);
extern cgiFormResultType cgiFormCheckboxMultiple( char *name, char **valuesText, int valuesTotal, int *result, int *invalid);
extern cgiFormResultType cgiFormRadio( char *name, char **valuesText, int valuesTotal,
int *result, int defaultV);
extern void cgiHeaderLocation(char *redirectUrl);
extern void cgiHeaderStatus(int status, char *statusMessage); extern void cgiHeaderContentType(char *mimeType);
typedef enum ( cgiEnvironmentIO, cgiEnvironmentMemory, cgiEnvironmentSuccess
} cgiEnvironmentResultType;
extern cgiEnvironmentResultType cgiWriteEnvironment(char *filename);
extern cgiEnvironmentResultType cgiReadEnvironment(char * filename);
extern int cgiMainO;
#endif /* CGI C */
Функция cgiMain () очень невелика. Основное ее назначение — вызов других функций, каждая из которых ответственна за обработку того или иного элемента <input type=...> из формы, т. е. за чтение значений тех или иных переменных.
int cgiMainO (
#if DEBUG
/* Загрузка сохраненного сценария при отладке. */
cgiReadEnvironment("/home/boutell/public_html/capcgi.dat");
Sendif
cgiHeaderContentType("text/html");
fprintf (cgiOut, "<HTMLXHEAD>\n") ;.
fprintf(cgiOut, "<TITLE>cgic test</TITLEX/HEAD>\n");
fprintf (cgiOut, "<BODYXHl>cgic test</Hl>\n") ;
Name () ;
Address ();
Hungry();
Temperature() ;
Frogs ();
Color();
Flavors();
NonExButtons();
RadioButtons();
fprintf (cgiOut, "</BODYX/HTML>\n") ;
return 0;
}
Программа начинается с выведения HTML-заголовка при помощи функции cgiHeaderContentType о . Затем выводится HTML-текст при помощи операторов вывода fprintf). Кроме того, вызываются упомянутые ранее функции.
Что такое CGI?
Вспомним еще раз, что такое CGI. CGI (Common Gateway Interface) — это стандарт взаимодействия программ с серверами, такими, как НТТР-сервер. Спецификация CGI в оригинальном виде находится в Интернете по адресу http://hoohoo.ncsa.uiuc.edu/cgi/interface.html. Так сложилось, что большое количество CGI-приложений пишется на компактных языках сценариев, например, на языке Perl, или на PHP. Отличительная особенность языков сценариев заключается в том, что они интерпретируются. По мере роста сложности решаемых сервером задач, становится необходимым использовать и иные языки.
Как работает CGI?
Когда HTTP-сервер получает запрос к CGI-скрипту (приложению), он связывается со скриптом, передавая ему детали запроса. Это может происходить одним из четырех способов:
Переменные окружения. Для передачи информации скрипту используются переменные окружения. В зависимости от типа запроса, переменные могут содержать всю передаваемую информацию, либо какую-то ее часть.
Командная строка. Командная строка используется не очень часто, поскольку это сопряжено с определенным риском.
Стандартный ввод. Если сервер получает HTTP-запросы посредством HTTP-методов форм POST и/или PUT, то сервер передает полученные данные как стандартный ввод. Количество передаваемой через стандартный ввод информации хранится в виде значения переменной CONTENTLENGTH.
Стандартный вывод. Скрипт выводит информацию через стандартный вывод. Вывод этот может быть организован в виде документа, создаваемого скриптом, либо в виде инструкции серверу о возвращении информации клиенту.
Переменные окружения в CGI
Переменные окружения, которые не зависят от типа запроса и присутствуют при всех типах запроса:
server_software — имя и версия серверного программного обеспечения В формате name/version;
server_name — имя хоста сервера, DNS, IP-адрес в том виде, как сервер себя представляет;
gateway_interface — версия спецификации CGI, представленной на сервере, в формате CGi/revision.
Переменные окружения, зависящие от типа запроса:
SERVER_PROTOCOL — ИМЯ И Версия Протокола В формате protocol/revision;
server_port — номер порта, по которому был послан запрос;
request_method — метод, которым был сделан запрос: для HTTP— это методы get, head, post;
path_info — дополнительная информация о пути от клиента;
path_translated — преобразованная сервером информация о пути;
script_name — виртуальный путь к выполняемому скрипту;
query_string — информация, которая следует в URL после символа знака вопроса;■
remote_host — имя хоста, пославшего запрос;
remote_addr — IP-адрес хоста, пославшего запрос;
auth_type — если сервер поддерживает аутентификацию и скрипт является защищенным, то эта переменная содержит информацию о методе аутентифи каци и;
remote_user — пользователь (в случае, если скрипт защищен);
remote_ident — если сервер поддерживает аутентификацию по RFC 931, то значение переменной равно полученному значению имени пользователя;
content_type — для запросов, содержащих дополнительно приложенную информацию, например, для HTTP при методах post и put, это может быть тип передаваемых формой данных;
content_length — длина информации, посланной клиентом.
Кроме того, существуют другие переменные окружения, связанные с HTTP:
нттр_ассерт — тип MIME, понимаемый клиентом, в формате type/subtype;
http_user_agent — тип клиентского браузера в формате software/ version 1ibrary/version.
Командная строка
Командная строка используется только при ISINDEX-запросах. Сервер ищет информацию запроса (переменная окружения query_string), если он не находит "=" в query_string, то командная строка не используется.
CGI-ввод
Информация, которая имеется в запросах после заголовка, будет послана скрипту через стандартный ввод stdin. В качестве дополнительной информации сервер посылает описание переменной окружения content_length (в байтах). Всегда следует помнить о том, что необходимо предварительно описывать данные при помощи переменной окружения content_type.
Пример
Зададим метод method="post". Предположим, что форма содержит 7 байтов, например, а=ь&ь=с. В этом случае сервер задаст значение переменной окружения content_length, равное 7, а значение типа следует задать как appiication/x-www-form-uriencoded. Первым байтом на стандартном вводе скрипту будет "а", а затем вся строка до конца.
CGI-вывод
Скрипт посылает вывод на стандартный вывод. Как правило, скрипты создают вывод, который должен быть направлен обратно клиенту. При этом скрипт не должен каждый раз создавать полные НТТР/1.0 заголовки.
Анализируемые заголовки
Вывод скриптов начинается с небольшого заголовка. Этот заголовок состоит из текстовых строк в том же формате, что и HTML-заголовки. Все заголовки отделяются пустой строкой, и те, которые не являются директивами серверу, посылаются клиенту. Существует три директивы серверу:
□ Content-type — тип MIME возвращаемого документа;
□ Location — указывает, что мы возвращаем не сам документ, а ссылку на него. Если аргументом указан URL, то сервер перенаправит клиента к этому URL. Если аргумент — виртуальный путь, то сервер вызовет документ, указанный в пути точно таким образом, как будто клиент сам запросил этот документ. Здесь можно использовать знак "?" , но предварительно клиенту должен быть отправлен символ # ;
□ status — используется для сообщения серверу строки статуса, формат ппп ххххх, здесь ппп — три цифры кода статуса, ххххх — строка, содержащая причину, например, "Forbidden".
Статус-коды
Категория Success 2хх
Коды 2хх сообщают об удачном завершении операции:
ОК 200
Запрос был выполнен;
CREATED 201
Следует за инструкцией POST, указывая на благополучную обработку. Текст ответа содержит URI вновь созданного документа;
Accepted 202
Запрос принять для обработки, но обработка еще не завершена. Неизвестно, будет ли дан на запрос ответ или предприняты те или иные действия. Это зависит от того, как запрос будет обрабатываться, все будет определяться в процессе обработки;
Partial Information 203
Если такой ответ получен в ответ на команду GET, то он означает, что полученная возвращаемая мета-информация недостаточна;
No Response 204
Сервер получил запрос, но нет информации, которая должна быть послана назад. Клиенту следует просматривать тот же документ, в котором он находился. Это может быть полезно в тех случаях, когда скрипт должен получить информацию, но изменения в клиентской странице при этом не нужны.
Категория ошибок Error 4хх, 5хх
Коды 4хх предназначены для того, чтобы сообщать об ошибках клиента. Коды 5хх соответствуют ошибкам сервера. Это информационные сообщения: □ Bad request 400
Запрос содержит неверный синтаксис или невозможно выполнить запрос;
Unauthorized 401
Требуется аутентификация, клиент должен повторить запрос с аутентификацией;
PaymentRequired 402
Клиент должен повторить запрос с использованием заголовка ChargeTo;
Forbidden 403
Запрос запрещен, аутентификация не помогает;
Not found 404
Сервер не нашел документ, соответствующий запросу;
Internal Error 500
Сервер столкнулся с непредвиденными обстоятельствами, которые не позволили ему выполнить запрос;
Not implemented 501
Сервер не поддерживает запрашиваемый ресурс;
Service temporarily overloaded 502
Сервер не может обработать запрос ввиду его перегрузки;
Gateway timeout 503
Код совпадает с кодом внутренней ошибки сервера 500, но подразумевает, что при этом ответ от внутренних ресурсов превысил установленный предел ожидания.
Коды перенаправления Redirection Зхх
Коды Зхх подразумевают, что будут предприняты дополнительные действия по перенаправлению клиента (как правило, эти действия осуществляются автоматически):
Moved 301
Запрошенные данные были перемещены на другой URI, изменения постоянные. Ответ содержит одну или несколько строк в форме.
URI: <url> String CrLf
Здесь указаны новые альтернативные адреса запрашиваемого ресурса. String — это необязательное поле, в нем содержится комментарий;
Found 302
Запрошенные данные находятся на другом URL. Формат такой же, как и при Moved 301;
Method 303
Method: <method> <url>
body-section
Клиент перенаправляется на другой адрес с указанием метода, например, GET;
Not Modified 304
Клиент произвел запрос, но документ не изменялся с даты, указано ВIf-Modofied-Since.
Примеры с анализируемыми заголовками
Заголовок содержит описание типа содержимого: start of output
Content-type: text/html.
end of output
После заголовка обязательно следует пустая строка.
Пусть скрипт возвращает документ (файл) /path/doc.txt с сервера, как если бы браузер запросил его, указав при этом в качестве адреса http://server:port/path/doc.txt. В этом случае пишем заголовок в виде: start of output
Location: /path/doc.txt
end of output
Проверим на примере. Создадим файл headtest.с:
#include "cgic.h"
int cgiMain() {'
fprintf(cgiOut, "Location: http://localhost/redirect.html \n");
return 0;
}
Скомпилируем его и построим headtest.exe вместе с библиотекой cgic.c. Получим файл headtest.exe. Запустим его из командной строки. Ответ показан на рис. 7.9.
Понятно, что при запуске скрипта в консоли никакой переадресации не произойдет, ее некому производить, сервер остался не у дел.
Помещаем файл headtest.exe в каталог исполняемых файлов сервера Smabar — cgi-bin.
В окне браузера вводим запрос http://localhost/cgi-bin/headtest.exe (рис. 7.10).
Рис. 7.10. Запрашиваем скрипт
Создадим файл, на который браузер будет нас отсылать. Это файл redi- rect.html:
<html>
<head>
<title>Redirection</title>
<body>
<H1 align=center>Redirected.</hl>
<р>Севрер нас перенаправил.
</body>
</html>
После выполнения скрипта получаем в окне браузера документ redirect.html (рис. 7.11).
После этого сервер выполнит запрос и отправит документ клиенту. Если скрипт должен перенаправить клиента на службу "гофер", напишем такой заголовок:
start of output
Location: gopher://gopher.ncsa.uiuc.edu/
end of output
Еще один пример, где мы общаемся с клиентом напрямую. Сервер не получает никаких заголовков, все будет перенаправлено непосредственно клиенту по протоколу HTTP.
start of output
HTTP/1.0 200 OK
Server: NCSA/1.0a6
Content-type: text/plain
This is a plaintext document generated on the fly just for you.
end of output
2
Redirected.
Сервер нас перенаправил.
У Готово •У Готово •PTf^?.^ Местная интрасеть. *
У Готово •
У Готово •
Рис. 7.11. Сервер перенаправил нас на новый документ
Создаем файл directcomm.c.
; Файл directcomm.c
#include "cgic.h"
int cgiMain() {
fprintf(cgiOut, "HTTP/1.1 200 OK\n");
fprintf(cgiOut, "Server: Sambar 5.0\n");
fprintf(cgiOut, "Content-type: text/plain\n\n");
fprintf(cgiOut, "This is a plaintext document generated on the fly just for you.Xn");
return 0;
Здесь важно помнить, что нужно отделить текст файла от заголовков пустой строкой ("\п\п").
Компилируем файл, добавляем в проект файл cgic.c, получаем directcomm.exe, копируем его в каталог cgi-bin, обращаемся из браузера к адресу http://localhost/cgi-bin/directcaoinm.exe. Результат показан на рис. 7.12.
This is a plaintext document generated on the fly just for you.<1
„„.^.^
Рис. 7.12. Ответ направлен непосредственно браузерубез посредничества Web-сервера
При работе напрямую по протоколу HTTP удобно контролировать ответ сервера при помощи, например, программы telnet. Набираем в командной строке telnet, появляется стандартное окно (рис. 7.13).
Рис. 7.13. Используем telnet
Рис. 7.14. Задаем параметры удаленной системы
Выбираем в меню режим подключения к удаленной системе и в окне вводим имя этой системы и порт. В нашем случае, в качестве удаленной системы будет localhost, а номер порта тот, что установлен для сервера Sambar, по умолчанию это 80 (рис. 7.14).
Установлена связь с Web-сервером. Вводим запрос по протоколу HTTP в виде:
GET /cgi-bin/directccomm.exe
и два раза нажимаем клавишу <Enter>.
Запрос отправлен серверу, и тут же мы получаем ответ (рис. 7.15). Перед этим полезно установить такие параметры окна telnet, чтобы с программой было удобно работать. Ответ содержит то, что получает браузер.
JI Пз1№?1 -151313
Р>№п%ул- Ц^аьгв Т«,рмим» £грпвг»
GET /cgi-bin/directconn.exe
НТТР/1.1 200 ОК
Server: Sanbar 5.0
Content-type: text/plain
(This is a plaintext document generated on the fly just for you.
Рис. 7.15. Ответ по протоколу HTTP
Аналогичным образом мы можем связаться с любым сервером. Важно иметь в виду, что протокол telnet все же отличается от TCP, поэтому не всегда можно использовать клиент telnet. Однако сокеты тут могут быть весьма полезны.
CGI-заголовки. Метаинформация о документах и объектах
Помимо заголовка content-type, существуют и другие заголовки. Все они не являются обязательными. Если приложение не поймет тот или иной заголовок, он будет попросту проигнорирован.
Список заголовков:
Allowed;
Public;
Content-Length;
Content-Type;
Content-Transfer-Encoding;
Content-Encoding;
Date;
Expires;
Last-Modified;
Message-Id;
URI;
Version;
Derived-From;
Content-Language;
Cost;
Link;
Title.
Allowed: Method
Список допустимых методов, по умолчанию get head.
Пример
Allowed: GET HEAD PUT
Public: Method
Список методов, которые допускается использовать для всех запросов, по умолчанию get.'
Пример
Public: GET HEAD TEXTSEARCH
Content-Length: int
Подразумевается, что тело запроса является двоичным, и можно производить чтение информации напрямую, не анализируя ее.
Подробнее с заголовками можно разобраться в соответствующей документации.
Библиотека cgic
В этом разделе мы обсудим некоторые возможности библиотеки cgic более подробно.
Вывод заголовка
Для вывода заголовка используется функция cgiHeaderContentTypeо, которой передается MIME тип документа, выводимого программой. В примере cgic.h, рассмотренном ранее в данной главе, мы использовали тип text/html, который соответствует обычному HTML-документу. Примеры других часто используемых заголовков: image/gif, image/jpeg, audio/basic. Заголовок необходимо выводить всегда, иначе возникает ошибка. Вместо функции cgiHeaderContentType () можно использовать другие функции, выводящие заголовок, — cgiHeaderStatus () ИЛИ cgiHeaderLocation ().
Ввод текста
В файле примера cgic.h использована функция Name о :
void Name () {
char name[81];
cgiFormStringNoNewlines("name", name, 81);
fprintf(cgiOut, "Name: %s<BR>\n", name);
}
Эта функция предназначена для получения имени, которое пользователь вводит в форму в окне браузера. Здесь установлено, что значение поля name не должно быть более 80 символов, соответствующий буфер указан равным 81. Функция cgiFormStringNoNewlines () получает значение переменной, которое не должно содержать символа перевода строки. Первый аргумент функции — имя поля в HTML-форме. Вторая переменная — буфер, куда будет выведено значение переменной, третий аргумент — длина этого буфера. Библиотека cgic не выделит места больше, чем указано в третьем аргументе. Если буфер мал, то значение будет укорочено. Вместо этой функции можно использовать функцию cgiFormStringSpaceNeededO, которая автоматически проверяет размер буфера, требуемый для хранения значения.
Вывод
Функция Name () записывает данные в поток вывода cgiOut. Как правило, cgiOut эквивалентно stdout.
Обработка полей для установки флажка
В функции Hungry () осуществляется проверка того, установлен ли флажок в поле hungry:
void Hungry() {
if (cgiFormCheckboxSingle("hungry") == cgiFormSuccess) {
fprintf(cgiOut, "I'm Hungry!<BR>\n") ;
} else {
fprintf(cgiOut, "I'm Not Hungry!<BR>\n");
}
}
Для проверки используется функция cgiFormCheckboxSingle(). Она определяет, выделен ли указанный в качестве параметра элемент (см. также функции cgiFormCheckboxMultiple() И cgiFormStringMultiple()).
Числовой ввод
Рассмотрим функцию Temperature о, с ее помощью мы получаем температуру в градусах : void Temperature() { double temperature;
cgiFormDoubleBounded("temperature", &temperature, 80.0,120.0,98.6) ;
fprintf(cgiOut, "My temperature is %f.<BR>\n", temperature);
}
Температура получена С использованием функции cgiFormDoubleBounded (). Первый аргумент — имя поля, второй — указатель на адрес переменной, где будет храниться значение температуры, третий и четвертый — нижняя и верхняя граница для температуры. Последний аргумент — значение, которое будет использовано по умолчанию, в том случае, если значение не будет указано или выйдет за установленные пределы (см. также функцию cgiFormDoubie ()). Существуют аналогичные этим функции для работы С целыми значениями cgiFormlnteger () И cgiFormlntegerBounded ().
Обработка альтернативного выбора
Для предоставления возможности выбора, в HTML-документе используется элемент <select> (но можно также применить радиокнопки и поля для установки флажков). Рассмотрим функцию Color (): char *colors[] = {
"Red",
"Green",
"Blue"
};
void Color() {
int colorchoice;
cgiFormSelectSingle("colors", colors, 3, &colorChoice, 0);
fprintf(cgiOut, "I am: %s<BR>\n", colors[colorchoice]);
}
Функция cgiFormseiectsingieо определяет, какой именно выбран цвет в описанном массиве цветов. Она содержит несколько аргументов. Первый аргумент — имя поля в форме. Второй — указатель на список допустимых цветов. Третий элемент — количество элементов массива цветов. Четвертый — указатель на переменную, в которой будет храниться выбранный цвет. Пятый аргумент — индекс элемента массива, который будет использован по умолчанию в случае, если браузер не укажет на установленный выбор.
Обработка множественного выбора
Рассмотрим фрагмент файла cgictest.c:
char *votes[] = {
"А",
"В",
"С",
"D"
};.
void NonExButtons() {
int votechoices[4];
int i ;
int result;
int invalid;
char **responses;
/* Метод #1: проверка допустимых значений. */ fprintf(cgiOut, "Votes (method l):<BR>\n");
result = cgiFormCheckboxMultiple("vote", votes, 4, voteChoices, &invalid);
if (result = cgiFormNotFound) { fprintf(cgiOut, "I hate them all!<p>\n");
} else {
fprintf(cgiOut, "My preferred candidates are:\n"); fprintf(cgiOut, "<ul>\n");
for (i=0; (i < 4); i++) { if (voteChoices[i]) { fprintf(cgiOut, "<li>%s\n", votes[i]);
fprintf(cgiOut, "</ul>\n");
Здесь используется функция cgiFormCheckboxMuitipie (), которая определяет, какие выбраны позиции в элементе множественного выбора. Первый аргумент — имя элемента, второй — указатель на массив возможных (допустимых) значений, они должны соответствовать значениям, указанным в качестве значений атрибутов value. Третий аргумент — количество элементов в массиве допустимых значений. Четвертый элемент — указатель на массив целых значений с тем же числом элементов, что и массив допустимых значений. Каждый элемент принимает значение true, если выбрано соответствующее значение, в противном случае — значение false.
Другой способ (фрагмент из файла cgictest.c):
/* Метод #2: все значения принимаются. Полезно в том случае, когда используется дополнительная проверка всех вводимых значений. При этом важно уделить внимание тому, чтобы ввод не мог быть потенциально опасным. */
fprintf(cgiOut, "Votes (method 2):<BR>\n");
result = cgiFormStringMultiple("vote", ^responses);
if (result == cgiFormNotFound) {
fprintf(cgiOut, "I hate them alli<p>\n");
} else {
int i = 0;
fprintf(cgiOut, "My preferred candidates are:\n");
fprintf(cgiOut, "<ul>\n") ;
"while (responses[i]) {
fprintf(cgiOut, "<li>%s\n", responses[i]);
}
fprintf(cgiOut, "</ul>\n");
}
/* Освобождение памяти, чтобы избежать утечки памяти с помощью функций freed и cgiStringArrayFree() . */
cgiStringArrayFree(responses); }
Здесь использована функция cgiFormStringMultiple о. Если обратиться к ней с помощью строки: cgiFormStringMultiple("vote", &responses);
то возникнет вопрос, какое количество ответов мы получим?
Задача решается так:
int i = 0;
while (responses[i]) (
/* Здесь функции для обработки строк responses[i] */ i++;
}
Функция cgiFormstringMuitipie () возвращает ссылку на память. Содержимое памяти нельзя изменить, и если необходимо внести изменения, то содержимое памяти предварительно следует запомнить в переменной. После того как проверка массива, полученного скриптом, завершена, необходимо использовать функцию cgistringArrayFree о, указав массив в качестве аргумента. Это необходимо сделать в целях экономии памяти.
Работа с изображениями
Библиотека cgic может быть использована в сочетании с графической библиотекой GD (адрес http://www.boutell.com/gd/). С ее помощью можно осуществлять работу с графикой "на лету", как мы это делали при работе с PHP.
#include "cgic.h"
#include "gd.h"
char *colors[] = (
"red", "green", "blue"
};
#define colorsTotal 3
int cgiMain() (
int colorChosen;
gdlmagePtr im; int r, g, b;
/* Используем библиотеку GD */
im = gdlmageCreate(64, 64);
r = gdlmageColorAllocate(im, 255, 0, 0) ;
g = gdlmageColorAllocate(im, 0, 255, 0) ;
b = gdlmageColorAllocate(im, 0, 0, 255);
/* Используем возможности CGI для определения запрошенного пользователем цвета */
cgiFormSelectSingle("color", 3, scolorChosen, 0);
/* Заполняем выбранным цветом */
switch(colorChosen) ( case 0: gdlmageFill(im, 32, 32, r); break;■
case 1: gdlmageFill(im, 32, 32, g); break; case 2: gdlmageFill(im, 32, 32, b); break; } /* Выводим рисунок. Тип содержимого. */ cgiHeaderContentType("image/gif"); /* Отправка рисунка в поток вывода cgiOut */ gdlmageGif(im, cgiOut); /* Освобождаем ресурс */ gdlmageDestroy(im) ; return 0; } Здесь мы не будем более уделять специальное внимание графической библиотеке GD.
Отладка CGI-приложений
Отладка CGI-приложений порой оказывается довольно болезненным занятием, так как не всегда сразу удается определить место, где возникает сбой или ошибка. CGI-приложения работают в специфическом окружении. Трудно создать такой отладчик, который бы позволил найти ошибки простым способом. Библиотека cgic располагает своеобразным отладчиком capture.c, который "запоминает" живое окружение, сохраняет его в файле, что помогает отладке cgi-программ.
Описание некоторых функций библиотеки cgic Рассмотрим некоторые функции библиотеки cgic: □ cgiFormResultType cgiFormString(char ‘name, char *result, int max) определяет строку-результат для указанного поля (1 аргумент). Результат заносится в буфер (2 аргумент), длина которого указана в третьем аргументе (должна быть на 1 больше, чем длина значения поля, т. е. длина строки);
cgiFormResultType cgiFormStringNoNewlines(char ‘name, char ‘result, int max)
эквивалентна функции cgiFormstring () с тем различием, что она исключает все значки перевода строки, ее рекомендуется использовать для обработки однострочных полей;
cgiFormResultType cgiFormStringSpaceNeeded(char ‘name, int ‘length)
используется при определении длины текстового буфера для приема указанного текстового поля. Длина учитывается вместе с завершающим нулем null, возвращается cgiFormSuccess. Если длина поля не установлена, то устанавливается значение, равное 1, и возвращается cgiFormNotFound;
cgiFormResultType cgiFormStringMultiple(char ‘name, char ‘“ptrToStringArray)
полезна тогда, когда одна форма имеет несколько элементов для ввода с одинаковыми именами, возвращает массив;
void cgiStringArrayFree(char “stringArray)
используется для высвобождения памяти из-под строкового массива, созданного при ПОМОЩИ функции cgiFormStringMultiple();
cgiFormResultType cgiFormlnteger(char ‘name, int ‘result, int defaultV)
получает целое значение, передаваемое в качестве значения элемента формы. Смысл параметров довольно очевиден;
cgiFormResultType cgiFormDouble(char ‘name, double ‘result, double defaultV)
извлекает вещественное значение по имени элемента <input> HTML- формы;
cgiFormResultType cgiFormDoubleBounded(char ‘name, double ‘result, double min, double max, double defaultV)
извлекает вещественное значение по имени элемента <input> HTML- формы. Заданы пределы величины;
cgiFormResultType cgiFormSelectSingle(char ‘name, char “choicesText, int choicesTotal, int ‘result, int defaultV)
извлекает выбранный номер из списка <select> HTML-формы по имени элемента <select>;
cgiFormResultType cgiFormSelectMultiple(char ‘name, char “choicesText, int choicesTotal, int ‘result, int ‘invalid)
извлекает выбранные номера из списка <select> с заданным именем в HTML-форме, допуская множественный выбор. Результат располагается В массиве ChoicesText;
cgiFormResultType cgiFormCheckboxSingle(char ‘name)
извлекает информацию о том, установлен ли флажок в поле по имени этого поля, возвращает cgiFormSuccess, если поле отмечено, или cgiFormNotFound, если поле не отмечено;
cgiFormResultType cgiFormCheckboxMultiple(char ‘name, char “valuesText, int valuesTotal, int ‘result, int ‘invalid)
извлекает информацию о полях с установленными флажками, помещая результат В массив valuesText;
cgiFormResultType cgiFormRadio(char ‘name, char “valuesText, int valuesTotal, int ‘result, int defaultV)
извлекает имена радиокнопок, на отмеченный выбор указывает внутренний указатель;
void cgiHeaderLocation(char ‘redirectUrl)
осуществляет перенаправление;
void cgiHeaderStatus (int status, char *statusMessage)
передает клиенту статус-код;
void cgiHeaderContentType(char ‘mimeType)
передает клиенту тип содержимого, например text/html, text/piain или image/gif ИЛИ audio/basic;
int cgiMain()
основная функция, куда записываются все пользовательские инструкции;
char ‘cgiServerSoftware
имя серверного программного продукта;
char ‘cgiServerName
имя сервера; '
char ‘cgiGatewaylnterfасе
имя интерфейса (CGI/1.1);
char ‘cgiServerProtocol
протокол (НТТР/1.0);
char ‘cgiServerPort
серверный порт;
char ‘cgiRequestMethod
метод, использованный запросом (get или post);
char ‘cgiScriptName
имя скрипта;
char *cgiRemoteHost
имя удаленного хоста, где расположен браузер;
char *cgiRemoteAddr
IP клиентского браузера;
char *cgiContentType
тип кодировки MIME-данных, посланных пользователем;
char *cgiAccept■
список используемых кодировок MIME;
char *cgiUserAgent
имя пользовательского браузера;
char *cgiReferrer
URL страницы, с которой осуществлен переход;
int cgiContentLength
количество байтов запроса;
FILE *cgiOut
указатель на поток вывода;
FILE *cgiln
указатель на поток ввода;
cgiEnvironmentSuccess
определяет, было ли чтение или запись окружения удачным.
Мы рассмотрели особенности библиотеки cgic. Понятно, что при использовании этой библиотеки, язык C++ позволяет создавать приложения любой сложности. Это могут быть, в частности, работа с базами данных, распределенные приложения, работа с сетью и т. п. Далее мы немного остановимся на рассмотрении некоторых деталей протокола HTTP, так как знание этого протокола наиболее важно при программировании CGI-приложений, если приложение общается напрямую с клиентским браузером. Основное внимание мы уделим сообщениям HTTP.
Протокол HTTP
Протокол HTTP — это протокол транспортного уровня, он используется для осуществления общения между клиентом-браузером и Web-сервером. Протокол основан на обмене сообщениями: клиент посылает запрос, а сервер посылает ответ. Клиент создает связь с сервером, посылает серверу запрос с указанием методов, версии протокола, сообщением, зашифрованном в виде MIME, клиентскую информацию. Сервер отвечает с указанием строки
статуса, где есть версия протокола и код выполнения (удачный или ошибка), затем следует тело ответа в MIME-кодировке.
Некоторые обозначения
OCTET = <ЛЮБАЯ ПОСЛЕДОВАТЕЛЬНОСТЬ 8-БИТОВЫХ ДАННЫХ> CHAR = <любой символ US-ASCII (octets 0 — 127)> UPALPHA = <любой заглавный символ US-ASCII "A".."Z"> LOALPHA = <любой строчный символ US-ASCII "a"..”z"> ALPHA = UPALPHA | LOALPHA
DIGIT = <любая цифра "0".."9">
CTL = <любая управляющая последовательность (octets 0-31) и DEL (127)>
CR = <US-ASCII CR,
возврат каретки (13)>
LF = <US-ASCII LF,
перевод строки (10)>
SP = <US-ASCII SP,
пробел (32)>
HT = <US-ASCII HT,
горизонтальная табуляция (9)
<"> = <US-ASCII двойные кавычки (34)>
CRLF = CR LF
LWS = [CRLF] 1*(SP | HT)
TEXT = <любой OCTET, кроме CTL, но включая LWS> HEX = "A" | "B" | "С" I "D" | "E" | "F" | "a" | "b" [ "с" | "d" | "e" | "f" | DIGIT word = token | quoted-string token = 1*<любая CHAR, кроме CTL или tspecials> tspecials = "(" I ")" I "<" I ">" I "0" I "," I ";" I ":"
| ll^ff |<”>[11^'1|11 £ ••| If ] II |И911 j It — II I { 11
"}" | SP | HT comment = "(" *(ctext | comment) ")" ctext = <любой TEXT, включая " (" и ")"> quoted-string = (<"> *(qdtext) <">) qdtext = <любой CHAR, кроме <"> и CTL, но включая LWS>
Параметры протокола
Версия HTTP
HTTP-VersionHTTP-Version= "HTTP" "/" 1*DIGIT "." 1*DIGIT
HTTP-Version
HTTP-Version
Универсальный идентификатор ресурса URI
Синонимами этого термина являются www-адрес, идентификатор документа. URI — это строка, сформатированная стандартным образом, которая сообщает о местоположении ресурса.
Синтаксис URI
URI = (absoluteURI | relativeURI) [ "#" fragment ] absoluteURI = scheme ":" *(uchar | reserved) relativeURI = net_path | abs_path | rel_path net_path = "//" net_loc [ abs_path ] abs_path = "/" rel_path•
rel_path = [ path ] [ ";" params ] [ "?" query ] path = fsegment *("/" segment) fsegment = l*pchar segment = *pchar params = param *(";" param) param = *(pchar | "/") scheme = 1*(ALPHA I DIGIT | "+" | "-" | ".") net_loc = *(pchar I ";" | "?") query = *(uchar | reserved) fragment = *(uchar | reserved) pchar = uchar I ":" | "@" ] "&" | "=" | "+" uchar = unreserved | escape■
unreserved = ALPHA I DIGIT | safe | extra | national escape = "%" HEX HEX
reserved = ";" | "/" I extra = "!" | "*" | ""' safe = "$" I "-" | "_" unsafe = CTL I SP I <">reserved = ";" | "/" I extra = "!" | "*" | ""' safe = "$" I "-" | "_" unsafe = CTL I SP I <">n*)ii । if . n ।|| ff—_h | n_|_ff
reserved = ";" | "/" I extra = "!" | "*" | ""' safe = "$" I "-" | "_" unsafe = CTL I SP I <">
reserved = ";" | "/" I extra = "!" | "*" | ""' safe = "$" I "-" | "_" unsafe = CTL I SP I <">
| II ff |1111[ ft 11
IIII
national = <any OCTET excluding ALPHA, DIGIT, reserved, extra, safe, and unsafe>
Сообщения HTTP
HTTP-сообщения состоят из запросов клиента серверу и ответов сервера клиенту:
HTTP-message = Simple-Request I Simple-Response
I Full-Request I Full-Response
Full-Request = Request-Line
* (General-Header I Request-Header I Entity-Header) CRLF
[ Entity-Body ] Full-Response = Status-Line *(General-Header I Response-Header I Entity-Header) CRLF [ Entity-Body ]
Простые ответы И простые запросы Simple-Request И Simple-Response Не могут пересылать информацию в заголовках HTTP-сообщений и ограничиваются использованием метода get: Simple-Request = "GET" SP Request-URI CRLF Simple-Response = [ Entity-Body ]
Заголовки сообщений
HTTP-сообщения могут содержать заголовки, которые, в свою очередь, могут содержать несколько строк, при этом каждая новая строка должна начинаться с элемента sp или элемента ht.
HTTP-header = field-name ":" [ field-value ] CRLF field-name = token field-value = *(field-content I LWS) field-content = <набор, состоящий из OCTET и составляющий field-value, представляющий собой или *ТЕХТ, или комбинацию из token, tspecials, quoted-string>
Основные поля заголовка
Как правило, заголовок имеет стандартные, часто используемые поля.
General-Header = Date I Pragma
Запросы
Запросы (Requests) посылаются клиентом серверу. Синтаксис запроса таков:
Request = Simple-Request | Full-Request
Simple-Request = "GET" SP Request-URI CRLF
Full-Request = Request-Line
*(General-Header
I Request-Header
I Entity-Header)
CRLF
[ Entity-Body ]
Строка запроса Request-Line
Строка запроса состоит из указания метода, идентификатора URI и номера версии протокола HTTP:
Request-Line = Method SP Request-URI SP HTTP-Version CRLF
Разница между простым и полным запросом состоит в том, что, в отличие от простого запроса, полный запрос содержит в себе информацию о версии протокола HTTP, а также в нем могут использоваться различные методы, а не только метод get.
Методы
Существуют следующие методы (методы чувствительны к регистру):
Method = "GET"
| "HEAD"
I "POST"
I extension-method
extension-method = token
Если указанный в полном запросе метод не опознан, то сервер должен вернуть код статуса 501.
Запрашиваемый URI Request-URI
Запрашиваемый ресурс указывается в форме URI:
Request-URI = absoluteURI | abs_path
Например (абсолютный URI):
GET http://www.w3.org/pub/WWW/TheProject.html НТТР/1.0
или (абсолютный путь)
GET /pub/WWW/TheProject.html НТТР/1.0
Поля заголовка запроса Request-Header
Заголовок запроса может содержать дополнительную информацию о запросе и клиенте. Эти поля служат в качестве своеобразных модификаторов запроса:
Request-Header = Authorization
I From
I If-Modified-Since
I Referer
I User-Agent
Ответ
После получения и обработки запроса, сервер посылает клиенту ответ:
Response = Simple-Response ] Full-Response Simple-Response = [ Entity-Body ] Full-Response = Status-Line
*(General-Header
I Response-Header
I Entity-Header)
CRLF
[ Entity-Body ]
Простой ответ посылается только в ответ на простой запрос.
Строка состояния Status-Line
Полный ответ содержит в себе строку состояния:
Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF.
Строка состояния всегда начинается с указания используемой версии протокола HTTP:
"HTTP/" 1*DIGIT "." 1*DIGIT SP 3DIGIT SP.
Код статуса Status-Code и пояснение Reason-Phrase
Код статуса — это трехзначное число (смысл статус-кода мы уже рассматривали раньше):
Ixx: Informational — не используется. Зарезервировано на будущее;
2хх: Success — удачное исполнение;
Зхх: Redirection — необходимо предпринять дополнительные действия для обработки запроса;
4хх: Client Error — запрос содержит синтаксические ошибки или не может быть выполнен;
5хх: Server Error — сервер не может выполнить запрос.
Некоторые стандартные значения статус-кодов:
Status-Code = "200";ОК
I "201";Created
I "202";Accepted
I "204";No Content
I "301";Moved Permanently
I "302";Moved Temporarily
I "304";Not Modified
I "400";Bad Request
I "401";Unauthorized
I "403";Forbidden
I "404";Not Found
I"500";Internal ServerError
I"501";Not Implemented
I"502";Bad Gateway
I"503";Service Unavailable
I extension-code extension-code = 3DIGIT Reason-Phrase = *<TEXT, excluding CR, LF>
Заголовки ответа
Ответ сервера содержит заголовок ответа:
Response-Header = Location
I Server
I WWW-Authenticate
Сущность сообщения Entity
Сообщения-запросы и сообщения-ответы могут содержать в себе сущности, т. е. некоторую информацию, важную для данного сообщения.
Заголовок Entity-Header
Заголовок может содержать дополнительную мета-информацию о том, что содержит тело сущности:
Entity-Header = Allow
I Content-Encoding
I Content-Length
I Content-Type
I Expires
I Last-Modified
I extension-header
extension-header = HTTP-header
Неопознанные заголовки игнорируются. Если используется прокси-сервер, то он передает их без изменения.
Тело сущности Entity-Body
Тело сущности, если оно присутствует, посылается вместе с НТТР-запросом или ответом в формате, определяемом в полях заголовка сущности EntityHeader. Тело сущности выглядит так: Entity-Body = *ОСТЕТ
Типы Туре
Тип данных тела сущности entity-body определяется при помощи такой конструкции:
entity-body := Content-Encoding(Content-Type(data))
Методы
Рассмотрим стандартные методы:
Метод get используется для получения любой информации, указанной в запросе, в виде сущности;
Метод HEAD
идентичен методу get, однако сервер не обязан пересылать в ответ тело какой-либо сущности;
Метод post
используется для того, чтобы сообщить серверу о том, что запрос содержит сущность. Реальные действия, производимые методом post, определяются сервером.
Глава 8
Работаем с J2EEРаботаем с J2EEВ ряде языков общего назначения особенно выделяется язык Java. Именно этот язык наиболее приспособлен для решения задач, связанных с интер- нет-программированием. Создание распределенных приложений в последнее время приобретает все большую популярность благодаря новым возможностям, предоставляемым современными технологиями разработки интернет-приложений. Созданные на их основе приложения отличаются большой производительностью, скоростью, надежностью, безопасностью. Разработчики, участвующие в создании интернет-проектов, связанных с электронной коммерцией, информационными технологиями, не могут обойти стороной современные методы интернет-программирования, благодаря которым процесс разработки приложений становится сравнительно простым, менее дорогостоящим, наиболее быстрым и эффективным, отнимающим меньшее количество ресурсов, чем требовалось для выполнения аналогичной работы ранее. Новая версия пакета средств разработки приложений на языке Java, которая полностью называется Java 2 Platform Enterprise Edition, или сокращенно J2EE, представляет собой технологию, основанную на возможности разработки и многократного использования компонентов, объединяющихся в распределенные серверные модули. J2EE использует модель многопоточных серверных компонентов, которые могут быть повторно использованы. Технология основывается на использовании метаязыков описания компонентов и их размещения с применением средств языка XML.
Работаем с J2EE
Работаем с J2EE
Современное программирование на языке Java использует богатый набор средств, упрощающих работу с распределенными многопоточными приложениями, компонентами пакета J2EE, клиентами J2EE, Web-компонентами, уровнем информационной системы предприятия, бизнес-компонентами, контейнерами J2EE, службами контейнеров, стандартными утилитами упаковки приложений, установкой уровней безопасности и другими полезными средствами.
Обзор возможностей современного интернет-программирования на языке Java
В этом разделе мы кратко остановимся на рассмотрении основных типов приложений, написанных на языке Java, которые создаются специально для работы в сети Интернет с применением технологии J2EE. Ранее в гл. 6 мы уже работали с апплетами. Создание апплетов происходит на основе пакетов, входящих в состав JDK1.3, предоставляющего основные средства Java. При этом класс апплета основан на классах и интерфейсах пакета java.applet. J2SE содержит возможности, предоставляемые пакетом swing, который, в частности, позволяет создавать апплеты, работающие в составе многих Web-браузеров и которые создаются на основе класса JAppiet пакета javax.swing.
J2EE содержит пакет javax.servlet. Классы и интерфейсы, содержащиеся в этом пакете, используются для создания сервлетов. Сервлеты представляют собой приложения, выполняемые на Web-сервере, обращение к которым происходит, как правило, с Web-клиентов. Частным случаем Web-клиента могут служить серверные страницы Java (JSP), с помощью которых браузер, получающий HTML-код, генерируемый JSP, может обращаться к сервлету, отправляя ему HTML-форму. Серверные страницы JSP представляют собой своеобразную разновидность технологии сервлетов (JSP-страницы вначале автоматически трансформируется в сервлет), призванную обеспечить наиболее удобный метод создания пользовательского интерфейса приложения, концентрируясь при этом на дизайне, когда основное внимание разработчика привлекает фронт-енд, т. е. то, как будет представлен документ пользователю, "лицо приложения". Серверные страницы JSP как бы отделяют разработку функциональной части серверного приложения от разработки пользовательского интерфейса, реализуемого средствами HTML или средствами других языков интернет-программирования. Например, средствами XML или XSL, задача которых наиболее функционально и адекватно представить клиентский документ пользователю.
Пакет J2EE предоставляет средства разработки серверных компонентов, в число которых входят компоненты EJB. Интерфейс серверных компонентов EJB предназначен для создания надежных серверных компонентов, призванных решать основные задачи, возникающие в процесс создания серверных приложений (обработка клиентских запросов, работа с внешними ресурсами, с базами данных, организация сетевых соединений, обеспечение безопасности, многопоточности, синхронизации и т. п.). Эти задачи разработчики были вынуждены решать по старинке. С использованием средств пакета J2EE решается вопрос экономии времени, затрачиваемого на создание таких приложений. Создаваемые приложения отличаются надежностью, безопасностью, быстротой в работе. Благодаря своей структуре, создаваемые
компоненты могут быть распределены в сети, находясь на различных виртуальных машинах Java. Компоненты EJB работают на серверах EJB, в средах, предоставляемых контейнерами EJB, которые имплементируют интерфейсы пакетаjavax.ejb.
Сервисы и контейнеры J2EE
Клиентские приложения, так называемые "тонкие клиенты", оказываются довольно сложными при разработке. Так, во время их создания необходимо учитывать множество деталей, в число которых входят самостоятельное проведение транзакций (с учетом безопасности и многопоточности), поддержание состояний, создание пула ресурсов и учета прочих деталей, возникающих при достаточно низкоуровневом программировании, к которому необходимо было прибегать при создании приложений традиционными методами, с применением сокетов или средств RMI (вызов удаленных методов, Remote Methods Invocation). Создание таких приложений, с использованием основанной на применении платформенно-независимых компонентов архитектуры J2EE, облегчено, поскольку бизнес-логика приложений облачена в многократно используемые модули, на основе которых автоматически создаются объекты, а разработка таких модулей использует стандартные средства. Архитектура J2EE освобождает разработчика от необходимости создания многих элементов, которые требуются при работе сервера. 12ЕЕ-сервер предоставляет набор необходимых сервисов, организованных в виде контейнеров. Для каждого типа компонентов предоставляется свой собственный набор сервисов в соответствии с интерфейсами, описанными в пакете javax.ejb. Разработчику нет нужды повторять заново то, что уже создано, и он может сосредоточиться на решении принципиально значимых задач, не отвлекаясь на низкоуровневое программирование.
Контейнеры — это интерфейсы между компонентами и функциями низкого уровня, необходимые для работы компонентов и выполняемые сервером. Компонентами могут быть не только EJB, в качестве компонентов приложения могут выступать также Web-компоненты, самостоятельные приложения-клиенты. Перед тем как компонент будет использован, приложение необходимо "собрать" и разместить его в контейнер. Процесс сборки состоит в задании параметров для каждого приложения J2EE и каждого компонента, входящего в состав этого приложения. Параметры размещения используются для задания уровней безопасности, поддержания работы с транзакциями, для поиска имен с использованием интерфейса JNDI (Java Naming and Directory Interface), установки удаленных соединений. Модель безопасности, используемая в J2EE, позволяет ограничивать доступ к Web- компонентам и компонентам EJB, позволяя обращаться к ним только тем пользователям, кому это разрешено. Поддержка транзакций позволяет объединить несколько методов в блок, который будет выполняться как одно
целое. При этом невозможно одновременное обращение к ресурсу, используемому в транзакции, из другой транзакции. Службы поиска интерфейса JND1 позволяют работать с именами и каталогами. Удаленный доступ между клиентами и серверными компонентами поддерживается автоматически. Вызов методов компонентов EJB происходит таким же образом, как если бы этот компонент находился на той же самой виртуальной машине, что и клиент. Контейнер предоставляет ряд управляемых сервисов, к числу которых относится, например, задание условий доступа к ресурсам, в том числе к базам данных. Часть доступных сервисов не относится к числу управляемых. Разработчик не может управлять жизненным циклом компонентов EJB, персистентными соединениями и некоторыми другими сервисами. Организация персистентных соединений с базами данных, относящаяся к числу неуправляемых сервисов, тем не менее может быть организована вручную при помощи средств, которые при этом необходимо будет имплементировать в классе компонента EJB. Общая архитектура приложения J2EE показана на рис. 8.1.
Архитектура J2EE предусматривает наличие трех типов контейнеров. Все контейнеры входят в состав J2EE-cepBepa. Контейнер серверных компонентов EJB используется для размещения серверных компонентов EJB. Контейнер клиентских приложений необходим для работы клиентов, взаимодействующих с серверными компонентами. Контейнер апплетов используется для выполнения приложений апплетов. Этот контейнер представляет собой Web-бразуер, в состав которого включена возможность для работы с апплетами.
Компоненты приложения существуют самостоятельно, но организуются вместе, образуя приложение, которое размещается на сервере. Все файлы приложения, включая файлы классов, вспомогательные файлы, например, картинки, клиентские файлы (такие как HTML, XML, XSL, CSS, DTD и пр.), а также файл описателя размещения, объединяются в самостоятельный модуль и вставляются в приложение. Приложение состоит из одного или нескольких компонентов EJB, модуля Web-клиента или модуля самостоятельного клиента. Законченное приложение J2EE может содержать одно или несколько самостоятельных приложений J2EE, конфигурация зависит от требований дизайна.
Каждое приложение J2EE и каждый модуль приложения имеют свой описатель размещения (дескриптор размещения). Описатель размещения организован в виде XML-документа, который хранится в файле с расширением xml, и содержит параметры размещения компонента или приложения. Так, описатель размещения компонента EJB содержит параметры транзакций, параметры доступа, определяющие уровни безопасности компонента. Все указываемые параметры не зависят от программного кода, имплементирующего компонент. Эти параметры можно изменять, не меняя программного кода компонента. Дескриптор размещения читается сервером J2EE во время работы сервера. Все приложения J2EE и входящие в его состав модули объединяются в файл архива серверного приложения, в файл EAR (Enterprise Archive). Расширением файла архива является ear. Утилита размещения (менеджер размещения) приложений предоставляет удобный графический интерфейс для упаковки готовых приложений в файл EAR. С помощью менеджера размещения мы создаем файл EAR, а затем вставляем в него готовое приложение. При использовании утилит упаковки, работающих в командной строке, вначале создаются файлы архивов JAR и WAR, а затем приложение упаковывается в архив WAR. Каждый архив JAR, содержащий компоненты EJB, включает в свой состав дескриптор размещения, файлы компонента EJB и связанные с этими компонентами файлы, которые необходимы для функционирования компонентов. Каждый клиентский архив JAR состоит из дескриптора размещения файлов классов клиентского приложения и файлов, необходимых для работы этого приложения. Каждый архив приложения WAR состоит из дескриптора размещения, файлов Web-компонентов и необходимых для правильной работы этих компонентов файлов ресурсов. Использование файлов EAR позволяет создавать несколько приложений, в которых повторно используются одни и те же компоненты, при этом нет необходимости создавать дополнительный программный код.
Стандартная версия платформы J2SE предоставляет основные средства программного интерфейса, которые также используются в процессе создания компонентов J2EE, утилиты для разработки, программное обеспечение, реализующее средства виртуальной машины Java. Для работы пакета J2EE
необходимо установить пакет J2SE. В состав пакета J2EE включены следующие возможности:
Технология серверных компонентов EJB. Компонент EJB представляет собой фрагмент кода, имплементирующего бизнес-логику приложения. Компонент EJB — это своеобразный блок, используемый отдельно или в сочетании с другими блоками для реализации бизнес-логики приложения, который выполняется на сервере J2EE. Существует три типа компонентов EJB — это компоненты сессий (session bean), компоненты сущностей (entity bean), компоненты, основанные на обработке сообщений (message-driven bean). Одним из достоинств компонентов сущностей является направленность этих компонентов на работу с базами данных. Компоненты сущностей позволяют избежать использования запросов SQL или программного интерфейса JDBC при обращении к базам данных. Запрос выполняется контейнером компонентов EJB. При обращении к базам данных из компонентов сессий или, при необходимости из компонентов сущностей, возможность использования SQL-запросов и средств JDBC сохраняется.
Программный интерфейс JDBC позволяет формировать SQL-запросы средствами языка Java. Интерфейс JDBC может быть применен в компонентах сущностей, если не используется постоянное соединение, реализуемое средствами контейнера. Иначе нет необходимости создавать запросы средствами SQL или JDBC. Использование JDBC полезно в сервлетах и JSP-страницах. Средства разработки приложений JDBC платформы J2EE состоят из двух частей. Первая часть используется при создании компонентов приложения, из которых производится обращение к базам данных, вторая часть состоит из средств, поддерживающих работу программного интерфейса JDBC на платформе J2EE.
Технология сервлетов позволяет работать с HTTP-приложениями, обрабатывать запросы HTTP. Классы сервлетов расширяют возможности серверов. Как правило, сервлеты используются для расширения возможностей приложений, размещенных на Web-сервере или на прочих серверах, работа которых основывается на обмене сообщениями, состоящими из запросов к серверу и ответов сервера на получаемые запросы. Сервлеты, созданные на основе технологии Java Servlet Technology 2.3, позволяют создавать классы, специально предназначенные для работы с протоколом HTTP.
Серверные страницы JSP представляют собой текстовые документы, состоящие как из статического текста, который может быть записан в виде любого статического формата, например, как текст HTML, WML, XML, XSL и т. п., а также из динамических элементов JSP.
Сервис сообщений Java Message Service 1.0 используется для создания, отсылки, получения и чтения сообщений. При помощи сервиса сообщений
возможна организация удаленной коммуникации, при этом коммуникация оказывается надежной, не отвлекает основные ресурсы.
Интерфейс имен и каталогов Java Naming and Directory Interface 1.2 используется для выполнения стандартных операций сопоставления имен объектам и ресурсам, поиска объектов. С его помощью можно сохранять и извлекать любые именованные объекты.
Программный интерфейс для работы с транзакциями Java Transaction API (JTA) помогает при организации транзакций. Он предоставляет средства подтверждения транзакции и средства отката текущей транзакции.
Программные средства почты JavaMail API 1.2 состоят из двух частей. Первая часть используется в приложениях и реализует программный интерфейс, используемый в приложениях, вторая часть предоставляет средства для работы с почтой на платформе J2EE.
Программный интерфейс для обработки XML (JAXP 1.1) позволяет обрабатывать XML-документы с использованием средств DOM, SAX, XSLT. Средства JAXP позволяют анализировать и преобразовывать документ XML. Так, например, приложение J2EE может создавать отчеты на основе XML. При этом отчеты для разных заказчиков могут выглядеть по- разному, в соответствии со специфическими требованиями того или иного заказчика.
Мы перечислили наиболее важные и заметные службы, используемые в пакете J2EE.
Платформа J2EE содержит ряд утилит, применяемых для "сборки" и размещения приложений. Менеджер размещения (утилита deploytool) предоставляет графический интерфейс, с помощью которого процесс сборки и размещения приложения осуществляется легко и удобно. Помимо режима графического интерфейса, утилита может быть использована в режиме командной строки. Графический интерфейс предоставляет несколько проводников. Среди проводников можно назвать проводник упаковки, конфигурирования и размещения 12ЕЕ-приложений, проводник упаковки и конфигурирования компонентов EJB, компонентов Web, приложений-клиентов, адаптеров ресурсов. Помимо проводников, менеджер размещения предоставляет средства, с помощью которых можно задать параметры конфигурации для каждого типа компонентов и модулей. Часть утилит представляет собой скрипты, призванные решать определенные "узкие" задачи. Скрипты выполняются в командной строке. Утилита j2ee запускает и останавливает сервер J2EE. Скрипт cloudscape используется для запуска и остановки используемой по умолчанию базы данных. Скрипт j2eeadmin служит для установки драйверов JDBC, мест назначений служб JMS и заданий конфигураций для прочих служб и ресурсов. Утилита keytool используется для генерации ключей и сертификатов, используемых в шифровании. Утилита realmtool применяется для работы с сертификатами и списками аутентифи-
цируемых пользователей. Утилита packager упаковывает компоненты J2EE в архивы EAR, JAR, WAR. Утилита runclient запускает 52ЕЕ-клиент. Утилита cleanup используется для удаления всех размещенных на 12ЕЕ-сервере приложений.
Платформа J2EE использует модель многопоточных распределенных приложений. Логика приложения распределяется между несколькими приложениями в соответствии с функциями, выполняемыми этими приложениями. Приложения могут располагаться на различных машинах, это зависит от того, к какому уровню относятся приложения. Среда, в которой работают приложения, предоставляет средства, позволяющие одновременную параллельную работу нескольких потоков. В целом приложение распределяется между несколькими уровнями:
клиентский уровень. Приложение этого уровня выполняется на клиентской машине;
уровень Web-приложения. Выполняется на J2EE-cepeepe;
уровень бизнес-логики приложения. Выполняется на J2EE-cepeepe;
уровень информационной системы предприятия. Выполняется на сервере EIS.
ПервоеприложениеEJBПервоеприложениеEJBБаза данныхБаза данныхПриложение- клиентПриложение- клиентВторое приложние EJBВторое приложние EJBКлиентскийуровеньКлиентскийуровеньУровеньWeb-приложенияУровеньWeb-приложенияБизнес-уровеньБизнес-уровеньУровеньинформационнойсистемыпредприятияУровеньинформационнойсистемыпредприятияКлиентский компьютерКлиентский компьютерКомпьютер сервера J2EEКомпьютер сервера J2EEКомпьютер базы данныхКомпьютер базы данных
ПервоеприложениеEJB
ПервоеприложениеEJB
База данных
База данных
Приложение- клиент
Приложение- клиент
Второе приложние EJB
Второе приложние EJB
Клиентскийуровень
Клиентскийуровень
УровеньWeb-приложения
УровеньWeb-приложения
Бизнес-уровень
Бизнес-уровень
Уровеньинформационнойсистемыпредприятия
Уровеньинформационнойсистемыпредприятия
Клиентский компьютер
Клиентский компьютер
Компьютер сервера J2EE
Компьютер сервера J2EE
Компьютер базы данных
Компьютер базы данных
Рис. 8.2. Многоуровневая структура распределенного приложения
Как правило, приложение J2EE (которое может состоять из 3 или 4 уровней) рассматривается в рамках трехуровневой модели, поскольку они распределены между тремя различными местоположениями. Это клиентский компьютер, машина, на которой работает сервер J2EE, машина, на которой работает база данных, и прочие средства (рис. 8.2).
Компоненты J2EE относятся к одному из следующих типов:
приложения — клиенты и апплеты (клиентские приложения);
сервлеты и серверные страницы JSP. Эти приложения образуют Web- компоненты и выполняются на сервере;
компоненты EJB — это бизнес-компоненты приложения, выполняются на сервере.
Все компоненты J2EE создаются с применением языка программирования Java и компилируются в обычном порядке. Основное отличие компонентов J2EE от "обычных" приложений Java состоит в том, что компоненты J2EE объединяются в приложения J2EE и размещаются на сервере с использованием дескрипторов размещения.
Клиентские приложения
Клиентом J2EE может быть как Web-клиент, так и независимый клиент, созданный в виде самостоятельного приложения.
Web-клиент
Web-клиент состоит из двух частей. Первая часть — это динамические Web- страницы, созданные на основе различных языков, например, HTML, XML, XSL и т. п. Эти динамические страницы генерируются Web-компонентами, работающими на уровне Web-приложений. Вторая часть — это Web- браузеры, которые отображают полученные от сервера страницы. Web- клиент иногда называют "тонким" клиентом. Тонкий клиент, как правило, не производит обращений к базам данных, не выполняет сложных бизнес- методов, не соединяется с приложениями, используемыми сервером. Все перечисленные операции, для выполнения которых требуются значительные ресурсы, выполняются на сервер J2EE. При этом обеспечивается безопасность, высокая скорость, надежность, свойственные технологии J2EE.
Апплет
Уровень Web-приложения может создать и отправить клиенту страницу, содержащую апплет. Апплет — это небольшое клиентское приложение, которое выполняется виртуальной машиной, входящей в состав браузера.
Клиент-приложения
Клиент-приложение выполняется на клиентской машине, он не зависит от браузера, разработчик имеет больше возможностей, чем при работе с клиентом
на основе языков разметки. Как правило (однако это вовсе не обязательно), такой клиент использует графический интерфейс для общения с пользователем, который создается с использованием пакетов swing или awt. Клиентское приложение может напрямую обращаться к серверным компонентам, работающим на уровне сервера.
Сервер и клиент могут использовать компоненты JavaBeans ("классические" JavaBeans).
Работа сервера J2EE
На уровне сервера функционируют различные компоненты приложения (рис. 8.3).
Сервер J2EEСервер J2EEКлиентский уровень
Сервер J2EE
Сервер J2EE
Рис. 8.3. Компоненты приложения
Web-компоненты
В качестве Web-компонентов могут выступать либо сервлеты, либо серверные страницы JSP. Сервлеты представляют собой Java-классы, которые динамически обрабатывают запросы и посылают ответы. Серверные страницы JSP — это текстовые документы, которые содержат в себе встроенную функциональность, реализуемую средствами JSP. Статические страницы HTML (и подобные им) и апплеты вставляются в Web-приложение в процессе упаковки и размещения компонента (рис. 8.4).
Клиентский уровеньКлиентский уровеньСерверJ2EEСерверJ2EE
Клиентский уровень
Клиентский уровень
СерверJ2EE
СерверJ2EE
Рис. 8.4. Web-компоненты приложения
Бизнес-компоненты
На уровне бизнес-приложения выполняется программный код, связанный с выполнением основных бизнес-методов. Это могут быть функции, поддерживающие банковские операции и пр. На этом уровне работают все три типа компонентов EJB (рис. 8.5).
Браузер,Web-страницы,апплеты,компонентыJavaBeansБраузер,Web-страницы,апплеты,компонентыJavaBeansУровень Web-приложенияУровень Web-приложенияБизнес-уровеньБизнес-уровеньУровень информационной системы предприятияУровень информационной системы предприятия
Браузер,Web-страницы,апплеты,компонентыJavaBeans
Браузер,Web-страницы,апплеты,компонентыJavaBeans
Уровень Web-приложения
Уровень Web-приложения
Бизнес-уровень
Бизнес-уровень
Уровень информационной системы предприятия
Уровень информационной системы предприятия
СерверJ2EEСерверJ2EEданных и прочееданных и прочее
СерверJ2EE
СерверJ2EE
данных и прочее
данных и прочее
Клиентское приложение (с компонентами JavaBeans)
Клиентский уровень
Рис. 8.5. Бизнес-уровень и уровень информационной системы
Уровень информационной системы предприятия
Уровень информационной системы предприятия служит для выполнения основных функций, обеспечивающих информационную деятельность предприятия. Это может быть осуществление транзакций в системе предприятия, работа с базами данных и пр.
Рассмотренные выше методы представляют собой современный подход к созданию распределенных систем на основе языка Java. Современные методы "утилизируют" возможности более ранних технологий, в том числе технологии вызова удаленных методов (RMI). В свою очередь, технология RMI основывается на методах работы с сокетами. Далее мы кратко обсудим, что представляет собой технология RMI, рассмотрим на примере возможности сетевого программирования с применением сокетов и перейдем к более сложному примеру, который посвящен методам создания серверных компонентов EJB.
Технология вызова удаленных методовRMI
Технология вызова удаленных методов (RMI, Remote Method Invocation) позволяет обращаться к методам объектов, работающих на другой виртуальной машине Java, отличающейся от той, на которой работает вызывающая эти методы программа. Вызов удаленных методов позволяет различным программам, созданным с применением языка Java, взаимодействовать друг с другом. Для того чтобы программа могла вызывать методы другого приложения, создается приложение-сервер. Методы сервера могут быть вызваны из другой самостоятельной программы-клиента. Приложение-сервер создает удаленные объекты, ссылки на которые должны быть доступны клиенту. Сервер ожидает клиентских запросов, которые вызывают методы объектов сервера. Как правило, клиент получает удаленные ссылки на один или несколько объектов сервера, на которых он может вызывать методы. Технология RMI предоставляет механизм, посредством которого клиент и сервер могут общаться друг с другом, передавая информацию как от клиента к серверу, так и от сервера клиенту. Такие приложения можно называть приложениями на основе распределенных объектов.
Приложения с распределенными объектами должны локализовать удаленный объект. Чтобы удаленный объект стал доступен, его необходимо зарегистрировать при помощи утилиты rmiregistry, тогда ссылка на этот объект станет доступна клиенту (рис. 8.6). Кроме этого, приложение может передавать ссылки в ходе нормального функционирования. Клиент должен установить связь с удаленным объектом. Все детали по установке связи возложены на средства RMI, разработчик обращается к методам удаленного объекта так же, как к обычным методам. RMI предоставляет средства для передачи кода объектов, а также для передачи данных. Вызывающая программа может передавать объекты удаленным объектам.
Рис. 8.6. Работа приложений с использованием RMI
RMI позволяет загружать байт-код класса объекта, если этот класс не описан и не определен на виртуальной машине, которая будет получать код. Тип и все поведение объекта, который ранее был доступен только на одной виртуальной машине, будет переведено на другую машину, на удаленную виртуальную машину. Поведение объекта при том не будет изменено.
Удаленные интерфейсы, объекты и методы
Как и прочие приложения, распределенные приложения, построенные на основе RMI, состоят из интерфейсов и классов. Интерфейсы определяют методы, классы имплементируют методы, описанные в интерфейсах, а также могут содержать дополнительные методы, не описанные в интерфейсах. В распределенных приложениях имплементации располагаются на разных виртуальных машинах. Объекты, методы которых доступны из других виртуальных машин, называются удаленными объектами. Для того чтобы объект мог стать удаленным объектом, он должен имплементировать удаленный интерфейс. Удаленный интерфейс создается на основе интерфейса java.rmi.Remote. Помимо прочих исключительных ситуаций, каждый метод удаленного интерфейса должен содержать в своем описании фрагмент throws, связанный С исключением типа java, rmi .RemoteException.
В модели RMI удаленный объект, передаваемый от одной виртуальной машины к другой, отличается от "неудаленного" объекта. Вместо того чтобы передать копию объекта удаленной машине, RMI передает класс stub удаленного объекта. Класс stub работает в качестве прокси-объекта, т. е. объекта, который представляет удаленный объект на той машине, куда он был передан. Приложение, вызывающее удаленный метод, фактически вызывает метод из класса stub, расположенного на той же машине, что и вызывающее приложение. Класс stub удаленного объекта имплементирует такой же набор интерфейсов, что и удаленный объект. Это позволяет приводить объект stub к любому типу в соответствии с имплементированными интерфейсами.
348348Гпава 8
348
348
Создание приложений с использованием RMI
Процесс создания распределенного приложения на основе RMI состоит из следующих этапов:
Разработка и имплементация компонентов распределенного приложения.
Компиляция кода, получение соответствующих классов stub.
Регистрация классов, чтобы классы стали доступны для удаленных программ.
Запуск приложения.
Разработка компонентов
Первая задача, которую должен решить разработчик компонентов,— разработка архитектуры приложения, определение того, какие объекты будут локальными, а какие удаленными. При этом осуществляются следующие шаги:
описание удаленного интерфейса. Удаленный интерфейс описывает методы, которые могут быть вызваны клиентом на удаленном объекте;
имплементация удаленных объектов. Удаленные объекты могут имплементировать один или несколько удаленных интерфейсов. Класс имплементации может имплементировать и другие интерфейсы (локальные или удаленные) и прочие методы, доступные локально. Если в качестве параметров используются типы, соответствующие локальным классам, или если методы возвращают значения типов, описанных в локальных классах, то эти классы также должны быть имплементированы;
имплементация клиента. Клиент может быть имплементирован в любое время, даже после того, как удаленный объект уже был размещен и зарегистрирован.
Компиляция и создание классов Stub
Этап компиляции состоит из двух шагов. На первом шаге используется компилятор javac. С его помощью компилируются исходные файлы, среди которых файлы, содержащие имплементацию удаленных интерфейсов (серверные классы) и клиентские классы. На втором этапе используется компилятор rmic. С его помощью создаются классы stub, соответствующие удаленным объектам. Классы stub удаленных объектов используются для создания прокси-объектов на машинах, обращающихся к удаленным объектам.
Регистрация классов
Все созданные классы, связанные с удаленным интерфейсом, классы stub и другие классы должны быть доступны клиенту. Они должны быть соответствующим образом зарегистрированы на Web-сервере или расположены в таких каталогах, откуда они могут быть свободно получены клиентом.
Запуск приложения
Чтобы запустить распределенное приложение, необходимо запустить регистр удаленных объектов, сервер, затем клиент приложения.
Мы не будем останавливаться на деталях работы с распределенными приложениями на основе RMI. Далее мы остановимся на рассмотрении простых методов работы с сетью на основе сокетов, а затем перейдем к изучению примера создания приложения на основе компонентов EJB.
Java и сокеты
Мы уже упоминали о возможностях работы с сетью. Сейчас мы рассмотрим простое приложение, которое состоит из двух частей: из клиента и сервера. Клиент и сервер могут находиться на разных компьютерах в любой части света, они обмениваются сообщениями. При создании сервера и клиента мы используем сокет — специальный класс, предназначенный для работы с сетью. Программа-сервер работает на компьютере и связана с определенным портом. Сервер ждет запросы к сокету — это его основное назначение. Запросы к сокету посылает клиент. Клиент должен знать адрес машины или имя хоста, где ожидает запросов сервер, кроме того, клиенту должен быть известен порт, на котором "прослушивает" сервер. Если клиент и сервер благополучно соединяются через сокеты, то можно приступать к чтению и записи информации в сокеты, что мы и сделаем в следующем примере.
Класс сокетов хранится в пакете java.net. Создадим файл Client.java.
Файл Clientjava
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args) throws lOException (
Socket kkSocket = null;
Printwriter out = null;
BufferedReader in = null;
try (
kkSocket = new Socket("localhost", 7);
out = new Printwriter(kkSocket.getOutputStream(), true); in = new BufferedReader(new
InputStreamReader(kkSocket.getlnputstream()));
} catch (UnknownHostException е) (
System.err.printin("Host not found");
System.exit(1) ;
} catch (lOException e) (
System.err.printin("No connection to the host");
System.exit(1);
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
String fromServer;
String fromUser;
while ((fromServer = in.readLine()) != null) (
System.out.println("Server replies: " + fromServer);
if (fromServer.equals("Bye.")) break;
fromUser = stdin.readLine();
if (fromUser != null) {
System.out.printin("Client says: " + fromUser); out.printin(fromUser);
out.close();
in.close();
stdin.close();
kkSocket.close();
Компилируем клиент:
javac Client.java
Сейчас нам нужно создать программу-сервер. Запишем ее в файл Server.java.
| Файл Serverjava.
import java.net.*; import java.io.*;
public class Server {
public static void main(String[] args) throws lOException (
ServerSocket serversocket = null;
try {.
serversocket = new ServerSocket(7); } catch (lOException e) { System.err.printin("Could not listen on port: 7."); System.exit(1); }
Socket clientsocket = null;
try ( clientsocket = serverSocket.accept(); } catch (lOException e) { System.err.println("Accept failed."); System, exit (1); }
Printwriter out = new Printwriter(clientSocket.getOutputStreamf) , true);
BufferedReader in = new BufferedReader( new InputStreamReader( clientSocket.getlnputStreamO)); String inputLine, outputLine;
KKProtocol kkp = new KKProtocol();
outputLine = kkp.processinput(null); out.printin(outputLine);
while ((inputLine = in.readLine()) != null) { outputLine = kkp.processinput(inputLine);
out.printIn(outputLine);
if (outputLine.equals("Bye.")) break;
out.close();
in.close ();
clientsocket.close ();
serverSocket.close();
class KKProtocol {
private static final int WAIT = 0;
private static final int NOWAIT = 1;
private int state = WAIT;
public String processinput(String thelnput) { String theOutput = null;
if (state == WAIT) {
theOutput = "Hello there! You are welcome...."; state = NOWAIT;
} else {
theOutput = thelnput;
}
return theOutput; }
Скомпилируем код при помощи команды javac Server.java и запустим сначала сервер, затем клиент. Клиент и сервер могут располагаться на разных компьютерах, при этом необходимо правильно указать имя хоста для клиента. В окне клиента можно напечатать текст, он будет передан серверу и возвращен назад в первозданном виде, как эхо (рис. 8.7).
Если клиент вводит строчку "Вуе", работа прекращается, клиент и сервер закрываются одновременно.
Server: Hello there* You are welcone....
Hello, I an client
Client: Hello, I an client
Server: Hello, I an client
How are you?
Client: How are you?
Server: How are you?
I an working pronptly
Client: I an working pronptly
Server: $ an working pronptly
You do also indeed
Client: You do also indeed
Server: You do also indeed
Рис. 8.7. Клиент и сервер на одном компьютере
Наш сервер страдает одним крупным недостатком — он может работать только с одним экземпляром клиента. Исправим недостаток, создадим поток (легковесный процесс) и напишем сервер на основе потока. Код потока запомним в файле ServerlThread.java.
Файл ServerlThread.java
import java.net.*;
import java.io.*;
public class ServerlThread extends Thread { private Socket socket = null;
public ServerlThread(Socket socket) { super("ServerlThread");
this.socket = socket;
}
public void run() (
try {
Printwriter out = new Printwriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader( new InputStreamReader(
socket.get!nputStream()));
String inputLine, outputLine;
out.printin("Hello!");
while ((inputLine = in.readLine()) != null) (
outputLine = inputLine;.
out.printin(outputLine);
if (outputLine.equals("Bye.")) break;
}
out.close();
in.close ();
socket.close();
) catch (lOException e) ( e.printStackTrace();
)
}
}
Этот поток используется в классе serveri, код которого приведен ниже в файле Serveri.java.
Файл Serveri .java
import java.net. *;
import java.io.*;
public class Serveri (
public static void main(String[] args) throws lOException ( ServerSocket serversocket = null;
boolean listening = true;
try (
serversocket = new ServerSocket(7);
} catch (lOException e) (
System.err.printin("Could not listen on port: 7.");
System.exit(-1);
while (listening)
new ServerlThread(serversocket.accept()).start() ;
serversocket.close();
} }
Легко видеть, что многопоточный вариант выглядит даже более наглядно, чем первоначальный однопоточный сервер. Скомпилируем и запустим сервер. Сейчас к нему можно обратиться сразу из нескольких клиентов (рис. 8.8).
l<”<;C:WINNT4xysle«3.?\i4¥й.
Server: Hello?
Hi, Ьча client 1
Client: Hi, Ina client 1
Server: Hi, Iwa client 1 first Client is calling....
Client: first Client is calling....
Server: first Client is calling....
C/WINH Ги^ет^1?Х|<^
iSeruer: Hello?
Seconf client iClient: Seconf client 'Server: Seconf client
|,?A CAWINNTAsj^le^
Server: Hello?
Hi. This is client no 3
Client: Hi. This is client no 3
Server: Hi. This is client no 3 Houq are you doing?
Client: Howq are you doing7
Art J axrt jaArt J axrt jaServer: Howq are you doing?
Art J a
xrt ja
Art J a
xrt ja
Рис. 8.8. Многопоточный сервер
"Бешеный" клиент
С клиентом и сервером можно экспериментировать часами. Завершим наш краткий экскурс в мир клиент-серверных приложений примером "бешеного" клиента, который зацикливается на передаче своей информации серверу. Рассмотрим пример файла Clientl.java.
i Файл Clientl Java import java.io.*;
' import java.net.*;
public class Clientl (
public static void main(String[] args) throws lOException ( int kk = 0;
Socket kkSocket = null;’
Printwriter out = null;
BufferedReader in = null;
try ( kkSocket = new Socket("localhost", 7); out = new Printwriter(kkSocket.getOutputStream(), true); in = new BufferedReader(new
InputStreamReader(kkSocket.getlnputStreamf)));
} catch (UnknownHostException e) (
System.err.printin("Host ne najden. Oshibka.");
System.exit(1);
} catch (lOException e) (
System.err.printin("Couldn1t get I/O for the connection to host.");
System.exit(1); }
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
String fromServer;.
String fromUser;
while ((fromServer = in.readLine()) != null) (
System.out.printin("Server: " + fromServer); if (fromServer.equals("Bye.")) break;
while(kk < 1000) ( kk++; fromUser = "My name is client 1 "; fromUser = "this is my " + kk + " try. ";
if (fromUser != null) (
System.out.println("Client: " + fromUser + "Try no " + kk); out.println(fromUser);
}
}
out.close();
in.close();
stdin.close();
kkSocket.close();
На рис. 8.9 показан "бешеный" клиент в работе.
Рис. 8.9. "Бешеный" клиент
Мы рассмотрели простейший пример работы с сетью с использованием сокетов. Средства программирования более высокого уровня предоставляет архитектура RMI. Но серверные компоненты EJB, входящие в состав платформы J2EE, предоставляют мощный, ни с чем не сравнимый механизм, используемый для создания распределенных многопоточных приложений на языке Java. Далее в этой главе мы рассмотрим классические примеры, которые помогут нам понять основные принципы работы с J2EE.
Пример с компонентами EJB
Лучший способ понять, что происходит, — изучить структуру примера, затем внести в него изменения, понять, чего недостает, и перейти к более сложному примеру или документации. Прежде чем рассмотреть пример, нам необходимо установить программное обеспечение.
Установка и конфигурирование сервера
Мы установили на компьютере пакет разработчика (пакет JDK1.3.1, т. е. J2SE). Кроме этого нам потребуется J2EE, пакет можно получить через Интернет по адресу http://java.sun.eom/j2ee/download.html#sdk (примерно 17 Мбайт). Еще нам понадобится пакет jakarta-ant, который можно найти на сайте http://jakarta.apache.0rg/builds/jakarta-ant/release/vl.3/bin (около 1 Мбайта). J2EE в системе Windows устанавливается автоматически, пакет ant следует распаковать в папку для установки вручную. Необходимо убедиться в том, что заданы нужные переменные окружения (табл. 8.1).
Таблица 8.1. Переменные окружения
ПеременнаяЗначение
окружения
JAVA_H0ME
Основной каталог установки J2SE SDK
J2EE_HOME
Каталог, где установлен пакет J2EE SDK
ANT_HOME
Каталог, где расположен пакет ant
PATH
Path должна содержать пути к папкам bin пакетов J2EE SDK, J2SE, ant
Запуск сервера
Сервер должен работать. Чтобы сервер заработал, его надо запустить. Это несложно сделать. Из командной строки выполним команду: j2ee -verbose
Через некоторое время на экране появится сообщение, в котором будут указаны несколько Web-серверов, активизированных на нашем компьютере на различных портах (рис. 8.10).
Рис. 8.10. Основной сервер запущен
Рис. 8.11. Web-сервер с портом 8000
I^EJ, VW F^'Jo* H*Q
И^Й^№ http//loca#Tost 91913 ^Gc fL"»*
Directory Listing For /
Filename •
DateApp995Q63442280.jar
Size
4.0 kb
Mon, 23
Jul
Last Modified
2001 04:44:04 GMT
7 PateApp9958634449138erver.jar
4.7 kb
Mon, 23
Jul
2001
04:44:08 '. GMT
04:44:08
GMT
DateAppClient.jar
4.7 kb
Mon, 23
Jul
2001
1
converterApp995792007985.jar .
7.1 kb
7 Sun, 22
Jul
2001
08:53:30 / . GMT
1
converterApp995792020773Server.jar
45.4 kb
Sun, 22
Jul
2001
08:53:44 GMT
4
converterAppCllent.jar .■
45.4 1 kb ■
Sun,' 22
Jul
2001
08:53:44
GMT
Рис. 8.12. Web-сервер с портом 9191
'3 Def dull J2LL Home PcMje • Miciosoll Internet 1 xplotet'3 Def dull J2LL Home PcMje • Miciosoll Internet 1 xplotet
'3 Def dull J2LL Home PcMje • Miciosoll Internet 1 xplotet
'3 Def dull J2LL Home PcMje • Miciosoll Internet 1 xplotet
J2EE 1.3
Default Home Page
Congratulations!
Viewing this page means that your Web Server has been installed correctly and is serving files properly.'
J2EE-ri-feedback@isun.com
<Ж1й^й1|^4Ш!г::Йогэ|йй5^^
Проверим работу Web-серверов, обратимся к ним из браузера (рис. 8.11—8.13). На порту 8000 отвечает сервер со стандартной страницы.
Порт 9191 отдан другому Web-серверу, который автоматически устанавливается при установке пакета J2EE (рис. 8.12)..
На 7000-м порту также установлен Web-сервер, но он работает по безопасному протоколу HTTPS (HTTP с использованием SSL), весь поток информации кодируется.
Чтобы остановить основной сервер, используем команду: j2ee -stop
В J2EE разработан графический интерфейс для автоматического размещения созданных серверных приложений (рис. 8.14). Чтобы запустить программу, выполняем команду: deploytool
Enterprise Bean
Resource Adapter™
Add Server...Remove ServerAdd Server...Remove Server"" Web Component...ргЭТН [I converter. JerClient | ^ DateApp"" Web Component...ргЭТН [I converter. JerClient | ^ DateAppРис. 8.14. Работаем с утилитой размещения deployment toolРис. 8.14. Работаем с утилитой размещения deployment tool
Add Server...
Remove Server
Add Server...
Remove Server
"" Web Component...
ргЭТН [I converter. JerClient | ^ DateApp
"" Web Component...
ргЭТН [I converter. JerClient | ^ DateApp
Рис. 8.14. Работаем с утилитой размещения deployment tool
Рис. 8.14. Работаем с утилитой размещения deployment tool
Первое и2ЕЕ-приложение с компонентами EJB
Пакет J2EE предоставляет разработчику возможность создавать серверные компоненты EJB. EJB — аббревиатура от Enterprise Java Bean. Дистрибутив J2EE содержит несколько готовых примеров, разбор которых будет весьма полезен. В качестве своего первого приложения мы рассмотрим стандартный пример из пакета J2EE SDK. Этот пример продемонстрирует метод, используемый при создании компонентов EJB с применением средств пакета J2EE. Приложение состоит из трех основных компонентов, код которых будет расположен в нескольких классах и файлах Java. Компоненты эти — компоненты EJB, клиентское приложение, которое обращается к компоненту EJB, расположенному на EJB-сервере, и Web-клиент, который обращается к компоненту EJB через приложение-клиент. При этом клиент
для работы с компонентом EJB оказывается сервером по отношению к Web-клиенту. Перед тем как мы сможем создать свое приложение, нам нужно создать новое приложение с помощью стандартной утилиты deploytool. Создадим приложение, которое назовем ConverterApp, сохранив его в файле с расширением ear. Файл EAR представляет собой один из стандартных файлов, используемых при работе с пакетом EJB. Вначале запустим утилиту deploytool, а затем вызовем команду меню File -> New -> Application, что позволит нам создать шаблон для нового приложения (рис. 8.14). Все примеры расположены в каталоге j2eetutorial/examples/ src/ejb/converter. Каталог j2eetutorial содержит описания всех примеров и основных методов работы с J2EE. В первом примере нам потребуется создать домашний интерфейс для компонента EJB, удаленный интерфейс и класс, имплементирующий компонент EJB.
Воспользуемся стандартным набором примеров пакета J2EE. Из установочного каталога пакета J2EE выберем файл /examples/src/ejb/converter. В поле File Name должен быть записан файл ConverterApp.ear. Наконец, щелкнем кнопку New Application и закроем окно, нажав кнопку ОК. Механическое выполнение таких действий позволит нам сделать первый шаг на пути освоения методов работы с компонентами EJB. Все, что нам понадобится, это разместить все создаваемые далее Java-файлы в каталоге examples/src/ejb/ converter, там же будет расположен и файл index.jsp. Этот каталог выбран в соответствии с описанием, заданным в файле build.xml, который мы поместим в каталог /examples. Файл build.xml содержит описание размещения компонентов создаваемого нами приложения. Этот файл используется сервером.
Файл build.xml
<project name="j2ee-tutorial-examples" default="about" basedir=".">
<target name="init">
<tstamp/>
<property name="build" value="build" />
<property name="src" value="src" />
<property name="date" value="web/date" />
<property environment= "myenv" />
<property name="j2eepath"
value="$(myenv.J2EE_HOME}/lib/j2ee.jar" />
<property name="webpath" value="$(webejb)" />
<property name="connector-lib"
value="$(myenv.J2EE_H0ME}/lib/connector" />
<property name="cloud-lib"
value="$(myenv.J2EE_HOME}/lib/cloudscape" />
<property name="system-lib" value="$(myenv.J2EE_H0ME)/lib/system"
<property name="cloudpath"
value=".:$(cloud-lib)/cloudclient.jar:
$(cloud-lib)/RmiJdbc.jar:
$(system-lib)/cloudutil.jar:
$(system-lib)/cloudscape.jar" />
<property name="cloud-jvmargs"
value="-ms!6m -mx32m -Dij.connection.CloudscapeDB=
jdbc:rmi://localhost:1099/jdbc:cloudscape:CloudscapeDB;
create=true -Dcloudscape.system.home=
$(myenv.J2EE_HOME)/cloudscape" />
</target>
<target name="ejb" depends="init, savingsaccount, bank, cart, checker, confirmer, converter, enroller, order, salesrep, storagebin, teller, htmlreader, warehouse, simplemessage, cmproster" >
<chmod perm="go+r" type="both">
<fileset dir=".." />
</chmod>
</target>
<target name="converter" depends="init">
<mkdir dir="$(build)/${ejb)/converter" />
<javac srcdir="$(src)/$(ejb)/converter"
destdir="$(build)/${ejb)/converter" classpath="$(j2eepath)" />
<copy todir="$(build)/$(ejb)/converter" >
<fileset dir="$(src)/$(ejb)/converter" >
<include name="**/*.jsp" />
</fileset>
</copy>
</target>
<target name="web" depends="init, date, hellol, hello2.
bookstorel, bookstore2, bookstore3" >
<chmod perm="go+r" type="both">
<fileset dir=".." />
</chmod>
</target>
</project>
Скомпилированные файлы классов будут располагаться в каталоге /examples/build/ejb/converter.
Код удаленного интерфейса
Удаленный интерфейс содержит методы, к которым может обратиться клиент. Методы имплементируются в коде серверного компонента EJB. Код интерфейса содержится в файле Converter.java. В первом примере мы создаем компоненты EJB, которые будут преобразовывать доллары в йены и йены в евро, нам нужно описать два метода, ответственные за конвертацию.
; Файл Converter.java
import javax.ejb.EJBObject;
import java.rmi.RemoteException;
import java.math.*;
public interface Converter extends EJBObject {
public BigDecimal dollarToYen(BigDecimal dollars) throws RemoteExcept ion;
public BigDecimal yenToEuro(BigDecimal yen) throws RemoteException;
Код домашнего интерфейса
Домашний интерфейс содержит методы, которые позволяют клиенту создавать, находить или удалять серверный компонент EJB. В нашем случае домашний интерфейс с названием Converte'rHome содержит единственный метод create, который возвращает объект удаленного интерфейса.
Г Файл с кодом домашнего интерфейса ConverterHome.java
import java.io.Serializable;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;
public interface ConverterHome extends EJBHome (
Converter create () throws RemoteException, CreateException; )
Код класса компонента EJB
Наконец, нам нужно создать класс компонента EJB. Назовем его ConverterBean. Класс будет имплементировать два метода. Это будут те самые методы, которые мы описали в файле Converter.java в виде методов удаленного интерфейса — dollarToYen И yenToEuro.
Класс компонента EJB в файле ConverterBean.java.j
import java.rmi.RemoteException; import javax.ejb.SessionBean;
import javax.ejb.Sessioncontext; import java.math.*;
public class ConverterBean implements SessionBean (
BigDecimal yenRate = new BigDecimal ("121.6000");
BigDecimal euroRate = new BigDecimal("0.0077");
public BigDecimal dollarToYen(BigDecimal dollars) (
BigDecimal result = dollars.multiply(yenRate) ; return result.setScale(2,BigDecimal,ROUND_UP);
}
public BigDecimal yenToEuro(BigDecimal yen) (
BigDecimal result = yen.multiply(euroRate); return result.setScale(2,BigDecimal,ROUND_UP);
}
public ConverterBean() (} public void ejbCreateO (} public void ejbRemove() {}
public void ejbActivate() {}
public void ejbPassivate() {}
public void setSessionContext(Sessioncontext sc) {}
}
Присмотревшись к происходящему, можно констатировать, что здесь нет ничего сложного.
Компилируем код
Сейчас произойдет несколько не очень понятных событий. Эта "непонятность" возникает на первых порах, она связана с особенной "конструкцией" пакета J2EE и прилагаемых к нему примеров. Мы не станем разрушать структуру пакета примеров, в дальнейшем вы сами сможете рассмотреть их настолько подробно и детально, насколько вам это будет необходимо. Мы не сможем уделить достаточно внимания большинству примеров. Произведем несколько стандартных, действий, будем помнить, что некоторая информация о том, как сконфигурировано окружение, останется от нас скрытой. Полезным здесь могло бы стать изучение архитектуры CORBA.
Перейдем в каталог j2eetutorial/examples и из командной строки выполним команду ant converter. В выбранном нами каталоге находится файл build.xml, содержащий нужную для работы утилиты ant информацию. Чтобы понять происходящее, полезно познакомится с тем, как работает ant. Ant — это утилита для создания Java-классов.
i Фрагмент файла build.xml -!
<target name="converter" depends="init">
«mkdir й1т="МЪтпЛй>/МедЪ>/converter" />
<javac srcdir="${src}/${ejb}/converter"
destdir="${build}/${ejb}/converter"
classpath="${j2eepath}" />
<copy todir="${build}/${ejb}/converter" >
<fileset dir="${src}/${ejb}/converter" >
<include name="**/*.jsp" />
</fileset>
</copy>
</target>
В соответствии с описанием, компилятор поместит результат работы в каталог j2eetutorial/examples/build/ejb/converter. Дополнительно нужно убедиться
в том, что путь к файлу j2ee.jar указан в переменной path (утилита ant должна установить это значение).
Упаковка компонента EJB
Процедура создания компонентов EJB предусматривает их упаковку. Это делается при помощи утилиты deploytool, в которой вызывается проводник упаковки. Проводник упаковки создаст дескриптор компонента EJB и упакует его и классы компонента EJB в JAR-файл. Затем вставит созданный JAR-файл в файл ConverterApp.ear. Созданный дескриптор можно посмотреть, выбрав команду Tools -> Descriptor Viewer (рис. 8.15).
!^ Deployment Descriptor Viewer
«"«аррисаютр'—— ——
, «display-name»converterApp«/display-name*
; «description»Application description«/description* ; «module»
: «java*app-client-ic.jar«/java* «/module»
I «module*
«web»
i «web-uri»war-ic.war«/Web-uri*
■«с о ntext- ro ot* с о nve rte r«/co ntext- ro ot*
. «/Web*
■ «/module*
«module*
; «ejb»ejb-jar-ic.jar«/e)b»
«/module*
! «/application*
Save As... | I Close
Рис. 8.15. Созданный дескриптор
Вызовем проводник серверных компонентов EJB, для этого выберем команду меню File -> New -> Enterprisew Bean (рис. 8.16). У нас есть приложение, мы создаем новый компонент EJB.
В окне ввода (рис. 8.17) читаем информацию о том, что данный проводник связывает тот или иной JAR-файл с конкретным серверным компонентом EJB, производит выбор типа создаваемого компонента EJB, идентифицирует класс компонента EJB и описанные в нем интерфейсы.
Кроме того, здесь описаны дополнительные возможности, которые предоставляет проводник. Переходим к следующему шагу — окно EJB JAR (рис. 8.18). Здесь мы устанавливаем флажок Create New JAR File in Application, в поле должно быть указано значение converterApp.
Close
Add Server...
1<ИГ1Г1У>‘ Sui И-Г
Save
Exit
тг
Application...
Application Client...
Enterprise Bean...
Resource Adapter...
Web Component...
StUAR :erClient
-Р
1
Рис. 8.16. Вызов проводника серверных компонентов EJB
i О converter Аррi О converter Аррг kj Add to Existing JAR Fileг kj Add to Existing JAR FileContents:Contents:e- ЕЭ meta-infe- ЕЭ meta-inf. В Description™. В Description™JAR Display Нлшп: I ConverterJARJAR Display Нлшп: I ConverterJAR
i О converter Арр
i О converter Арр
г kj Add to Existing JAR File
г kj Add to Existing JAR File
Contents:
Contents:
e- ЕЭ meta-inf
e- ЕЭ meta-inf
. В Description™
. В Description™
JAR Display Нлшп: I ConverterJAR
JAR Display Нлшп: I ConverterJAR
p2* New Enteiprise Bean Wizard - EJB JAR
A JAR file,is required to contain this enterprise bean. You can create a new JAR file within an existing application or ; use an existing JAR file. Alter you have selected a JAR file, add the EJB classes and any other desired flies to it's toitente,*ggiyg|HS$||i||l||g|l|||||||||l|^^
Optionally, you can also provide a description, edit the manifest classpath, and choose Icons for the JAR file.
; JAR file Locanriii:-- ---
i » Create New JAR File in Application
, Edit...
Manifest Classpat™' | j Icons...
< Hack ; Next >< Hack ; Next >| Help™ i
< Hack ; Next >
< Hack ; Next >
Рис. 8.18. Окно проводника EJB JAR
Затем устанавливаем в поле JAR Display Name значение ConverterJAR и нажимаем кнопку Edit. Находим файлы в папке j2eetutorial/examples/ build/ejb/converter и переносим из верхнего окна (можно простым перетаскиванием) файлы классов Converter.class, ConverterBean.class И ConverterHome.class (рис. 8.19).
Сейчас нажимаем кнопку ОК и переходим к следующему шагу.
Перед нами окно общих сведений о компоненте EJB (рис. 8.20). Здесь мы задаем тип компонента EJB (один из трех — Entity, Message-Driven, Session). Мы выберем Session и Stateless. В поле Enterprise Bean Class укажем значение ConverterBean. В поле Enterprise Bean Name запишем ConverterEJB. Затем в поле Remote Home Interface выбираем ConverterHome, а в поле Remote Interface задаем значение Converter.
Нажимаем кнопку Next, переходим к следующему окну Transaction Management. Нам нет необходимости вносить какие-либо изменения в дальнейших установках, нажимаем кнопку Finish (рис. 8.21).
Рис. 8.19. Вставляем в компонент EJB файлы классов
Рис. 8.21. Завершающие шаги упаковки
Создаем приложение-клиент
Мы скомпилировали и упаковали компонент EJB, но нам необходим клиент, который будет обращаться к серверным компонентам EJB. Клиент может находиться на другой машине Java, не на той же самой, где установлен J2EE-cepBep. Клиент J2EE требует два файла JAR. В одном файле будут клиентские компоненты, дескриптор, классы. Этот файл автоматически создается утилитой deploytool и заносится в файл EAR. Файл EAR переносим (портируем) на любые J2EE-cepBepbi. Второй файл JAR содержит классы объектов stub, которые требуются клиенту во время выполнения. Эти классы позволяют клиенту обращаться к компонентам EJB на сервере.
Код клиента в файле ConverterClient.java находит домашний интерфейс, создает компонент EJB, вызывает методы.
| Файл ConverterClientJava
import javax.naming.Context;
import javax.naming.Initialcontext;
import javax.rmi.PortableRemoteObject;
import java.math.BigDecimal;
public class Converterclient {
public static void main(String[] args) { try {
Context initial = new Initialcontext();
Context myEnv = (Context)initial.lookup("java:comp/env");
Object objref = myEnv.lookup("ejb/SimpleConverter");
ConverterHome home =
(ConverterHome)PortableRemoteObject.narrow(objref, ConverterHome.class);
Converter currencyconverter = home.create();
BigDecimal param = new BigDecimal ("100.00");
BigDecimal amount = currencyconverter.dollarToYen(param);
System.out.println(amount);
amount = currencyconverter.yenToEuro(param);
System.out.printin(amount);
System.exit(0);
} catch (Exception ex) {
System.err.printin("Caught an unexpected exception!"); - ex.printStackTrace(); }
} }
Интерфейс ConverterHome содержит основные методы, например метод create. Прежде чем клиент converterclient сможет обратиться к этому методу, он должен найти и инициировать объект типа ConverterHome. Задача
состоит из четырех частей. Первым делом нужно создать начальный исходный контекст:
Context initial = new Initialcontext();
Интерфейс context — это часть JNDI, т. е. часть интерфейса Java Naming and Directory Interface. Объект initialcontext (он имплементирует интерфейс context) предоставляет точку входа для разрешения имен. Затем необходимо получить окружение имен контекста:
Context myEnv = (Context)initial.lookup("java:comp/env");
Сейчас ИМЯ java:comp/env связано C Converterclient.
Третий шаг — получение объекта, связанного с именем е jb/SimpleConverter:
Object objref = myEnv.lookup("ejb/SimpleConverter");
Четвертый шаг — сузить ссылку до объекта ConverterHome:
ConverterHome home =
(ConverterHome) PortableRemoteObject.narrow(objref, ConverterHome.class);
Создаем экземпляр компонента EJB
Чтобы создать экземпляр компонента EJB, клиент вызывает метод create объекта ConverterHome. Этот МСТОД возвращает объект, ТИП которого — Converter. Удаленный интерфейс converter содержит методы, которые могут быть вызваны клиентом. При обращении клиента к методу create, компонент EJB инициализируется И вызывается метод ConverterBean.ejbCreate. Клиент обращается к методу create следующим образом:
Converter currencyconverter = home.created;
Вызываем методы компонента EJB
Обращение к методам компонента EJB не слишком сложно. Просто нужно обратиться к соответствующим методам объекта Converter. Контейнер EJB вызывает соответствующие методы в converterEJB на сервере. Например, к методу doiiarToYen происходит обращение следующим образом:
BigDecimal param = new BigDecimal ("100.00");
BigDecimal amount = currencyconverter.doiiarToYen(param);
Приложение-клиент компилируется одновременно во время компиляции компонента EJB при обращении к утилите ant. Чтобы упаковать клиента, в утилите deploytool вызовем проводника упаковки. Необходимо создать дескриптор клиента, разметить дескриптор в файле JAR, вставить файл JAR в файл ConvertrApp.ear.
Открываем проводника создания нового клиента командой New -> Application Client (рис. 8.22).
Open...CloseOpen...CloseН Edit Tools HelpН Edit Tools HelpApplication,Application,Add to Application ►Add to Application ►Enterprise Bean... . Resource AdapterWeb Component...Enterprise Bean... . Resource AdapterWeb Component...Add Server...Add Server...№mow S№mow S(erClient(erClient
Open...
Close
Open...
Close
Н Edit Tools Help
Н Edit Tools Help
Application,
Application,
Add to Application ►
Add to Application ►
Enterprise Bean... . Resource AdapterWeb Component...
Enterprise Bean... . Resource AdapterWeb Component...
Add Server...
Add Server...
№mow S
№mow S
(erClient
(erClient
Save
Save As... '
Exit
Рис. 8.22. Проводник клиента приложения в меню New
Появляется вводное диалоговое окно, в котором сообщается, что при создании нового клиента необходимо идентифицировать, к какому приложению относится клиент и основной класс клиента. Затем приводится список дополнительных возможностей. Переходим к следующему окну.
||||New Application Client WizanT^JA^—-j5||
IPlease select the application that this application client Is targeted to and a JAR file will be added to it. Add the
' class flies for this application client to the contents ofthe JAR file.
.
Й l О converterApp▼ I '
i_—--—-— — — — -
Рис. 8.23. Содержимое файла JAR
Окно JAR File Content (рис. 8.23) предлагает сделать выбор. Установим значение поля ConverterApp и нажмем кнопку Edit. Из каталога, содержащего классы j2eetutorial/examples/build/ejb/converter, выберем файл converterclient. class. Вставим его в окно Contents of <AppIication Client>, щелкнем кнопку OK и перейдем к следующему диалоговому окну (рис. 8.24).
В поле Main Class указываем converterclient, поле Display Name содержит converterclient (рис. 8.25). Переходим к следующему окну, в котором завершаем процесс, нажимая кнопку Finish.
Задаем ссылку клиента приложения на компонент EJB.
При обращении к методу lookup клиент обращается к компоненту EJB. Для того чтобы ссылка на компонент EJB была задана, необходимо выбрать клиента в deploytool (рис. 8.26) и выбрать закладку ссылок EJB Refs, затем нажать кнопку Add.
Manifest Classpath-Manifest Classpath-Icons...Icons...
Manifest Classpath-
Manifest Classpath-
Icons...
Icons...
I^Edit Contents of (Application Client>
Sj^rfino Diieauiy
!c: CGI_bookiinater lais j?eptutoi idlyxarnplesisr c ejb converter
A¥4iial№Vihw_ _ _
: f E3 c:lCGl_booMmaterialslj2eetutorlariexamples'isrclejtAconverter
j0 app-client-temp21364Jar
:0 Converter.class
i0 Converterjava
0 converterApp.ear
0 converterAppCIIentjar
0 ConverterBean.class
0 ConverterBean.java
0 ConverterClientclass
0 ConverterClientjava
Ai ।Remove
r iiritivils lit «.Application ПииИ'
®- C3 МЕТА-INF~—
Pl ConverterClientclass
OK i ' Cancel I Help...
Рис. 8.24. Класс Converterclient.class
f^New Application Client Wizard - General
В Description- \В Description- \Select the application client's main class and provide a dlspaly name for it Optionally, you also Identity a callback handler class, provide a description, define the manifest classpath for the JAR file, and select the icons for the • application client.'-..".. .., .
В Description- \
В Description- \
Apple. itinn Client. .-...
|iiBBISsSllie8iilBiflt®8118liieBi8lieiii8ll^^
। Converterclient
DisplayName: _ _ _ __ _ ...
[converterClient|j '
C*di.k Handler C lass:_ ___ _.
' (Use container-managed authentication)■»■'
ф ЕЗ Filesф ЕЗ Applicationsф ф converterAppф 3 ConverterWAR @ index®- § ConverterJAR ® Converterclientф ЕЗ Filesф ЕЗ Applicationsф ф converterAppф 3 ConverterWAR @ index®- § ConverterJAR ® Converterclientf Ups. A[>plicjtions.ciin№iteiApp.Curiveitei ClientiGen^Entl^EJI^LJB's Referenced in Code ■ ■-■- Coded Name|'Type i;| ■ ■Irs, ejb/SimpIeConverter ^SessioniRemotf Ups. A[>plicjtions.ciin№iteiApp.Curiveitei ClientiGen^Entl^EJI^LJB's Referenced in Code ■ ■-■- Coded Name|'Type i;| ■ ■Irs, ejb/SimpIeConverter ^SessioniRemot
ф ЕЗ Files
ф ЕЗ Applications
ф ф converterApp
ф 3 ConverterWAR @ index
®- § ConverterJAR ® Converterclient
ф ЕЗ Files
ф ЕЗ Applications
ф ф converterApp
ф 3 ConverterWAR @ index
®- § ConverterJAR ® Converterclient
f Ups. A[>plicjtions.ciin№iteiApp.Curiveitei Client
iGen^Entl^EJI^
LJB's Referenced in Code ■ ■-■
- Coded Name|'Type i;| ■ ■Ir
s, ejb/SimpIeConverter ^SessioniRemot
f Ups. A[>plicjtions.ciin№iteiApp.Curiveitei Client
iGen^Entl^EJI^
LJB's Referenced in Code ■ ■-■
- Coded Name|'Type i;| ■ ■Ir
s, ejb/SimpIeConverter ^SessioniRemot
ф ® Servers
Ф В localhost ф converterApp ф DateApp
Рис. 8.26. Задаем ссылку
Затем вводим:
в поле Coded Name — значение ejb/simpieConverter;
в поле Туре — значение Session;
в поле Interfaces — значение Remote;
в поле Home Interface — значение converterHome;
в поле Local/Remote Interface — значение converter.
Сейчас мы имеем компонент EJB и клиент приложения. Нам недостает Web-клиента. Web-клиент будет обращаться к клиенту приложения. Создадим Web-клиент.
Создаем Web-клиент
Наш пример будет содержать Web-клиента, реализованного средствами JSP (Java Server Pages, серверными страницами Java).
Клиент содержится в файле j2eetutorial/examples/src/ejb/converter/index.jsp.
Вот код Web-клиента.
Файл index.jsp.
<%@ page import="Converter,ConverterHome,javax.ejb.*, java.math.*, javax.naming.*, javax.rmi.PortableRemoteObject, java.rmi.RemoteException" %>
<%!
private Converter converter = null;
public void jsplnit() (
try {
Initialcontext ic = new Initialcontext();
Object objRef = ic.lookup("java:comp/env/ejb/TheConverter"); ConverterHome home =
(ConverterHome)PortableRemoteObject.narrow(objRef, ConverterHome.class);
converter = home.create();
} catch (RemoteException ex)
{■
System.out.printin("Couldn't create converter bean."+ ex.getMessage());
} catch (CreateException ex) {
System.out.printin("Couldn't create converter bean."+ ex.getMessage() ) ;
} catch (NamingException ex) {
System.out.printin("Unable to lookup home: "+ "TheConverter "+ ex.getMessage());
} }
public void jspDestroyO {
converter = null;■
} %>.
<html> <head>
<title>Converter</title>
</head>
<body bgcolor="white">
<hlxbXcenter>Converter</centerX/bx/hl>
<hr>
<p>Enter an amount to convert:</p>
<form method="get">
<input type="text" name="amount" size="25"> <br>
<p>
<input type="submit" value="Submit">
<input type="reset" value="Reset">
</form>
<%
String amount = request.getParameter("amount");
if (amount 1= null && amount.length() > 0) (
BigDecimal d = new BigDecimal (amount);
%>
<P>
<%= amount %> dollars are <%= converter.dollarToYen(d) %> Yen;
<P>
<%= amount %> Yen are <%= converter.yenToEuro(d) %> Euro;
<%
}
%>
</body>
</html>
Основная часть, ответственная за обнаружение домашнего интерфейса, — создание экземпляра компонента EJB и вызов методов — выглядит так:
Initialcontext ic = new Initialcontext();
Object objRef = ic.lookup("java:comp/env/ejb/TheConverter");
ConverterHome home = (ConverterHome)PortableRemoteObject.narrow( objRef, ConverterHome.class);
converter = home.create();
Символы <%@ и %> обрамляют исполняемые на Web-сервере фрагменты кода. JSP-декларации, выполняемые только один раз, помещаются между символами <%! и %>. Используются также вставки скриптов <% %> и выражений <%= %> .
Web-клиент должен быть упакован. Для этого, как всегда, нужен дескриптор Web-клиента. Компоненты должны быть вставлены в файл WAR, который должен быть внесен в файл ConverterApp.ear. Все это нам поможет сделать утилита deploytool.
Выберем меню New -> WebComponent (рис. 8.27).
В вводном окне узнаем, что этот проводник поможет нам выбрать для Web- клиента WAR файл, поможет задать класс сервлета или JSP-файл (рис. 8.28). Кроме этого, в окне ввода описаны дополнительные возможности. Переходим к окну WAR File (рис. 8.29).
Выбираем команду Create New WAR File in Application, указав приложение ConverterApp. В качестве имени файла зададим (в поле WAR Display Name) converterWAR. Нажмем кнопку Edit.
Add to Application
Application...
Application Client-
Open...
Close
Add Server...
!;■■.:.:,. ■■ V!W
Save
Save As...
Exit
Enterprise Bean...
Рис. 8.27. Включаем в приложение Web-клиент
|^New Web Component Wizard - Introduction
Я
This wizard will help you to create a new web component. You must begin with a servlet class or JSP file. The wizard will then package the selected files into a Web ARchive (.WAR) file and will create the deployment descriptor required. ■ '
Creating this web component requires the following steps:
♦ Select the WAR file'to contain the component:
• Identify the servlet class or JSP file. ■■
Optionally, you can also:"'
, .: • Provide the description and icons for the component. '.' ' .
• Provide the initialization parameters for the component. - \.
.♦ Provide the aliases to be used by the component, -. ; , .
- •.Provide the security settings for the component.■ -
' • Identify the set of servlet filters and the mapping of those filters.'
' ■ ♦ Identify the set of event listener classes in the WAR file. „
, ' ♦ Provide the context and environment parameters for the WAR file. -... •
Identity any enterprise beans and resources that are referenced by components in this ' ■ • WAR file. .• ' •’
' ■ :.; ♦ Identify files referenced by components in the WAR file. ■ "
v ♦ Provide the required security information for the WAR file." ■'
□ Skip this Screen in the Future
Help... J ’
! <gack
Next>
Рис. 8.29. Создаем файл WAR
Выбираем папку /examples/build/ejb/converter, находим файл index.jsp и переносим его в окно Contents of Converter WAR (рис. 8.30).
Файл внесен, переходим к следующему окну выбора типа компонента Choose Copmponent Туре (рис. 8.31). Здесь нам достаточно выбрать радиокнопку JSP и перейти к следующему шагу.
Рис. 8.31. Задаем тип компонента
Следующее окно — Component General Properties, окно общих свойств компонента (рис. 8.32).
В качестве имени файла в поле JSP Filename указываем index, jsp. Сейчас можно нажать кнопку Finish. После того как Web-клиент упакован, необходимо задать на него ссылки.
Задаем ссылки
Чтобы задать ссылку, необходимо в утилите deploytool выбрать закладку ConverterWAR, а в правом окне выбрать закладку EJB Refs (рис. 8.33). Затем щелкнем на кнопке ADD и укажем следующие параметры:
В поле Coded Name — ejb/TheConverter;
в поле Туре — Session;
в поле Interfaces — Remote;
в поле Home Interface — converterHome;
в поле Locai/Remote Interface — converter.
£^ Application Deployment Tool: convciteiApp
File Edit Tools HelpFile Edit Tools Help
File Edit Tools Help
File Edit Tools Help
rdes.AppllCdtions.coi ivortui App Corwoi lerWARrdes.AppllCdtions.coi ivortui App Corwoi lerWARInterfaces I Home Interface -/ |lo<Interfaces I Home Interface -/ |lo<RemoteRemoteConverterHome CoConverterHome Co^FJITsRefeimicfnl in Cud» --* Coded Name I _ TypeI e^h eConverter Session __^FJITsRefeimicfnl in Cud» --* Coded Name I _ TypeI e^h eConverter Session __9 C3 Rites
rdes.AppllCdtions.coi ivortui App Corwoi lerWAR
rdes.AppllCdtions.coi ivortui App Corwoi lerWAR
Interfaces I Home Interface -/ |lo<
Interfaces I Home Interface -/ |lo<
Remote
Remote
ConverterHome Co
ConverterHome Co
^FJITsRefeimicfnl in Cud» --
* Coded Name I _ Type
I e^h eConverter Session __
^FJITsRefeimicfnl in Cud» --
* Coded Name I _ Type
I e^h eConverter Session __
9 C Applications
9 <£ cr «e^s’-cc
9 9 ConverterWARО index
©■ 8 ConverterJAR
SI Converte'Ciient
Ф S Servers
9 3 localhost
* converterApp ф DateApp
Рис. 8.33. Ссылка для ConverterWAR
Задание имен JNDI
Приложение J2EE и Web-клиент обращаются к одному и тому же компоненту EJB. Но код приложения и Web-клиента обращаются к нему по-разному, указывают разные имена. Приложение обращается к ejb/simpieconverter. Web- клиент обращается к ejb/TheConverter. Чтобы обращение происходило правильно, необходимо задать JNDI-имена. JNDI — это Java Naming and Directory Interface. Чтобы задать имена, выберем папку converterApp и закладку JNDI Names (рис. 8.34).
V C3 Flies$ П Applications*■ ф converterAppf 8 Serversf Й localhost0 converterApp ф DateAppV C3 Flies$ П Applications*■ ф converterAppf 8 Serversf Й localhost0 converterApp ф DateAppРис. 8.34. Задаем имена JNDIРис. 8.34. Задаем имена JNDI
V C3 Flies
$ П Applications
*■ ф converterApp
f 8 Servers
f Й localhost
0 converterApp ф DateApp
V C3 Flies
$ П Applications
*■ ф converterApp
f 8 Servers
f Й localhost
0 converterApp ф DateApp
Рис. 8.34. Задаем имена JNDI
Рис. 8.34. Задаем имена JNDI
^Application Deployment Tool conveiteiApp
Hte &W Tools Help
4€вИВ1В® ^:r <^<§ <£ <
I ldes.A|9№j>tiuns.cotw<HtefApp,
1l8MKS5l!№
I (АррМг.МЮП • -• - 1 • -*•••- -
i PeTVT’- .3;- _Convert9r€JB • . t MyCcnvertar _ ~
В столбце Component найдем приложение converterEjB и введем в столбце JNDI Name значение MyConverter. В таблице ссылок (в нижней части рис. 8.35) в каждой строке столбца JNDI Name укажем имя MyConverter.
Размещаем приложение на сервере
Сейчас мы имеем готовое приложение, компонент EJB и Web-клиент. Необходимо все это разместить на сервере. Выбираем (в утилите deploytool) наше приложение ConverterApp и выбираем в меню Tool режим Deploy (рис. 8.36).
I Tools;; Help
JEdit Search Paths...i
-Update Files!
угк1ер1одм|
^Update and Redeploy...i
*Verifier.-I
.Clone Inspector|
Edit Roles...
Descriptor Viewer...i
Server Configuration...।
Рис. 8.36. Размещаем приложение на сервере
Появляется проводник, его окно ввода сообщает, что мы собираемся разместить приложение converterApp на сервере localhost. Выбираем режим Return Client Jar, указываем путь /examples/src/ejb/converter (рис. 8.37), нажимаем кнопку Next.
На следующем шаге дополнительно убеждаемся, что имена указаны верно (диалоговое окно JNDI Names на рис. 8.38).
^Deploy conveiterApp - JNDI Names
Application
Component Type! CompJNDI Name11
EJB-.ConyerterEJB_ jylyConverter’
। Roforences -। Roforences -| Help.-| Help.-■Ref. Type EJ9 Ref " ’ EJ9 Ref “ '■Ref. Type EJ9 Ref " ’ EJ9 Ref “ '1 - JNDI Name j {iMvConverter fl1 - JNDI Name j {iMvConverter fl Referenced By ConyerterClient _ ejWSimpleConv..7”^iyConyerter ConyerterWAR _ ejbHheCqnyBiterjMyConverter _ Referenced By ConyerterClient _ ejWSimpleConv..7”^iyConyerter ConyerterWAR _ ejbHheCqnyBiterjMyConverter _Reference NameReference NameCancelCancel< Back Next >< Back Next >FinishFinish
। Roforences -
। Roforences -
| Help.-
| Help.-
■Ref. Type EJ9 Ref " ’ EJ9 Ref “ '
■Ref. Type EJ9 Ref " ’ EJ9 Ref “ '
1 - JNDI Name j {
iMvConverter fl
1 - JNDI Name j {
iMvConverter fl
Referenced By
ConyerterClient _ ejWSimpleConv..7”^iyConyerter ConyerterWAR _ ejbHheCqnyBiterjMyConverter _
Referenced By
ConyerterClient _ ejWSimpleConv..7”^iyConyerter ConyerterWAR _ ejbHheCqnyBiterjMyConverter _
Reference Name
Reference Name
Cancel
Cancel
< Back Next >
< Back Next >
Finish
Finish
Рис. 8.38. Проверяем имена
Переходим к следующему шагу. В окне WAR Context Root в поле Context Root вводим значение converter (рис. 8.39). Когда мы будем запускать Web- клиент, converter будет частью URL.
Переходим к следующему шагу. В окне Review нажимаем кнопку Finish. Через некоторое время (рис. 8.40—8.42) наше приложение готово, попробуем его запустить.
Рис. 8.40. Начало процесса размещения приложенияРис. 8.40. Начало процесса размещения приложения
Рис. 8.40. Начало процесса размещения приложения
Рис. 8.40. Начало процесса размещения приложения
Progress
Contacted Sewer... L- 'j;.. '
Application converterApp transferred
converterApp has 1 ejbs, 1 web components to dep
Deploying Ejbs... - - ' -.,f-
Processing beans... .-=. , / "**,= - *
Compiling wrapper code
Compillng.RMHIOP code... W. • /t ;• .
Making sewer JARSL? "v~'“• •
Making clientJARs"
Г?
Contacted Server/ ■ ' : '
ApplicatlonconverterApptransferred' 5 Ч1 ;:'"‘ co-werterApp has 1 e.bs, 1 web components to dep Deploying Ejbs..
Processing beans..-•. ч.
Compiling wrapper code...’’-ЧЧ'
Compiling RMt-llOP code...Д Л
MakingserverJARs; 'и- . - -<•
Making client JARs*
Contact he web serverand ask tto run c\j2sdkeet Web Components Deployed * S;_ .лД^ * Deployment ofconverterApp is completer?'/® " gtlspt code for the deployed application converterAp ' '™™™l|iliei
нининнРис. 8.42. Приложение размещено
ни
ни
н
н
Запускаем приложение
Перед запуском дополнительно убедимся, что в каталоге /examples/ src/ejb/converter есть файлы ConverterApp.ear и ConverterAppClient.jar, а также, что задана переменная окружения аррсратн, значение которой ConverterAppClient.jar.
Запускаем клиента с помощью команды (рис. 8.43):
runclient -client ConverterApp.ear -name Converterclient -textauth
В качества имени login вводим guest, пароль будет guestl23 (рис. 8.44).
' С \WINNTXSystem32\cmd схе
С:\2_CGI bookXmaterialsXj2eetutorial\examples\src\ejb\convertег>гипс 1 lent -client Converter.esr -name ConverterCIient -textauth
Рис. 8.43. Запускаем клиент приложения
Initiatimj loyin ...
Enter Usernanecyuest
Enter Разаwurdcyues1123_,я
Binding name:'javacconp/enu/ejb/SinpleConverter* 12160.00 0.77
Рис. 8.45. Приглашение для ввода
На экране появится сообщение:
Binding name:'java:comp/env/ejb/SimpleConverter1 12160.00
0.77■
Откроем браузер, зададим адрес http://localhost:8000/converter. В окне увидим результат, показанный на рис. 8.45.
Введем 1000, нажмем кнопку Submit, через мгновение получим ответ, представленный на рис. 8.46.
Пакет J2EE SDK поддерживает возможности пошаговой разработки приложений. Готовое приложение может быть легко изменено. Для этого необходимо лишь создать новый вариант приложения и затем разместить его на сервере. Все, что нужно, — это изменить Java-код приложения, скомпилировать приложение и разместить его на сервере заново.
Пример с JSP — серверными страницами Java
Серверные страницы Java напоминают активные серверные страницы. Они также содержат в себе HTML-код, в который включаются фрагменты, выполняемые сервером. С тем, как создаются HTML-документы, мы достаточно хорошо знакомы. Познакомимся с ярлыками, которые помогают выделить в JSP-документах код, исполняемый на сервере:
директивы <%@ раде ... %> используются для импортирования пакета java.util, пользовательского класса MyLocaies, а также для задания типа контекста;
элемент <jsp:useBean> используется для создания объекта, который содержит все данные о представлении дат и времени и инициализирует переменную, указывающую на объект;
скрипты (<% ... %>) вставляют в HTML-текст значения;
выражения (<%= ... %>) вставляют значение, соответствующее имени, в файл.
Приведем пример:
<%@ page import="java.util.*,MyLocaies" %>
<%@ page contentType="text/html; charset=ISO-8859-5" %>
<html>
<headxtitle>Localized Dates</titlex/head>
<body bgcolor="white">
<jsp:useBean id="locales" scope="application" class="MyLocaies"/>
<form name="localeForm" action="index.jsp" method="post">
<b>Locale:</b>
<select name=locale>
<%
String selectedLocale = request.getParameter("locale");
Iterator i = locales.getLocaleNames().iterator();
while (i.hasNext()) (
String locale = (String)i.next();
if (selectedLocale != null && selectedLocale.equals(locale)) { %>
<option selectedx%=locale%x/option>
<%
} else (
%>
<optionx%=locale%x/option>
<%
}
}
%>
</select>
<input type="submit" name="Submit" value="Get Date">
</form>
<jsp:include page="date.jsp"/>
</body>
</html>
Рассмотрим шаги, которые необходимо предпринять для того, чтобы создать JSP-страницу, разместить ее на сервере и выполнить. Общие принципы создания JSP-страниц довольно просты. Чтобы JSP-приложение работало, необходимо иметь Web-сервер, поддерживающий JSP. Таких серверов довольно много. JSP-страницы содержат в себе фрагменты кода, выполняемого на сервер. От HTML-текста этот код отделяется специальными символами, с которыми мы уже встречались. В стандартных пакетах разработчика языка Java есть несколько вариантов серверов, с которыми возможна работа JSP- страниц. Используем готовый пример пособия, которое предлагается разработчиками. Все описываемые файлы поместим в каталог /examples/src/ web/date/. Там появятся файлы MyDate.java, MyLocales.java, date.jsp. Когда все файлы будут готовы, приложение можно скомпилировать, перейдем в папку /examples и выполним команду ant date.
Нам также будет нужна папка examples/build/web/date. Эта папка появится автоматически, как только мы выполним команду ant date.
После этого у нас будут готовы классы Java. Воспользуемся утилитой deploytool (рис. 8.16) и создадим приложение DateApp, выбрав меню File ■> New ■> Application. Откроем папку /examples/src/web/date, в качестве имени File Name зададим DateApp, нажмем кнопку создания нового приложения New Application и далее кнопку ОК.
Появится новый файл DateApp.ear.
Сейчас нам нужно создать файл WAR. Выбираем команду меню File ■> New ■> Web Component. Выбираем режим DateAPP, в качестве имени пишем DateWAR и переходим к редактированию (нажимаем кнопку Edit). В папке /examples/build/web/date находим файлы index.jsp, date.jsp, MyDate.class, MyLocales.class и добавляем их в файл архива DateWAR. Переходим к следующему шагу (нажмем кнопку Next). На следующем шаге (как показано на рис. 8.31) мы указываем, что создаем приложение JSP (отмечаем радиокнопку, рядом с которой расположен текст JSP).
Сейчас нам необходимо задать базовый каталог Web-адреса. Подведем курсор и выделим создаваемое приложение DateApp, затем откроем закладку Web Context, в поле ContextRoot введем какое-либо имя, например, da.
Сейчас можно разместить приложение на сервере. Выберем меню Tool ■> Deploy, щелкнем кнопку Finish. Все очень просто.
Сейчас можно обратиться к нашей серверной странице из браузера, указав в качестве адреса http://localhost:8000/da (рис. 8.47).
№JE3№JE33 Localized Dates - Microsoft Internet Explorer
№JE3
№JE3
j Fie Edit. View' Favorite» Tool* Help .
] <P8ack v •♦..?!^| >J} | .^Search i»j Favorites
] Address |$] http //localhost: 8000/da/mdex.jsp
Locale: [Dutch (Belgium.Euro) 5 Get Date
The date in Dutch (Belgium,Euro) is dinsdag 1 oktober 2002
У Done
Рис. 8.47. Серверные страницы работают
Структура программного интерфейса J2EE
Здесь коротко представлена схема строения интерфейса J2EE. Далее перечислены пакеты, которые могут быть использованы при создании серверных страниц JSP. Эти пакеты включают в себя классы, используемые в серверных
страницах и обеспечивающие необходимую функциональность серверных страниц, а также сервлетов. Краткое описание классов дано в таблице, посвященной иерархии классов (табл. 8.2). Детальная информация о методах, содержащихся в этих классах, приводится в документации к пакету J2EE. Здесь мы приводим список классов с кратким описанием, которое позволяет понять, каково назначение того или иного класса и для решения каких задач он используется.
Пакеты
Иерархия пакетов:
javax.activation;
javax.ejb:
• javax.ejb.spi;
□ javax.jms;
Cl javax.mail:
javax.mail.event;
javax.mail.internet;
javax.mail.search;
javax.resource:
javax.resource.cci;
javax.resource.spi:
° javax.resource.spi.security;
Cl javax.security.auth:
javax.security.auth.callback;
javax.security.auth.login;
javax.security.auth.spi;
javax.servlet:
javax.servlet.http;
javax.servlet.jsp:
° javax.servlet.jsp.tagext;
javax.sql;
javax.transaction:
• javax.transaction.xa;
Cl javax.xml.parsers;
□ javax.xml.transform:
javax.xml.transform.dom;
javax.xml.transform.sax;
javax.xml.transform.stream;
org.w3c.dom;
org.xml.sax:
org.xml.sax.ext;
org.xml.sax.helpers.
В этой главе мы рассмотрели базовые примеры работы с серверными компонентами EJB и серверными страницами Java. Эти технологии предоставляют богатые возможности при создании средних и крупных Web-сайтов, порталов и распределенных интернет-систем. Они могут быть использованы и при создании небольших Web-приложений и интернет-приложений. Это большая область интернет-программирования, рассмотрению которой можно посвятить не одну монографию.
Работаем с CORBAРаботаем с CORBA
Работаем с CORBA
Работаем с CORBA
Глава 9
О технологии CORBA
В этой главе познакомимся с технологией CORBA. Мы не ставим перед собой цель изложить все тонкости и детали во всей полноте. В одной главе это сделать просто невозможно. Технологии CORBA посвящены толстые книги, и освоить ее можно лишь при самостоятельном практическом применении методов работы с CORBA. Эта технология позволяет создавать объекты, доступ к которым может быть осуществлен из различных клиентских приложений. Причем нет никаких ограничений ни для платформы, ни для программного обеспечения. Это мультиплатформенная спецификация. Все, что необходимо знать для того, чтобы обратиться к приложению, — это объект (его имя) и метод (или свойство) объекта.
Начнем с практических шагов. Что нам потребуется? Для рассмотрения примеров необходима будет хотя бы одна из реализаций CORBA. Их существует несколько. Язык Java в версии JDK 1.3 располагает встроенными возможностями создания CORBA-приложений. В варианте Java технология CORBA имеет название Java IDL. В качестве иллюстрации мы рассмотрим простой пример клиент-серверного приложения: клиент обращается к серверу, вызывает метод printYab, сервер содержит имплементацию этого метода, метод выводит текстовую фразу. При работе с CORBA мы будем создавать серверные и клиентские программы, которые общаются друг с другом непосредственно, для них не нужны Web-серверы, они самостоятельны. Программа-сервер и программа-клиент могут быть расположены как на одном и том же компьютере, так и на разных компьютерах, отстоящих друг от друга на тысячи километров, но объединенных сетью, например, сетью Интернет.
Об архитектуре CORBA
Любое взаимодействие между удаленными объектами предполагает наличие клиента и сервера. Сервер предлагает удаленный интерфейс, которым может воспользоваться клиент. Такая модель применяется в технологии RMI, она же работает и в архитектуре CORBA. Здесь следует особо отметить тот факт, что термины "клиент" и "сервер" применяются в отношении объектов, но не в отношении приложений. Приложения могут быть клиентами по отношению к одним объектам и серверами по отношению к другим объектам. Отдельный объект может быть клиентом для интерфейса, предоставляемого другим объектом, и в то же время этот же объект может имплементировать серверный интерфейс, предоставляемый им для других объектов. Методы этого интерфейса будут являться удаленными методами. В качестве примера приведем иллюстрацию взаимодействия удаленных объектов. Распределенный объект располагает единственным методом, который распределяется между сервером и клиентом, это приложение является аналогом классического приложения "Hello World!".
Клиентская часть содержит ссылку на удаленный объект. Эта ссылка используется для получения класса stub, содержащего методы, вызываемые в качестве заместителей соответствующих методов, расположенных на сервере. Класс stub используется брокером ORB. Таким образом, обращение к методу приводит к вызову внутренних механизмов ORB. ORB (Object Request Broker) — это брокер объектных запросов, составной компонент архитектуры CORBA.
На клиентской стороне брокер ORB использует класс stub для выполнения клиентских запросов удаленных методов. На серверной части ORB прибегает к помощи скелетонов. Скелетон переводит запрос и связанные с ним данные в необходимый формат и вызывает соответствующий метод. После завершения работы метода, когда метод возвратил значение, скелетон преобразует полученный результат (или сообщение об ошибке) и передает его клиенту средствами брокера ORB.
Брокеры ORB могут взаимодействовать друг с другом. Общение брокеров друг с другом происходит по протоколу ПОР (Internet Inter-ORB Protocol), по интернет-протоколу передачи данных между брокерами ORB. Протокол ПОР передается поверх протокола TCP/IP.
Помимо стандартных служб, призванных обеспечить работу распределенных объектов, брокеры ORB предлагают расширенный набор сервисов, описанных в стандартах, предложенных группой OMG (Objects Management Group). Среди таких служб можно назвать службу поиска объектов по имени, предоставление возможностей для создания многоуровневых приложений.
Что такое Java IDL?
Отличительной особенностью технологии CORBA является то, что она не зависит ни от платформы, ни от языков программирования. Технология Java IDL предоставляет возможности для работы с распределенными объектами, которые могут взаимодействовать независимо от платформ и языков, на которых они были имплементированы. Во многом технология Java IDL напоминает технологию RMI, которая также предназначена для работы с распределенными объектами, но в последнем случае эти объекты должны быть созданы на языке Java. Используя Java IDL, мы имеем возможность создавать распределенные объекты, которые могут быть созданы с применением и других языков программирования, например, C++, кобола, PHP и т. д. Такие возможности существуют благодаря тому, что технология Java IDL основана на архитектуре CORBA. Основой этой технологии является независимый от конкретных языков программирования метаязык описания интерфейсов (IDL, Interface Definition Language). Для каждого языка существует свой способ отображения стандартного языка IDL в свойственное для этого конкретного языка представление. Технология Java IDL использует отображение языка IDL, свойственное языку Java. Используемые при этом стандарты были разработаны группой OMG, одним из основных участников которой является компания Sun.
Для поддержки возможности взаимодействия между объектами, расположенными в различных программах, технология Java IDL использует так называемый объектный брокер или брокер объектных запросов (ORB). Брокер объектных запросов представляет собой библиотеку классов, при помощи которых происходит низкоуровневое взаимодействие между приложениями Java IDL и другими приложениями, совместимыми с CORBA.
Далее мы рассмотрим процесс создания приложения Java IDL.
Разработка приложений на основе Java IDL
Ранее мы кратко остановились на том, как соотносятся друг с другом клиент и сервер в модели CORBA. Чтобы получить более четкое представление о том, что происходит, необходимо рассмотреть процесс создания приложений Java IDL более детально.
Задание удаленного интерфейса
Интерфейс создается на языке IDL. Это независимый от конкретного языка программирования способ описания интерфейсов. Затем, при помощи компилятора iditojava из файла IDL, создаются все необходимые файлы скелетона и класса stub в версии для языка Java, причем это происходит автоматически. Помимо этого, создается инфраструктура на языке Java, при помощи которой приложение будет взаимодействовать с брокером ORB.
Если возникает необходимость имплементации клиента для уже существующих служб CORBA или необходимость создания сервера для существующего клиента, то в этом случае необходимо получить соответствующее описание интерфейса (на IDL) от разработчика существующих фрагментов приложения. Это обуславливается тем фактом, что создаваемое приложение будет работать именно с этим интерфейсом, а значит, он будет просто необходим. Получив интерфейс, мы имеем возможность преобразовать его в версию, используемую при работе с языком Java, для этого используется компилятор idltojava.
Компиляция классов удаленного интерфейса
Компилятор idltojava, примененный к файлу интерфейса, создает версию этого интерфейса, выраженную средствами языка Java. Помимо собственно интерфейса на Java, компилятор создаст код скелетона и код для класса stub, которые используются при работе с брокером ORB.
Имплементация сервера
Для создания серверного приложения используются классы скелетона. Серверное приложение имплементирует методы удаленного интерфейса, кроме этого, сервер содержит методы запуска брокера ORB. Он также должен обладать методами, с помощью которых начинается "прослушивание" запросов от удаленного клиента.
Имплементация клиента
Базу клиентского приложения составляют классы stub, созданные компилятором. Клиентский код также стартует брокер ORB, производит поиск сервера с помощью службы имен, которая входит в состав Java 1DL, получает ссылку на удаленный объект и вызывает методы удаленного объекта.
Запуск приложения
После того как сервер и клиент имплементированы, запускаем сервис имен, затем стартуем сервер, после чего запускаем клиента.
Перейдем к рассмотрению практических примеров.
Первый пример с Java IDL
Первое, что необходимо сделать, — это разработать интерфейс и описать его в файле IDL (IDL — это Interface Definition Language, язык описания интерфейса, используемый в CORBA). Весь интерфейс мы поместим в IDL-файл.
После того как он будет создан, его необходимо скомпилировать. Для компиляции используется специальная программа-компилятор javatoidi, которая преобразует IDL-файл в несколько файлов на языке Java. Компилятор создаст для модуля отдельную папку, в которую поместит создаваемые им файлы. Назовем модуль YabApp. Внутри модуля мы опишем интерфейс Yab, единственным методом которого будет метод printYab, выводящий текст. Больше файл IDL не будет содержать никакой информации. Интерфейс описывает только методы и свойства, но не конкретизирует, что именно делают эти методы и с чем связаны свойства. Файл Yab.idl запомним в папке с именем javaidl. Компилятор jdij — это обновленная версия компилятора, переводящая описание интерфейса IDL в Java-классы.
; Файл Yab.idl
module YabApp ( interface Yab (
string printYab();
Версия jdki.3.1 включает в себя компилятор idlj.exe, который на основе файла IDL создает клиентские файлы, содержащие классы stub клиентов и серверные скелетоны CORBA. Выполним команду idij -fall Yab.idl. Компилятор создаст папку YabbApp, в которую поместит 6 файлов java:
_YabImpBaase.java;
_YabSub.java;
Yab.java;
YabHelper.java;
YabHolder.java;
YabOperations.java.
Следующим шагом нам предстоит создать еще два файла Java: файл сервера YabServer.java и файл клиента YabClient.java. Затем мы скомпилируем созданное приложение, запустим программу-сервер и программу-клиент. Как только программа-клиент будет запущена, сервер получит от нее запрос, обработает его и отправит ответ. Клиент напишет текст.
Мы не будем на этом этапе рассматривать структуру созданных файлов, остановимся лишь на том, что должно быть в создаваемых нами файлах.
Программа-сервер YabServer.java
Программа-сервер должна включать в себя созданный компилятором пакет YabApp, запишем это:
import YabApp.*;
Кроме того, она включает в себя еще ряд пакетов:
import org.omg.CosNaming.★;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;
Далее мы описываем класс YabServer (см. пример файла YabServer.java), внутри которого содержится функция main о. На первом шаге мы создаем и инициализируем объектный брокер ORB:
ORB orb = ORB.init(args, null);
Затем мы создадим servant и зарегистрируем его у объектного брокера следующим образом:
YabServant yabRef = new YabServant();
orb.connect(yabRef);
Servant — это конкретный класс, который имплементирует абстрактный класс CORBA. В нашем случае класс Servant будет описан в этом же файле YabServer.java (это вовсе не обязательно) вместе с другой частью кода.
Затем необходимо обратиться к службе имен:
org.omg.CORBA.Object objRef =
orb.resolve_initial_references("NameService");
NamingContext ncRef = NamingContextHelper.narrow(objRef);
Связываем наш компонент co службой имен по полученной на предыдущем шаге ссылке:
NameComponent nc = new NameComponent("Yab", "");
NameComponent path[] = {nc} ;
ncRef.rebind(path, yabRef);
И, наконец, приступаем к ожиданию запросов от клиента:
java.lang.Object sync = new java.lang.Object() ;
synchronized(sync){ sync.wait();
Последний фрагмент кода сервера — обработка ошибок.
Приложение Servant с именем YabServant
Servant — это конкретный Java-класс, реализующий конкретную функциональность. В нашем случае servant, с именем YabServant, размещен в файле YabServer.java, но его можно было бы поместить и в отдельный файл.
class YabServant extends _YablmplBase (
public String printYabO
return "\nYa b volchikom skushal ves burokratizm!!!!!!!\n";
} }
Целиком файл YabServer.java выглядит так, как показано ниже.
§ Файл YabServer.java
// Наш пакет. Там клиентские Stubs и прочее
import YabApp.*;.
// Нам нужна служба имен '
import org.omg.CosNaming.*;
// Пакет обработки ошибок org.omg.CosNaming.NamingContextPackage.★;
import org.omg.CosNaming.NamingContextPackage.*;
// Приложения CORBA требуют использовать и эти классы import org.omg.CORBA.*;
public class YabServer
(
public static void main(String args[J)
(
try {
// Создаем и инициализируем ORB
ORB orb = ORB.init(args, null);■
// Создаем Servant и регистрируем его у брокера YabServant yabRef = new YabServant ();
orb.connect(yabRef);
// Обращаемся к службе имен■
оrg.omg.CORBA.Object objRef =
orb.resolve_initial_references("NameService");
NamingContext ncRef = NamingContextHelper.narrow(objRef);
// Связываем наш объект co службой имен
NameComponent nc = new NameComponent("Yab", "");
NameComponent path[] = {nc}; ncRef.rebind(path, yabRef);
// Ждем клиентских запросов
java.lang.Object sync = new java.lang.Object(); synchronized(sync){■
sync.wait(); }
} catch(Exception e) {
System.err.println("ERROR: " + e) ;
e.printStackTrace(System.out);
}■
} }
// Описывем класс Servant
class YabServant extends _YabImplBase {
public String printYabO"
{
return "\nYa b volchikom skushal ves burokratizm!!!!!!!\n";
}
}
Программа-клиент YabClient.java
Следующим нашим шагом будет создание клиента. Он должен включать в себя уже знакомые нам классы: import YabApp.*;
import org.omg.CosNaming.*;
import org.omg.CORBA.*;
Далее, подобно тому, как мы это делали в программе-сервере, создаем объектный брокер ORB:
ORB orb = ORB.init(args, null);
Затем мы обращаемся к службе имен:
org.omg.CORBA.Object objRef =
orb.resolve_initial_references("NameService");
NamingContext ncRef =
NamingContextHelper.narrow(objRef);
Получаем ссылку на объект:
NameComponent nc = new NameComponent("Yab", "");
NameComponent path[] = {nc};
Yab yabRef = YabHelper.narrow(ncRef.resolve(path));
Обращаемся к методу printYab объекта yabRef:
String Yab = yabRef,printYab();
Выводим полученную строку:
System.out.printin(Yab);
Весь файл YabClient выглядит так, как показано ниже.
I Файл YabClient.java-‘
• е.,, ее,..... ее,. е. е.е. е. е.е. е. ееее,ее. ,.•.,. ее*. le<. •.♦.•,•• r»««e*iei*t»e*l».*,ei*»,e,e»><elr*»«ee«,e,e,««*etvK**l*<eee»eVrj.M*«io*>5V#»ei#.e,er#*et,e*»lt*1***,«eei#r#io»ie*eiorj,te*A«,А|*еоеее;е»ее1еее»ю«1ее<еег,юе*»«*^»м*1Х**»**,еЛ
import YabApp.*;
import org.omg.CosNaming.*;
import org.omg.CORBA.*;
public class YabClient
public static void main(String args[])
try{
// Создаем брокер ORB
ORB orb = ORB.init(args, null);
// Обращаемся к службе имен
org.omg.CORBA.Object objRef =
orb.resolve_initial_references("NameService");
NamingContext ncRef = NamingContextHelper.narrow(objRef);
// Получаем ссылку
NameComponent no = new NameComponent("Yab", "");
NameComponent path[] = {no};
Yab yabRef = YabHelper.narrow(ncRef.resolve(path));
// Вызываем метод сервера .
String Yab = yabRef.printYab();
// Выводим результат
System.out.printin(Yab);
} catch(Exception e) {
System.out.printin("ERROR : " + e) ;
e.printStackTrace(System.out);
)
) )
Сейчас необходимо скомпилировать приложение. Для этого откроем окно командной строки и в каталоге c:\javaidl (здесь находятся наши java-файлы), включая файлы YabServer.java и YabClient.java, выполним команду java с *.java. Напоминаем, что на компьютере необходимо установить пакет jdkl.3.1, и переменная path должна содержать путь к установочной папке пакета и к папке /bin этого пакета. Мы получим 9 файлов: классы с именами файлов java и класс YabServant, он был описан в файле YabServer.java.
Запуск приложения
Теперь можно запустить приложение. Первым делом мы запустим сервер, затем — клиент.
Запуск сервера YabServer.class
Перед тем как запустить сервер, необходимо запустить службу имен. Это делается просто. В командной строке выполняем команду:
tnameserv -ORBInitialPort 777
Служба имен начала работу на порту номер 777 (как указано в нашей команде) (рис. 9.1).
Сейчас, когда служба имен работает, можно запустить сервер. Предварительно зададим новое значение переменной classpath, выполнив команду (наши классы находятся в папке c:\javaidl\YabApp) из командной строки:
Set classpath=%classpath%; с:\javaidl\YabApp;с:\javaidl;
Затем запускаем сервер с помощью команды Java YabServer, при этом мы должны находиться в каталоге c:\javaidl\YabApp:
java YabServer -ORBInitialPort 777
Server: Hello there? You are welcome.... Hello, I an client
Client: Hello, I an client
Server: Hello, I an client
How are you?
Client: How are you?
Server: How are you?
I an working promptly
'Client: I am working promptly
Server: I am working promptly
You do also indeed
Client: You do also indeed
Server: You do also indeed
Рис. 9.1. Служба имен стартовала
В конце команды указан номер порта службы имен.
Сервер благополучно стартует (рис. 9.2).
|?>start Java Client
" Iе- ~C:WINM ^tysteas32\|iwu.ene
Рис. 9.2. Сервер запущенРис. 9.2. Сервер запущен? Server: Hello!
Рис. 9.2. Сервер запущен
Рис. 9.2. Сервер запущен
Когда сервер стартует, в окне командной строки не появится никакого сообщения.
Запуск клиента YabClient.class
В качестве параметров при запуске клиента указывается имя хоста и имя порта сервера. Если сервер работает на том же компьютере, что и клиент, то указывать имя хоста необязательно. Команда выглядит так:
java YabClient -ORBInitialPort 777 -ORBInitialHost localhost
Перед запуском клиента (из нового окна командной строки) необходимо еще раз убедиться в том, что переменная classpath содержит требуемые пути, при необходимости следует выполнить команду:
Set classpath=%classpath%;с:\javaidl;с:\javaidl\YabApp
Thin
is my
936
t ry .
Server:
Tills
is ny
937
t г у -
ocruer:
Tills
is my
938
t ry.
Seruer:
This
is my
939
t i\y-
Server:
This
is my
9-to
try =
Se rver:
Thin
is my
941
t ry „
Server:
This
is my
942
try.
Seruer:
This
is my
943
t ry -
Server:
This
is my
944
t r ^ -
Server:
I his
is ns у
9-1b
t г у»
rv e r:
Tliis
is my
946
t ry,.
Server -
This
is my
947
t V у -
^eruer:
Tills
i s rnt у
948
try.
-ver^u p:
This
is my
949
try.
Server:
T1. i s
is my
95И
try™
S e pv r:
This
is my
951
t ry.
Vc rver:
Tills
is ny
952
try.
Server:
This
is my
953
t ry.
Server:
This
is my
954
t Г У-
Serv e 1'5
I his
is my
955
try.
Server^
Tills
is my
956
t ry -
Server:
This
is my
957
try-
Server5
This
is my
958
try.
Server:
I h is
is my
959
try.
Рис. 9.3. Запускаем клиента
Программа-клиент обратилась к серверу, запросила метод printYabo, получила ответ и вывела его на экран. Программа выполнила все, что мы запрограммировали (рис. 9.3).
Компилятор idlj
Теперь посмотрим, что содержится в файлах, автоматически сгенерированных компилятором idlj.
Файл _YablmplBase.java-
Файл _YabImplBase.java содержит каркас серверных методов. Этот файл используем тогда, когда создаем имплементацию серверной функциональности. Мы создали класс Servant на основе класса _YabImplBase:
class YabServant extends _YabImplBase
| Файл _YablmpfBase.java' •' * -•
package YabApp;
public abstract class _YabImplBase extends org.omg.CORBA.portable.Objectliupl implements YabApp.Yab, org.omg.CORBA.portable.InvokeHandler (
// Конструкторы public _YabImplBase () ( }
private static java.util.Hashtable _methods = new java.util.Hashtable (); static {
_methods.put ("printYab", new java.lang.Integer (0)); }
public org.omg.CORBA.portable.Outputstream _invoke (String method, org.omg.CORBA.portable.Inputstream in, org.omg.CORBA.portable.ResponseHandler rh)
{
org.omg.CORBA.portable.Outputstream out = null;
java.lang.Integermethod = (java.lang.Integer)_methods.get (method); if ( method == null)
throw new org.omg.CORBA.BAD_OPERATION (0, org.omg.CORBA.Completionstatus.COMPLETED_MAYBE);
switch ( method.intValue ()) {
case 0:// YabApp/Yab/printYab
(
String result = null;
result = this.printYab ();
out = rh.createReply();
out.write_string (result);
break;
}
default:
throw new org.omg.CORBA.BAD_OPERATION (0, org.omg.CORBA.Completionstatus.COMPLETED_MAYBE);
}
return out; } // _invoke
private static String[] _ids = { " IDL:YabApp/Yab:1.0"};
public String[] _ids () { return ids;
}
} // class _YabImplBase
Файл _YabStub.java
Это файл, содержащий класс stub клиентов.
Файл YabStub.java .''.
package YabApp;
public class _YabStub extends org.omg.CORBA.portable.Objectlmpl implements YabApp.Yab {
public _YabStub () { super (); }'
public _YabStub (org.omg.CORBA.portable.Delegate delegate)
{■
super (); _set_delegate (delegate); }
public String printYab ()
org.omg.CORBA.portable.Inputstream _in = null; try {
org.omg.CORBA.portable.Outputstream _out = _request ("printYab", true); _in = _invoke (_out);
String result = _in.read_string (); return result;
} catch (org.omg.CORBA.portable.ApplicationException _ex) { _in = _ex.getlnputstream (); String _id = _ex.getld (); throw new org.omg.CORBA.MARSHAL (_id);
} catch (org.omg.CORBA.portable.RemarshalException _rm) { return printYab (); } finally {
_releaseReply (_in);
}-
} // printYab
private static String[] ids = { "IDL:YabApp/Yab: 1.0 "};
public String[] _ids () {
return (String[J)ids.clone ();
}
private void readobject (java.io.ObjectlnputStream s)
{ try {
String str = s.readUTF ();
org.ang.OORBA.Object obj = org.arig.OORBA.ORB.init () ,string_to_object (str);
org.omg.CORBA.portable.Delegate delegate =
((org.omg.CORBA.portable.Objectlmpl) obj)._get_delegate ();
_set_delegate (delegate);
} catch (java.io.IOException e) {} }
private void writeObject (java.io.ObjectOutputStream s)
try
String str = org.omg.CORBA.ORB.init ().object_to_string (this); s.writeUTF (str);
} catch (java.io.IOException e) {} }
} // class _YabStub
Файл Yab.java
Этот файл предельно прост.
Файл Yab.java -■
package YabApp;
public interface Yab extends YabOperations, org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity (
} // interface Yab
Файл YabHelper.java
Файл YabHelper.java содержит код, сгенерированный автоматически компилятором idlj.
, Файл YabHelper.java .''
package YabApp;
abstract public class YabHelper (
private static String _id = "IDL:YabApp/Yab:1.0";
public static void insert (org.omg.CORBA.Anу a, YabApp.Yab that) (
org.omg.CORBA.portable.Outputstream out = a.create_output_stream ();
a.type (type ());
write (out, that);
a.read_value (out.create_input_stream (), type ());
}
public static YabApp.Yab extract (org.omg.CORBA.Any a) { return read (a.create_input_stream ()); }
private static org.omg.CORBA.TypeCode typeCode = null; synchronized public static org.omg.CORBA.TypeCode type () { if (typeCode == null) (
typeCode = org.omg.CORBA.ORB.init().create_interface_ tc (YabApp.YabHelper.id (), "Yab");
}
return typeCode;■
}
public static String id () {
return _id; }
public static YabApp.Yab read (org.omg.CORBA.portable.Inputstream istream) (
return narrow (istream.read_Object (_YabStub.class)); }
public static void write (org.omg.CORBA.portable.Outputstream ostream, YabApp.Yab value)
( ostream.write_Object ((org.omg.CORBA.Object) value); }
public static YabApp.Yab narrow (org.omg.CORBA.Object obj) ( if (obj == null)
return null;
else if (obj instanceof YabApp.Yab)
return (YabApp.Yab)obj;
else if (!obj._is_a (id ()))
throw new org.omg.CORBA.BAD_PARAM ();
else
{
org.omg.CORBA.portable.Delegate delegate =
((org.omg.CORBA.portable.Objectlmpl)obj),_get_delegate (); return new YabApp._YabStub (delegate);
}
}
Файл YabHolder.java
Еще один вспомогательный файл, автоматически создаваемый компилятором idlj.
Г.7 )
; Файл YabHolder.java
package YabApp;
public final class YabHolder implements org.omg.CORBA.portable.Streamable {
public YabApp.Yab value = null;
public YabHolder () }
public YabHolder (YabApp.Yab initialvalue) {
value = initialvalue;
}
public void _read (org.omg.CORBA.portable.Inputstream i) {
value = YabApp.YabHelper.read (i) ;.
}
public void _write (org.omg.CORBA.portable.Outputstream o) {
YabApp.YabHelper.write (o, value);
}
public org.omg.CORBA.TypeCode _type () {
return YabApp.YabHelper.type ();
}
}
Файл YabOperations.java
Файл YabOperations.java содержит один интерфейс, в котором объявлен один метод printYab ().
Файл YabOperations.java .'
package YabApp;
public interface YabOperations
(
String printYab ();
} // interface YabOperations"
В этой части мы научились создавать несложные CORBA-приложения с использованием Java IDL. Далее мы рассмотрим базовые возможности, предоставляемые реализацией архитектуры технологии CORBA, созданной компанией Borland.
C++ CORBA и Visibroker
Существует множество реализаций CORBA. Рассмотрим создание приложений с помощью среды Visibroker. Программу Visibroker можно получить через Интернет с сайта производителя http://www.borland.com. Полный объем файлов дистрибутивов для языков C++ и Java составляет около 50 Мбайт. Не спешите сразу устанавливать .пакет для C++. Предварительно необходимо установить среду выполнения Java, Java Runtime Environment. Если у вас ее нет, то ее можно получить бесплатно на сайте компании Sun.
После того как Visibroker в версии для языка C++ установлен, осуществим практические действия и выполним стандартные примеры, которые поставляются в комплекте дистрибутива. Мы не будем вдаваться в структуру CORBA на этом этапе. Сейчас для нас важным является то, что CORBA позволяет достаточно легко создавать сложные распределенные приложения, в частности создавать приложения, работающие совместно, как клиент и сервер. Удобство здесь заключается в том, что, с одной стороны, при создании приложений нам не придется непосредственно работать с сетью, нет необходимости работать с классами сокетов, весь механизм уже предварительно реализован и скрыт от разработчика, что упрощает дело. С другой стороны, созданные объекты будут весьма независимы и через механизм объектного брокера могут быть доступны различным приложениям, как тем, что мы будем создавать сами, так и другим, "чужим" приложениям, которые могут находиться в разных частях сети, в том числе в сети Интернет.
Еще раз повторим, что важным компонентом архитектуры CORBA является язык описания интерфейса IDL. При помощи этого языка в отдельном файле мы описываем интерфейс, т. е. описываем набор объектов и свойств, которые принадлежат интерфейсу. Сохраняем файл с расширением idl. Затем в работу вступает компилятор, который на основе IDL-описания создает четыре файла на языке C++. Ранее, в настоящей главе, мы использовали отображение описания интерфейса в вариант на языке Java.
Рассмотрим пример интерфейса (файл Bank.idl):
Файл Bankadl.)
module Bank{
interface Account { float balance();
};
interface AccountManager {
Account open(in string name);
);■
};
Здесь описан общий модуль Bank, в состав которого входят два интерфейса. В составе интерфейсов описаны методы. Интерфейс Account имеет вещественный метод balance, а интерфейс AccountManager содержит метод open, относящийся к интерфейсу Account. Параметром (входным, передаваемым) является строка с именем name.
Первый пример
На основе этого файла, содержащего описание интерфейса, Visibroker создает клиентские файлы, содержащие классы stub клиентов, и серверные файлы, с которыми будут связаны классы servant. Компиляция осуществляется из командной строки выполнением команды:
Cpp2idl.exe bank.idl.
В результате получается четыре файла:
Bank_c.hh — файл содержит описания классов Account и AccountManager;
Bank_c.cc — содержит внутренние процедуры, используемые клиентом. Здесь расположены клиентские файлы, содержащие классы stub клиентов;
Bank_s.hh — содержит описания классов сервера РОА_вапк::Account И POA_Bank: :AccountManager, ЭТО серверные Классы Servant;
Bank_s.cc — содержит внутренние процедуры, используемые сервером.
Для создания клиента используются файлы Bank_c.hh и Bank_c.cc. Компилятор создает файлы с расширениями двух типов: сс и hh. Задача упрощается до минимума. Нам необходимо установить на компьютер компилятор C++ и выполнить команду:
Nmake — f makefile.cpp.
При этом мы должны находиться в каталоге basic/bank_agent. Все файлы будут автоматически обработаны, и создан файл server.exe и client.exe. Эти файлы создаются на основе заранее подготовленных программ, приведенных далее.
Клиентской код clientc
♦include "Bank_c.hh"
int main(int argc, char* const* argv) (
try {
// Инициализация брокера
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
// Получение идентификатора менеджера
Portableserver::ObjectId_var managerld =
Portableserver::string_to_Object!d("BankManager");
// Нахождение менеджера счета, указание полного имени объектного
// адаптера РОА и идентификатора Servant
Bank::AccountManager_var manager =
Bank::AccountManager::_bind("/bank_agentj;oa", managerld);
// Имя счета указано в argv[l] или используется то, что по умолчанию const char* name = argc > 1 ? argv[l] : "Jack B. Quick";
// Запрос к менеджеру открыть счет
Bank::Account_var account = manager->open(name);
// Получить баланс счета balance = account->balance();
// Напечатать баланс
cout « "The balance in " « name « *"s account is $" « balance « endl;
}
catch(const CORBA:Exceptions e) { cerr « e « endl; ■ return 1;
}
return 0;
}
: Серверный код server.c:
#include "Banklmpl.h"
int main(int argc, char* const* argv)
(
try (
// Инициализация брокера ORB
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
// Ссылка на основной объектный адаптер РОА
CORBA::Object_yar obj = orb->resolve_initial_references("RootPOA") ; PortableServer::POA_var rootPOA = Portableserver::POA::_narrow(obj);
CORBA::PolicyList policies;
policies.length(1);
policies[(CORBA::ULong)0] = rootPOA->create_lifespan_policy( Portableserver::PERSISTENT);
// Получение менеджера адаптера Portableserver::POAManager_var poa_manager = rootPOA->the_POAManager();
// Создание нового адаптера по указанным политикам
Portableserver::P0A_var myPOA = rootPOA->create_POA("bank_agent_poa", poa_manager, policies);
// Создание Servant
AccountManagerImpl managerservant;
// Идентификатор Servant
Portableserver::ObjectId_var managerld = Portableserver::string_to_Object!d("BankManager");
// Активизация Servant по идентификатору с использованием myPOA myPOA->activate_object_with_id(managerld, smanagerServant);
// Активизация менеджера адаптера poa_manager->activate();
CORBA::0bject_var reference = myP0A-> servant_to_reference(smanagerServant); cout « reference « " is ready" « endl;
// Ожидание входящих запросов orb->run();
}
catch(const CORBA::Exceptions e) (
cerr « e « endl;
return 1; }
return 0;
Чтобы завершить краткий обзор первого примера CORBA-приложений, нам будет необходима команда SmartAgent. Запускаем пример из меню Start. Информация о работе программы будет храниться в файле логов (рис. 9.4).
Рис. 9.4. Файл логов агента SmartAgent
Затем запускаем server.exe (рис. 9.5).
Microsoft(R) Windows 98
(C)Copyright Microsoft Corp 1981-1999.
C:\Inprise\vbroker\examples\basic\bank_agent>cli ent
The balance in Jack 8. Quick's account is $0.41
C:\lnprise\vbroker\examples\basic\bank_agent>client
The balance in Jack B. Quick's account is $0.41
C:\Inprise\vbroker\examples\basic\bank_agent>client
The balance in Jack B. Quick's account is $0.41
C:\lnprise\vbroker\examp1es\basic\bank_agent>
Рис. 9.5. Запущен сервер
После этого несколько раз запустим клиента (рис. 9.6) из консоли.
Рис. 9.6. Несколько раз был запущен клиент, запрашивающий баланс на счету
В окне SmartAgent будет показана информация о запросах (рис. 9.7).
************************************************
Time: Sat Jul 07 14:57:00 2001
— Received a areYouAlive message from client-* Host Name: olvmo Client User name: olymp
Process id:-1655733
***********************************************
************************************************
Time: Sat Jul 07 14:57:58 2001
—The following client is down*
Host Name: olvmo
Client User name: olymp
Process Id: -1655733
*ннннннннннннмннннннмнннмннннннннннннннмннннмнне
DSACIientHandler:removeClient: Removina client
************************************************
Time: Sat Jul 07 14:57:58 2001
— Deleting the following client*
Host Name: olvmo
Client User name: olymp
Process id:-1655733
************************************************
Рис. 9.7. Агент сообщает о происходящих действиях
Далее мы разберем более подробно то, что происходит в создаваемых компилятором и разработчиком программах.
Что происходит в программе client.c?
Перед тем как наша клиентская программа сможет вызвать метод open (string name), необходимо сначала запустить метод bind о для того, чтобы создать соединение с сервером, в котором имплементирован объект AccountManager. Имплементация самой функции bind о осуществляется автоматически при работе компилятора idl2.cpp. Эта функция создает запрос к ORB о нахождении сервера и установки связи с ним. Если сервер успешно был найден, а связь благополучно установлена, то создается прокси-объект, соответствующий объекту сервера POA_Bank::AccountManager. Клиентская программа получает указатель на объект AccountManager.
Затем клиентская программа будет стремиться вызвать функцию open () объекта AccountManager, чтобы получить указатель на объект Account, где содержится конкретное имя владельца счета. После того как соединение установлено и объект Account найден, можно переходить к выполнению функции balance (). Функция balance () на клиентской части появляется в коде stub, создаваемого компилятором id2.cpp. Эта функция получает все необходимые данные на клиенте и отправляет их серверу. Другие функции нужны для того, чтобы иметь возможность осуществлять работу со ссылками на объект Account Manager.
Что происходит в программе-сервере server.c?
Эта программа имплементирует класс сервера. Программа инициализирует объектный брокер, создает портируемый объектный адаптер (РОА), создает объект Servant, активизирует его, активизирует менеджер РОА, ждет входящие запросы. В дальнейшем мы рассмотрим это базовый пример более подробно. Сейчас же, для полноты картины, необходимо привести листинг файла Banklmpl.h:
#include "Bank_s.hh"
#include <math.h>
class AccountRegistry
(
public:
AccountRegistry() : _count(0), _max(16), _data((Data*)NULL) (
data = new Data[16];
~AccountRegistry() { delete[] _data; }
void put(const char* name, Portableserver::ServantBase_ptr servant) { if (_count + 1 == _max) ( Data* oldData = _data;
_max += 16;
_data = new Data[_max);
for (CORBA::ULong i = 0; i < _count; i++)
_data[i] = oldData[ i ];
delete[] oldData; }
—data[—Count].name = name;
servant->_add_ref();
—data[—Count].account = servant;
_count++;
}
Portableserver::ServantBase_ptr get(const char* name) ( for (CORBA::ULong i = 0; i < _count; i++) ( if (strcmp(name, _data[i].name) = 0) {
—data[i].account->_add_ref();
return _data[i].account; }
return Portableserver::ServantBase::_nil();
}
private:
struct Data (
CORBA::String_varname;
Portableserver::ServantBase_var account;
CORBA::ULong _count;
CORBA::ULong _max;
Data* data;
class Accountlmpl : public virtual POA_Bank::Account,
public virtual Portableserver::RefCountServantBase
public:
Accountlmpl(CORBA::Float balance) : —balance(balance) {}
CORBA::Float balance() { return —balance; } private:
CORBA::Float balance;
class AccountManagerlmpl : public.POA_Bank::AccountManager (
public:
AccountManagerlmpl() {}
Bank::Account—ptr open(const char* name) { // Поиск счета
Portableserver::ServantBase_var servant = _accounts.get(name); if (servant == Portableserver::ServantBase::_nil()) { // Задание баланса счета
CORBA::Float balance = abs(randO) % 100000 / 100.0;
// Имплементация счета servant = new Accountlmpl(balance);
// Вывод баланса счета cout « "Created " « name « "'s account." « endl; // Запомнить счет _accounts.put(name, servant);
} try { // Активация адаптера Portableserver::РОА—var default—poa = _default_POA();
CORBA::0bject_var ref = default—poa->servant_to_reference(servant); Bank::Account_var account = Bank: -.Account: :_narrow (ref) ;
// Вывод нового баланса
cout << "Returning " « name << "' s account: " « account << endl;
// Возврат счета
return Bank::Account::_duplicate(account); }
catch(const CORBA::Exceptions e) { cerr « "_narrow caught exception: " « e « endl; }
return Bank::Account::_nil();
}
private:
AccountRegistry _accounts;
};■
В этом файле описаны детали форматирования баланса в соответствии с именем его владельца.
Объектный брокер ORB осуществляет связь между запросами клиента и имплементированными объектами. Каждое приложение должно инициализировать объектный брокер до того, как сможет с ним начать коммуникацию. Объектный брокер инициализируется строкой:
CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);
Ранние версии реализаций CORBA использовали базовый объектный адаптер ВОА, более поздние версии основываются на портируемом объектном адаптере РОА. Попросту говоря, портируемый объектный адаптер определяет, к какому объекту Servant необходимо обращаться в случае получения того или иного клиентского запроса, затем вызывается именно этот servant, servant не является объектом CORBA. Servant — это обычный программный объект, представляющий собой имплементацию абстрактного объекта. Каждый объектный брокер имеет портируемый объектный адаптер и основной адаптер, или root РОА. Программист имеет возможность создавать дополнительные адаптеры и конфигурировать их надлежащим образом. Можно задавать характеристики объектов, которые, тем не менее, должны контролироваться адаптером РОА. Вот основные шаги при работе с РОА и объектами servant:
получение ссылки на базовый РОА;
определение политик (policies) для РОА;
создание нового РОА как дочернего РОА;
создание объекта servant и его активизация;
активизация РОА через менеджера.
В зависимости от разрабатываемого приложения, эти шаги могут быть различными.
424424Гпава 9
424
424
Получение ссылки на базовый РОА
Все приложения должны получить ссылку на базовый РОА для того, чтобы иметь возможность работать с объектами или для создания нового РОА. Рассмотрим пример кода, получающего ссылку на базовый РОА:
// Ссылка на базовый РОА
CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");
// Сужение ссылки
Portableserver::POA_var rootPOA = Portableserver::РОА::_narrow(obj);
Ссылка на базовый РОА может быть получена с использованием метода:
resolve_initial_references.resolve_initial_references
Возвращаемое значение имеет тип corba: :object. Мы можем сузить тип до желаемого, как, например, это сделано в приведенном выше примере:
Portableserver::РОА;
Затем полученная ссылка может быть использована для создания (в случае необходимости) другого РОА.
Создание дочернего РОА
Базовый РОА имеет заранее установленный набор политик, этот набор не может быть изменен. Политика — это объект, который контролирует поведение РОА и тех объектов, которыми управляет этот РОА. Если требуется другое поведение, то необходимо создать новый РОА. Он может быть создан в качестве наследника, т. е. дочернего РОА с использованием метода create_POA. Можно создать любое требуемое число РОА. Созданные РОА не наследуют родительские политики. В примере, приведенном ниже, дочерний РОА создан на основе базового и имеет постоянную жизненную политику. Менеджер базового РОА используется для управления состоянием дочернего.
CORBA::PolicyList policies;
policies.length(1);
policies[(CORBA::ULong)0] = rootPOA->create_lifespan_policy(
Portableserver::PERSISTENT);
// Создание нового адаптера myPOA с указанными политиками
Portableserver::POAManager_var rootManager = rootPOA->the_POAManager();
Portableserver::P0A_var myPOA = rootPOA->create_POA("bank_agent_poa",
rootManager, policies);
Имплементация методов Servant
Язык описания интерфейса IDL имеет синтаксис, схожий с синтаксисом C++. Он может использоваться для задания модулей, интерфейсов, структур и других конструкций. При компиляции IDL-файла, в котором описан интерфейс, происходит создание класса, который служит основным классом для класса servant. Так, в файле bank.idl описан интерфейс AccountManager: module Bank{ interface Account {
float balance();
};
interface AccountManager {
Account open (in string name);■
}; };
Серверная имплементация AccountManager выглядит так:
class AccountManagerlmpl : public POA_Bank::AccountManager { private:
Dictionary _accounts;
public: virtual Bank::Account_ptr open(const char* name) { // Поиск счета
Bank::Account_ptr account = (Bank::Account_ptr) _accounts.get(name); if(account — Bank::Account::_nil()) { // Задание баланса счета float balance = abs(randO) % 100000 / 100.0; // Имплементация счета Accountlmpl *accountServant = new Accountlmpl(balance) ; try {
// Активация адаптера
Portableserver::P0A_var rootPOA = _default_POA();
CORBA::0bject_var obj = rootPOA-> servant_to_reference(accountservant); account = Bank::Account::_narrow(obj); } catch(const CORBA::Exceptions e) {
cerr « "_narrow caught exception: " « e « endl; } // Печать баланса cout « "Created " « name « '"s account: " « account «
endl ;
// Сохранение счета
_accounts.put(name, account); }
// Возвратили счет
return Bank::Account::_duplicate(account); }
};
Имплементация AccountManager должна быть создана и активирована в серверном коде. В нашем примере AccountManager активизируется с использованием метода activate_object_with_id, который передает идентификатор объекта В карту Active Object Мар для записи. Карта Active Object Map представляет собой таблицу с идентификаторами id, которая отображает идентификаторы в соответствующие им объекты Servant. Такой метод гарантирует, что объект будет всегда доступен, если активен РОА. Этот метод носит название метода явной активизации объектов (explicit object activation). В следующем примере мы создаем и активизируем объект Servant.
// Создание Servant
AccountManagerImp1 managerservant;
// Идентификатор Servant
Portableserver::ObjectId_var managerld =
Portableserver::string_to_ObjectId("BankManager");
// Активация Servant
myPOA->activate_object_with_id(managerld,SmanagerServant);
Активизируем РОА
Последний этап — активизация менеджера РОА, связанного с нашим РОА. По умолчанию менеджер РОА создается в состоянии ожидания. При этом все запросы направляются в очередь ожидания и не обрабатываются. Чтобы разрешить обработку запросов и их перенаправление, необходимо перевести РОА из состояния ожидания в активное состояние. Менеджер РОА — это объект, контролирующий состояние РОА (постановка запросов на ожидание, обработка запросов, отклонение запросов). Менеджер РОА связывается с самим РОА во время его создания. При этом можно указать, какой менеджер будет использован, либо поручить системе самой создать новый менеджер. Для этого необходимо указать в качестве имени менеджера литерал null В методе create_POA().
// Активизируем менеджер адаптера
PortablServer::POAManager_var mgr=rootPoa ->the_POAManager();
mgr->activate();
Активизация объектов
Мы уже упомянули о явной активации объектов. Существует несколько способов активации объектов:
явный способ подразумевает, что все объекты активизируются во время старта сервера посредством обращений к РОА;
активизация по требованию происходит тогда, когда менеджер servant активизирует объект при получении запроса к объекту servant, не связанному с идентификатором объекта;
неявная активизация происходит в том случае, когда объекты активизируются в ответ на действия РОА, а не как следствие запроса клиента;
активизация по умолчанию происходит тогда, когда РОА использует объект servant, который задан как объект, используемый по умолчанию для обработки клиентских запросов.
Ожидание клиентских запросов
После того как РОА создан, можно приступить к ожиданию клиентских запросов. Просто вызываем функцию orb.runt). Этот процесс будет работать до тех пор, пока не прекратит работу сервер.
// Ожидание входящих запросов
orb->run();
Вот полный код сервера, описанный в этой главе:
// Server.С
#include "Bank_s.hh"
#include <math.h>
class Dictionary {
private:
struct Data {
const char* name;
void* value;
};
unsigned _count;
Data* _data;
public:
Dictionary() {
_count = 0;
}
void put(const char* name, void* value) (
Data* oldData = _data;
_data = new Data[_count + 1 ];
for(unsigned i = 0; i < _count; i++) {
_data[i] = oldData[i]; }
_data[_count].name = strdup(name);
_data[_count].value = value;
_count++;
}
void* get(const char* name) (
for(unsigned i = 0; i < _count; i++) {
if(!strcmp(name, _data[i].name)) ( return _data[i].value;
} } return 0;
}
};
class Accountlmpl : public POA_Bank::Account { private:
float —balance;
public:
Accountlmpl(float balance) {
—balance = balance;
}
virtual float balance() { return —balance;
}
};
class AccountManagerlmpl : public POA_Bank::AccountManager ( private:
Dictionary _accounts;
public:
virtual Bank::Account—ptr open(const char* name) ( // Поиск счета
Bank::Account—ptr account = (Bank::Account—ptr) _accounts.get(name);
if(account = Bank::Account::_nil()) (
// Задание баланса счета
float balance = abs(rand()) % 100000 / 100.0;
// Имплементация счета
Accountlm.pl *accountServant = new Accountlmpl(balance); try {
// Активизация адаптера
Portableserver::POA_var rootPOA = _default_POA();
CORBA::Object_var obj = rootPOA->
servant_to_reference(accountservant);
account = Bank: .'Account: :_narrow (obj ) ;
} catch(const CORBA::Exceptions e) { cerr « "_narrow caught exception: " « e « endl;
}
// Печать нового баланса
cout « "Created " « name « ’"s account: " « account « endl ;
// Запомнить счет
_accounts.put(name, account); }
// Возвращаем счет
return Bank::Account::_duplicate(account); }
};
int main(int argc, char* const* argv) { try {
// Инициализируем брокер ORB
CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);
// Ссылка на базовый адаптер
CORBA::0bject_var obj = оrb->resolve_initial_references("RootPOA"); // Сужение ссылки
Portableserver::POA_var rootPOA = Portableserver::POA::_narrow(obj);
CORBA::PolicyList policies;
policies.length(1);
policies[(CORBA::ULong)0] = rootPOA->create_lifespan_policy( Portableserver::PERSISTENT );'
// Создание адаптера myPOA по указанным политикам
Portableserver::POAManager_var rootManager = rootPOA->the_POAManager(); Portableserver::POA_var myPOA = rootPOA->create_POA(
"bank_agent_poa", rootManager, policies);
// Создание менеджера Servant
AccountManagerlmpl managerServant;
// Идентификатор Servant
Portableserver::Objectld_var managerld =
PortableServer::string_to_Object!d("BankManager");
// Активизация Servant
myPOA->activate_object_with_id(managerld,SmanagerServant);
// Активизация менеджера адаптера
rootPOA->the_POAManager()->activate();
cout « myPOA->servant_to_reference(&managerServant) « " is ready" « endl;
// Ожидание входящих запросов
orb->run();
} catch(const CORBA::Exceptions e) {
cerr « e « endl;
POA
Мы много говорили о РОА. Остановим внимание на более подробном описании портативного адаптера объектов. Портативным мы называем его не потому, что он маленький, а от слова "порт", удобнее называть его портируемым. Он осуществляет возможность соединения с ним на серверной стороне. Объектный адаптер представляет собой переходное звено между имплементацией объекта и брокером объектных запросов ORB. В качестве такого посредника адаптер выполняет функции перенаправления запросов к объекту Servant, и в случае необходимости это может привести к запуску Servant и созданию новых РОА. Серверы могут поддерживать по несколько РОА, но хотя бы один должен обязательно присутствовать, это базовый РОА. Он создается автоматически. Множество всех РОА устроено иерархически, все они имеют в качестве общего "родительского" брокера базовый РОА. Менеджеры servant устанавливают соответствия между классами servant и активными объектами. Когда абстрактный объект ставится в соответствие Servant, такой объект называется активным объектом, а соответствующий ему класс Servant имплементирует этот объект. Каждый РОА имеет одну таблицу отображений Active object мар, в которой содержится информация об активных объектах и соответствующих им классах servant. Общая структура архитектуры РОА приведена в документации (рис. 9.8).
Сейчас мы остановимся лишь на основных концепциях, касающихся РОА. Полезно свести используемую в дальнейшем терминологию в одну таблицу (табл. 9.1).
Таблица 9.1. Терминология, используемая при описании РОА
Термин
Значение
Active Object Map — карта активных объектов
Таблица, которая сопоставляет активным объектам CORBA (посредством указания их идентификаторов id) объекты Servant. Для каждого РОА существует единственная карта активных объектов
Adapter activator — активатор адаптера
Объект, который может создать РОА при необходимости, если будет получен запрос к дочернему объекту, который еще не существует
Etherealize — девоплощение (развоплоще- ние, эфиризация)
Снятие соответствия между объектами Servant и абстрактным объектом CORBA■
Incarnate — воплощение (инкарнация)
Object ID — идентификатор объекта
Установление связи между объектом Servant и абстрактным объектом CORBA
Идентификатор объекта — это способ идентифицировать объект для объектного адаптера. Он создается либо объектным адаптером, либо приложением и является уникальным в пределах РОА, в котором он создается. Объекты Servant связываются с абстрактными объектами через их идентификаторы ObjectlD
■Таблица 9.1 (окончание)
Термин
Значение-
Persistent object — постоянный персистентный объект
CORBA-объект, продолжающий существовать вне серверного процесса, который его создал
РОА manager — менед
жер РОА
Объект, который управляет состоянием РОА, в частности отвечает за то, получает или отклоняет РОА входящие запросы
Policy — политика
Объект, который управляет поведением РОА, а также тех объектов, которые контролирует РОА
RootPOA — базовый РОА
Каждый РОА создается внутри исходного, базового РОА, root РОА. На основе этого базового могут быть созданы другие РОА
Servant — объект Servant
Любой код, имплементирующий методы объекта CORBA, который сам не является объектом CORBA
Servant manager —
менеджер Servant
Объект, отвечающий за поддержание соответствий между объектами и Servant и определяющий факт существования того или иного объекта. Может существовать несколько менеджеров Servant
Transient object — местный локальный объект
Объект CORBA, который существует только внутри создавшего его процесса
Поэтапное создание и использование РОА
В каждом конкретном случае процесс создания РОА будет разным. Однако можно выделить основные шаги, которые приходится проходить при работе с РОА. Вот эти шаги:
Задание политик.
Создание РОА.
Активизация РОА с помощью менеджера РОА.
Создание и активация объектов Servant.
Создание и использование менеджеров Servant.
Использование активаторов адаптера.
В зависимости от поставленных задач, некоторые из перечисленных шагов могут быть опущены. Например, если необходима только обработка запросов, то достаточно лишь активизировать РОА.
Политики для РОА
Каждый РОА имеет набор политик, которые определяют характеристики этого РОА. При создании РОА можно использовать набор политик, предлагаемых по умолчанию, либо создать другой набор, который соответствует требованиям. Политики могут быть заданы только в момент создания РОА, после этого они не могут быть изменены. РОА не наследуют политик от родительских РОА. Сейчас мы рассмотрим политики несколько более подробно.
Политики потоков (тредов, легковесных процессов)
Политики потоков задают модель легковесных процессов, которая будет использоваться в РОА. Политика потока может принимать следующие значения:
orb_ctrl_model (используется по умолчанию)
РОА должен связать запрос с потоком. В многопоточном окружении запросы, идущие одновременно, могут выполняться в самостоятельных потоках. Visibroker использует многопоточную модель;
SINGLE_THREAD_MODEL
РОА обрабатывает запросы последовательно.
Политики жизненного цикла
Политики жизненного цикла устанавливают тип объекта в РОА. Могут быть заданы следующие типы жизненного цикла:
TRANSIENT (ПО умолчанию)
Локальный или местный объект, созданный РОА, не может существовать вне пределов процесса, создавшего его. Как только РОА дезактивируется, возникает ошибка OBJECT_NOT_EXIST при любой попытке использования ссылок на объекты, созданные этим РОА;
PERSISTENT'
Постоянный персистентный объект может существовать за пределами процесса, его породившего. Запросы, касающиеся персистентного объекта, могут привести к неявной активации процесса.
Политики уникальности идентификатора объекта
Политики уникальности идентификатора объекта позволяют одному и тому же объекту servant обслуживать несколько абстрактных объектов. Значениями политики уникальности идентификатора объекта могут быть следующие:■
UNIQUE_ID (по умолчанию)
Активированный servant может поддерживать только один идентификатор объекта objectid;
MULTIPLE_ID
Активированные Servant могут иметь один или несколько идентификаторов объектов. Идентификатор объекта должен быть определен внутри метода, вызываемого во время выполнения.
Политики назначения идентификатора
Политики назначения идентификатора определяют, что задает идентификатор объекта: серверное приложение или РОА. Политика назначения идентификатора может иметь следующие значения:
USER_ID
Идентификатор объекта назначается объекту приложением;
system_id (по умолчанию)■
Объекты получают идентификаторы объектов objectiD от РОА. Если к тому же установлено значение политики жизненного цикла, равное persistent, то идентификатор объекта должен быть уникален для всех элементов, относящихся к данному конкретному РОА. Как правило, user_id используется для персистентных объектов, a system_id — для локальных. Если мы будем использовать system_id для персистентных объектов, то требуется получить идентификатор объекта от РОА.
Политики сохранности объекта Servant
Политика сохранности объекта servant устанавливает, будет ли РОА сохранять активные Servant в карте активных объектов. Политика сохранности servant может принимать такие значения:
retain (по умолчанию)
РОА сохраняет активные объекты в карте Active object мар;
NON_RETAIN'
РОА не оставляет активные объекты Servant В карте Active Object Map.
Политики обработки запросов
Политики обработки запросов определяют, как РОА будет обрабатывать запросы:
USE_ACTIVE_OBJECT_MAP_ONLY (ПО уМОЛЧЗНИю)
Если идентификатор объекта содержится в карте активных объектов Active object мар, то возвращается исключение object_not_exist;
USE_DEFAULT_SERVANT
Если идентификатор объекта не содержится в карте активных объектов, то запрос направляется к объекту servant, который указан как объект, используемый по умолчанию. Если Servant по умолчанию не зарегистрирован, то возвращается исключение obj_adapter;
USE_SERVANT_MANAGER
Если идентификатор активного объекта не указан в карте активных объектов (или установлена политика non_retain), то для получения объекта servant используется менеджер этого объекта servant.
Политики неявной активации
Политика неявной активации задает возможность поддержки неявной активации объектов servant. Политика неявной активации может принимать такие значения:
IMPLICIT_ACTIVATION
РОА поддерживает неявную активацию. Объекты servant могут быть активированы путем преобразования в ссылку на объект с помощью метода роа: :servant_to_reference о или через вызов указателя _th±s о объекта Servant. В РОА также необходимо задать system_id и retain;
no_implicit_activation (по умолчанию)
РОА не поддерживает неявную активацию.
Создание РОА
Чтобы имплементировать объекты с использованием РОА, необходимо, чтобы, по крайней мере, базовый РОА на сервере существовал. Для того чтобы базовый РОА заведомо присутствовал, базовый rootPOA создается в момент инициализации ORB. Этот РОА использует политики, установленные по умолчанию. Коль скоро базовый РОА существует, мы имеем возможность создавать на его основе дочерние РОА.
Соглашение о названиях для РОА
В каждом РОА содержится информация о его имени и полном имени (включая весь иерархический путь). Иерархии разделяются символом косая черта /. Так, например, /а/в/с означает, что РОА с именем с является дочерним по отношению к РОА с именем в, который в свою очередь является дочерним к РОА с именем а. Первый символ косой черты обозначает базовый РОА. Если в имени РОА встречаются какие-либо специальные символы, то они будут предварены символом двойной обратной косой черты:
Portableserver::POA_var myPOAl = rootPOA->create_POA("A/B",
poa_manager, policies);
Portableserver::POA_var myP0A2 = myPOAl->create_POA("\t",
poa_manager, policies);
Клиент будет связан следующим образом:
Bank::AccountManager_var manager = Bank::AccountManager::_ bind("/A\\/B/\t", managerld);
Получаем базовый rootPOA
Этот пример показывает, как серверное приложение получает базовый rootPOA:
// Инициализация брокера
CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");
// Ссылка на базовый адаптер
Portableserver::POA_var rootPOA = Portableserver::РОА::_narrow(obj);
Здесь опять метод resoive_initiai_references возвращает значение типа corba: :object. Нам необходимо сузить его до желаемого типа Portableserver::РОА.
Задание свойств РОА
Политики РОА не наследуются от родительского РОА. Если нужно иметь какие-либо особенные характеристики РОА, то следует изменить его политики. Например:
CORBA::PolicyList policies;
policies.length(1);
policies[(CORBA::ULong)0] = rootPOA-> create_lifespan_ policy(Portableserver::PERSISTENT);
Создание и активация РОА
РОА создается с использованием метода create POA в родительском РОА и может быть назван произвольным образом. Однако это имя должно быть уникальным в пределах всех РОА, созданных от одного родителя. Если мы попытаемся двум РОА присвоить одинаковые имена, то возникнет исключение AdapterAireadyExists — адаптер уже существует. Для того чтобы создать новый РОА, пишем:
РОА create_POA(POA_Name, POAManager, PolicyList};
Менеджер РОА управляет состоянием РОА (например, задает, будет ли РОА обрабатывать запросы). Если в качестве имени менеджера POAManager передано значение null, то создается объект менеджера РОА, который будет связан с этим РОА. Как правило, для всех РОА удобно иметь один и тот же менеджер РОА. Менеджеры РОА и сами РОА не активируются автоматически в момент их создания. Чтобы их активизировать, необходимо использовать метод activate ().
CORBA::PolicyList policies;
policies.length(1);
policies[(CORBA::ULong)0] = rootPOA->create_lifespan_ policy(Portableserver::PERSISTENT);
// Создание нового адаптера по указанным политикам
Portableserver::POAManager_var rootManager = rootPOA->the_POAManager();
PortableServer::POA_var myPOA =
rootPOA->create_POA("bank_agent_poa", rootManager, policies);
Активация объектов
Если объекты CORBA связаны с активным объектом Servant и политика сохранности (Servant Retention Policy) servant равна retain, to идентификатор объекта записывается в карту активных объектов, и тем самым объект оказывается активированным. Активация может произойти одним из следующих способов:■
явная активация
Серверное приложение само по себе явно активирует объект посредством вызова методов activate_object ИЛИ activate_object_with_id;
активация по запросу
Серверное приложение побуждает РОА активировать объекты через посредничество менеджера Servant, который предварительно должен быть зарегистрирован в РОА с использованием метода set_servant_manager;
неявная активация
Сервер активирует объекты исключительно в ответ на какие-либо действия. Если объект Servant не активен, то клиент ничего не может сделать, что привело бы к его активации (например, запрос к неактивному объекту не сможет сделать его активным);
объект Servant по умолчанию
РОА использует единственный Servant для имплементации всех своих объектов.
Явная активация объектов
Если задать значение политики idAssignmentPolicy:: system_id, то объекты могут быть явно активированы без необходимости указания идентификатора объекта. Сервер вызывает метод activate_object, с помощью которого активирует объект, присваивает идентификатор и возвращает его значение. Такой тип активации наиболее свойственен локальным объектам. В этом случае менеджер Servant не нужен, поскольку ни объект сам по себе, ни соответствующий ему Servant не будут нужны на протяжении длительного срока.
Объекты могут быть явно активированы с использованием идентификатора объекта. Например, во время инициализации сервера, когда пользователь
вызывает метод activate_object_with_id. Менеджер объекта servant также не нужен.
// Создание менеджера Servant
AccountManagerlmpl managerservant;
// Идентификатор Servant
Portableserver::0bjectld_var managerld =
Portableserver::string_to_ObjectId("BankManager");
// Активизация Servant
myPOA->activate_object_with_id(managerld,&managerServant);
// Активизация менеджера адаптера
Portableserver::POAManager_var rootManager = rootPOA->the_POAManager(); rootManger->activate();
Активация объектов no запросу
Активация по запросу происходит тогда, когда клиент запрашивает объект, который не имеет связанного с ним объекта Servant. После получения запроса РОА ищет в карте активных объектов Servant с заданным идентификатором объекта. Если таковой не обнаруживается, РОА вызывает метод incarnate в менеджере объектов servant, который и передает менеджеру идентификатор объекта. Менеджер объектов Servant может поступить одним из трех способов:
найти подходящий объект Servant, который способен произвести запрашиваемую операцию;
вызвать исключение object_not_exist, которое будет возвращено клиенту;
передать запрос другому объекту.
Политики, связанные с РОА, определяют дополнительные детали. Например, в случае, если установлены политики
RequestProcessingPolicy::USE_SERVANT_MANAGER,
ServantRetentionPolicy::RETAIN,
то карта Active object Map будет обновлена и дополнена новыми соответствиями между объектом servant и идентификатором объекта.
Неявная активация объектов■
Неявная активация может иметь место как результат некоторых действий, но только в том случае, если РОА был создан с указанием
ImplicitActivationPolicy::IMPLICIT_ACTIVATION, IdAssignmentPolicy:: SYSTEM_ID и ServantRetentionPolicy::RETAIN.
Неявная активация может быть осуществлена с применением:
функции-члена РОА: :servant_to_reference;
функции-члена РОА: :servant_to_id;
функции Servant _this().
Если задано значение ObjectidUniquenessPoiicy: :unique_id, то неявная активация может произойти при использовании любого из трех перечисленных методов. Если задано значение ObjectidUniquenessPoiicy::MULTIPLE_ID, то И servant_to_reference, И servant_to_id приводят К неявной активации, пусть даже при этом объект servant является активным.
Активация с использованием объекта Servant по умолчанию
Для того чтобы использовать один и тот же объект servant вне зависимости от того, какой идентификатор объекта, нужно задать:
Requestprocessing::USE_DEFAULT_SERVANT;
Это полезно в тех случаях, когда с каждым объектом связано небольшое количество данных.
: Пример активации всех объектов при помощи одного и того же Servant
int main(int argc, char* const* argv) { try {
// Инициализация брокера -
CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);
Portableserver::Current_var cur =
Portableserver: .'Current: :_instance() ;
DataStore::_create() ;.
// Ссылка на базовый адаптер
CORBA::Object_var obj = оrb->resolve_initial_references("RootPOA");
Portableserver::POA_var rootPOA =
Portableserver::POA::_narrow(obj);
CORBA::PolicyList policies;
policies.length(3);
// Задание политик для персистентного адаптера
policies[(CORBA::ULong)0] =
rootPOA->create_lifespan_j3olicy(Portableserver::PERSISTENT);
policies[(CORBA::ULong)1] =
rootPOA->
create_request_jorocessing_policy(Portableserver::USE_DEFAULT_SERVANT);
policies[(CORBA::ULong)2] =
rootPOA->
create_id_uniqueness_joolicy(Portableserver::MULTIPLE_ID);
// Создание нового адаптера по указанным политикам
PortableServer::POAManager_var rootManager = rootPOA->
the_POAManager();
Portableserver::POA_var myPOA = rootPOA->create_POA("bank_default_servant_poa", rootManager, policies);
// Задание Servant по умолчанию
AccountManagerlmpl * managerservant = new AccountManagerlmpl(cur); myPOA->set_servant(managerservant);
// Активизация менеджера адаптера rootManager->activate();
Portableserver::ObjectId_var an_oid =
PortableServer::string_to_Object!d("CheckingAccountManager");
CORBA::Object_var cref = myPOA->
create_reference_with_id(an_oid.in(), "IDL:Bank/AccountManager:1.0");
an_oid =
PortableServer::string_to_Object!d("SavingsAccountManager");
CORBA::Object_var sref = myPOA->
create_reference_with_id(an_oid.in(), "IDL:Bank/AccountManager:1.0");
// Ссылка
CORBA::String_var string_ref = orb->object_to_string(cref.in()); ofstream crefFile("cref.dat");
crefFile « string_ref « endl;
crefFile.close();
// Ссылка для записи
string_ref = orb->object_to_string(sref.in()) ;
ofstream srefFileCsref.dat");
srefFile « string_ref « endl;
srefFile.close();
cout « "Bank Manager is ready" « endl;
// Ожидание входящих запросов
orb->run();
DataStore::_destroy();
}
catch(const CORBA::Exceptions e) ( cerr « e « endl;
}
return 1;
Деактивация объектов
РОА имеет возможность удалить объект servant из карты активных объектов. Это может произойти, например, при сборке мусора. Как только servant удален, он становится деактивированным. Деактивировать объект servant можно с использованием метода deactivate_object о. Если объект деактивирован, то это вовсе не обозначает, что он навсегда потерян. В дальнейшем он может быть активирован вновь.
Пример деактивации объекта
Kil. ............. «к.... «.Hl. ..••’.* ««>>...H.l.ltl.lLH. .<»«•.!.....................,., I m.,.,.l|l..,,lUul.n..,..lU..,....,.,..,....Ul4U.<...i
class DeActivatorThread: public VISThread {
private :
Portableserver::ObjectId _oid;
Portableserver::POA_ptr _poa;
public :.
virtual -DeActivatorThread(){}'
// Конструктор
DeActivatorThread(const Portableserver::Objectld& oid, Portableserver::POA_ptr poa): _oid(oid), _poa(poa) { // Начать поток run();
}
// Имплементация begin()
void begin() {
// Ждем 15 сек.
VISPortable::vsleep(15);
CORBA::String_var s = Portableserver::0bjectld_to_string (_oid) ;
// Деактивируем объект
cout « "\nDeActivating the object with ID =" « s « endl;
if (_poa)
_poa->deactivate_object(_oid);
}
};.
// Активатор Servant
class AccountManagerActivator : public Portableserver::Servantctivator { public:
virtual Portableserver::Servant incarnate
(const Portableserver::0bjectld& oid,
Portableserver::POA_ptr poa) {
CORBA::String_var s = Portableserver::Objectld_to_string (oid);
cout « "\nAccountManagerActivator.incarnate called with
ID = " « s << endl;
Portableserver::Servant servant;
if (VISPortable::vstricmp((char *)s, "SavingsAccountManager") == 0) // Создаем Servant для SavingsAccountManager
servant = new SavingsAccountManagerImpl;
else if (VISPortable::vstricmp((char *)s, "CheckingAccountManager") == 0) // Создаем Servant для CheckingAccountManager servant = new CheckingAccountManagerImpl; else
throw CORBA::OBJECT_NOT_EXIST();
// Создаем поток деактиватора new DeActivatorThread(oid, poa) ; // Возвращаем Servant return servant;
)
virtual void etherealize (const Portableserver::ObjectId& oid, Portableserver::POA_ptr adapter, Portableserver::Servant servant, CORBA::Boolean cleanup_in_jDrogress, CORBA::Boolean remaining_activations) (
CORBA::String_var s = Portableserver::Objectld_to_string (oid);
cout « "XnAccountManagerActivator.etherealize called with
ID = " « s « endl;
if (!remaining_activations) delete servant;
Использование объектов Servant и менеджеров объектов Servant
Менеджеры объектов Servant производят два типа действий: находят и возвращают объекты servant, деактивируют объекты servant. С их помощью РОА имеет возможность активировать объекты при получении запросов к неактивным объектам. Менеджеры объектов Servant могут и отсутствовать, в частности, они не нужны, если сервер загружает все объекты во время своего старта. Менеджеры также могут сообщать клиентам о том, чтобы
они перенаправили запросы к другим объектам, используя для этого метод ForwardRequest.
Объект servant представляет собой активную сущность, имплементацию определенных функций объектов. РОА в свою очередь поддерживает карту активных servant и устанавливает соответствие между ними и идентификаторами объектов. При получении клиентского запроса РОА первым делом проверяет эту карту и смотрит, присутствует ли в ней идентификатор объекта, содержащийся в клиентском запросе. Если такой идентификатор найден в карте идентификаторов объектов, то РОА пересылает запрос объекту Servant. Если же идентификатор объекта в карте отсутствует, то менеджер объектов Servant определяет, где находится подходящий servant и активирует его. То, что мы здесь описали, — это всего лишь пример сценария, реально могут происходить и другие действия. Все будет зависеть от того, какие мы установим политики для данного РОА (рис. 9.9).
СерверСерверШаг 1Клиентский запрос объекту, которого нет в карте идентификаторов объектовШаг 1Клиентский запрос объекту, которого нет в карте идентификаторов объектовServantManagerServantManagerServantServantБазовый rootPOAБазовый rootPOAObjectID ObjectID ObjectIDObjectID ObjectID ObjectIDМенеджер servantМенеджер servantКарта FctriveObjectMapКарта FctriveObjectMapШагЗМенеджер servant создает подходящий servant и возвращает его РОА.Обработка запроса завершенаШагЗМенеджер servant создает подходящий servant и возвращает его РОА.Обработка запроса завершенаШаг 2РОА запрашивает менеджер servant о поиске подходящего servantШаг 2РОА запрашивает менеджер servant о поиске подходящего servant
Сервер
Сервер
Шаг 1
Клиентский запрос объекту, которого нет в карте идентификаторов объектов
Шаг 1
Клиентский запрос объекту, которого нет в карте идентификаторов объектов
ServantManager
ServantManager
Servant
Servant
Базовый rootPOA
Базовый rootPOA
ObjectID ObjectID ObjectID
ObjectID ObjectID ObjectID
Менеджер servant
Менеджер servant
Карта FctriveObjectMap
Карта FctriveObjectMap
ШагЗ
Менеджер servant создает подходящий servant и возвращает его РОА.
Обработка запроса завершена
ШагЗ
Менеджер servant создает подходящий servant и возвращает его РОА.
Обработка запроса завершена
Шаг 2
РОА запрашивает менеджер servant о поиске подходящего servant
Шаг 2
РОА запрашивает менеджер servant о поиске подходящего servant
Рис. 9.9. Сценарий обработки запроса
Существует два типа менеджеров объектов Servant: активатор объектов Servant (ServantActivator) И локатор объектов Servant (ServantLocator). Многое зависит от того, какие установлены политики. Но, как правило, активатор servant служит для того, чтобы активировать персистентные объекты, а локатор объектов servant используется для активации локальных объектов.
Необходимо задать политику RequestProcessingPolicy::USE_SERVANT_ manager, а также тип политики, который определяет тип менеджера объектов
Servant В ВИДС ServantRetentionPolicy::RETAIN ДЛЯ активатора Servantctivator ИЛИ ServantRetentionPolicy::NON_RETAIN ДЛЯ ЛОКЭТОра ServantLocator. После этого можно использовать менеджер servant.
Активаторы объектов Servant
Активаторы объектов servant могут быть использованы тогда, когда установлены следующие значения политик: ServantRetentionPolicy: .-RETAIN И RequestProcessingPolicy::USE_SERVANT_MANAGER. Объекты Servant, ЗКТИ- вируемые таким типом менеджеров, вписываются в карту активных объектов Active Object Map.
При обработке запросов с использованием активаторов Servant происходят такие события:
Получен клиентский запрос (клиентский запрос содержит имя РОА, идентификатор объекта id и несколько других параметров).
РОА производит проверку карты активных объектов. Если идентификатор, соответствующий идентификатору объекта, полученному в клиентском запросе, присутствует в карте активных объектов, то работа передается объекту Servant, клиент получает ответ.
Если идентификатор объекта не найден в карте активных объектов, то РОА вызывает метод incarnate в менеджере Servant, incarnate содержит в качестве параметров идентификатор объекта и РОА, в котором объект активируется, incarnate "воплощает", т. е. создает объект.
Менеджер объектов servant находит подходящий объект Servant.
Идентификатор объекта servant заносится в карту активных объектов, клиент получает ответ.
Методы ethereaiize и incarnate создаются пользователем.
В дальнейшем объект servant может быть деактивирован. Это может быть сделано различными способами, например, с использованием метода deactivate_object.
= Пример с менеджером-активатором Servant
int main(int argc, char* const* argv) { try {
// Инициализируем брокер
COREA::ORB_ptr orb = COREA::ORB_init(argc, argv);
DataStore::_create();
// Ссылка на базовай адаптер РОА
COREA::0bject_var obj = orb->resolve_initial_references("RootPOA");
Portableserver::POA_var rootPOA = Portableserver::РОА::_narrow(obj); CORBA::PolicyList policies;
policies.length(2);
policies[(CORBA::ULong)0] =
rootPOA->create_lifespan_policy(Portableserver::PERSISTENT);
policies[(CORBA::ULong)1] =
rootPOA->create_request_processing_policy( Portableserver::USE_SERVANT_MANAGER);
// Создать новый адаптер с заданными политиками
Portableserver::POAManager_var rootManager = rootPOA-> the_POAManager() ;.
Portableserver::P0A_var myPOA =
rootPOA->create_POA("bank_servant_activator_poa", rootManager, policies);
// Создать активатор Servant
AccountManagerActivator servant_activator_impl;
// Задать активатор Servant
myPOA->set_servant_manager(&servant_activator_impl);
Portableserver::ObjectId_var an_oid =
Portableserver::string_to_Object!d("CheckingAccountManager");
CORBA::Object_var cref = myPOA->
create_reference_with_id(an_oid.in(),"IDL:Bank/AccountManager:1.0") ;
an_oid =
Portableserver::string_to_ObjectId("SavingsAccountManager");
CORBA::0bject_var sref = myP0A->
create_reference_with_id(an_oid.in(),"IDL:Bank/AccountManager:1.0");
// Активизировать менеджер адаптера rootManager->activate();
// Ссылка на чековый счет
CORBA::String_var string_ref = orb->object_to_string(cref.in());
ofstream crefFileCcref.dat");
crefFile « string_ref « endl;
crefFile.close();
// Ссылка на сберегательный счет
string_ref = orb->object_to_string(sref.in());
ofstream srefFileCsref.dat");
srefFile « string_ref « endl;
srefFile.close();
// Ждем входящих запросов
cout « " BankManager Server is ready" « endl;
orb->run();
DataStore::_destroy();
)
catch(const CORBA::Exception& e) ( cerr « e « endl;
)
return 1;.
}
Ниже приведен менеджер объектов Servant для этого случая.
// Активатор Servant
class AccountManagerActivator : public Portableserver::Servantctivator ( public:
virtual Portableserver::Servant incarnate (const Portableserver::Objectld& oid, Portableserver::POA_ptr poa) {
CORBA::String_var s = Portableserver::0bjectld_to_string (oid);
cout « "XnAccountManagerActivator.incarnate called with ID = " « s « endl;
Portableserver::Servant servant;
if (VISPortable::vstricmp((char *)s, "SavingsAccountManager") == 0) // Создаем Servant для SavingsAccountManager
servant = new SavingsAccountManagerIm.pl;
else if (VISPortable::vstricmp((char *)s, "CheckingAccountManager") = 0)
// Создаем Servant для Create CheckingAccountManager
servant = new CheckingAccountManagerIm.pl; else
throw CORBA::OBJECT_NOT_EXIST();
// Поток деактиватора
new DeActivatorThread(oid, poa);
// Возвращаем Servant '
return servant;■
) virtual void etherealize (const Portableserver::ObjectId& oid,
Portableserver::POA_ptr adapter.
Portableserver::Servant servant,
CORBA::Boolean cleanup_in_progress,
CORBA::Boolean remaining_activations) {
CORBA::String_var s = Portableserver::ObjectId_to_string (old); cout « "\nAccountManagerActivator.etherealize called with
ID = " « s « endl;
if (!remaining_activations) delete servant;
} );
Локатор объектов Servant
Порой активная карта идентификаторов объектов РОА может слишком сильно разрастаться, занимая много памяти. Чтобы сэкономить память, можно создать РОА с такими значениями политик:
RequestProcessingPolicy::USE_SERVANT_MANAGER
И ServantRetentionPolicy: :NON_RETAIN. ЭТО обозначает, ЧТО СВЯЗИ Между servant и объектами не будут храниться в карте идентификаторов активных объектов. Поскольку соответствия между объектами и Servant не сохранены, то локатор ServantLocator будет вызываться при каждом клиентском запросе.
При использовании менеджера объектов servant в виде локатора объектов servant происходит следующая последовательность действий:
Получен клиентский запрос, содержащий имя РОА и идентификатор объекта.
Поскольку установлена политика ServantRetentionPolicy::NON_RETAIN, то РОА не производит поиск в карте активных объектов.
РОА вызывает метод preinvoke в менеджере объектов Servant, который получает идентификатор объекта id, РОА.
Локатор объектов servant находит подходящий объект servant.
Объект Servant выполняет действия, клиенту направляется ответ.
РОА вызывает метод postinvoke в менеджере объектов servant.
. Пример с локатором объектов servant,
int main(int argc, char* const* argv) { try {
// Инициализируем брокер
CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv); // Данные DataStore::_create();■
// Ссылка на базовый адаптер РОА CORBA::0bject_var obj = orb->resolve_initial_references("RootPOA"); Portableserver::P0A_var rootPOA = Portableserver::P0A::_narrow(obj); CORBA::PolicyList policies; policies.length(3) ;
policies[(CORBA::ULong)0] = rootPOA->create_lifespan_policy(Portableserver::PERSISTENT);
policies[(CORBA::ULong)1] = rootPOA-> create_servant_retention_policy(Portableserver::NON_RETAIN); policies[(CORBA::ULong)2] =
rootPOA-> create_request_processing_policy(Portableserver::USE_ SERVANT_MANAGER);'
Portableserver::POAManager_var rootManager = rootPOA-> the_POAManager();
Portableserver::P0A_var myPOA = rootPOA->create_POA("bank_servant_locator_poa", rootManager, policies); // Создаем локатор Servant AccountManagerLocator servant_locator_impl; myPOA->set_servant_manager(&servant_locator_impl); // Ссылки на сберегательный и чековый счета Portableserver::Objectld_var an_oid = Portableserver::string_to_0bjectld("CheckingAccountManager");
CORBA::0bject_var cref = myPOA-> create_reference_with_id(an_oid.in(), "IDL:Bank/AccountManager:1.0") ;
an_oid = Portableserver::string_to_ObjectId("SavingsAccountManager"); CORBA::0bject_var sref = myPOA-> create_reference_with_id(an_oid.in(), "IDL:Bank/AccountManager:1.0") ;
// Активизировать менеджер адаптера rootManager->activate();
// Ссылка на чековый счет
CORBA::String_var string_ref = orb->object_to_string(cref.in()); ofstream crefFile("cref.dat") ;
crefFile « string_ref « endl; crefFile.close() ;
// Ссылка на сберегательный счет
string_ref = orb->object_to_string(sref.in());
ofstream srefFile("sref.dat");
srefFile « string_ref « endl;
srefFile.close();
// Ожидание запросов
cout « "Bank Manager is ready" « endl; orb->run();
// Данные уничтожить DataStore::_destroy();
}
catch(const CORBA:Exceptions e) { cerr « e « endl;
}
return 1;
}
Менеджер объектов servant для этого примера выглядит так:
// Локатор Servant
class AccountManagerLocator : public Portableserver::ServantLocator { public:
AccountManagerLocator ()(}
virtual Portableserver::Servant preinvoke (const Portableserver::0bjectlds oid, Portableserver::POA_ptr adapter, const char* operation,■
Portableserver::ServantLocator::Cookies the_cookie) { CORBA::String_var s = Portableserver::Objectld_to_string (oid); cout « "\nAccountManagerLocator.preinvoke called with ID = " « s « endl;
Portableserver::Servant servant;
if (VISPortable::vstricmp((char *)s, "SavingsAccountManager") == 0) // Servant для SavingsAccountManager
servant = new SavingsAccountManagerImpl;
else if (VISPortable::vstricmp((char *)s, "CheckingAccountManager") == 0)
// Servant для CheckingAccountManager servant = new CheckingAccountManagerlmpl; else
throw CORBA: :OBJECT_NOT_EXIST() ;
return servant;
virtual void postinvoke (const Portableserver::0bjectld& old, Portableserver::POA_ptr adapter, const char* operation,
Portableserver::ServantLocator::Cookie the_cookie,
Portableserver::Servant the_servant) (
CORBA::String_var s = Portableserver::Objectld_to_string (oid) ;
cout « "XnAccountManagerLocator.postinvoke called with
ID = " « s « endl;
delete the_servant;
} };
Управление РОА с помощью менеджера РОА
Менеджер адаптера РОА управляет состоянием РОА (получает от РОА запросы для обработки или отклоняет их) и может его деактивировать. Каждый РОА связан с объектом менеджера РОА. Менеджер может управлять одним или несколькими РОА. Он связывается с адаптером РОА в момент создания РОА, при этом можно указать, какой будет использоваться менеджер для управления данным РОА, или же указать значение null (при этом будет создан новый менеджер для вновь создаваемого РОА).
i Пример создания имени для РОА и менеджера РОА■
Portableserver::POAManager_var rootManager = rootPOA->the_POAManager();
Portableserver::P0A_var myPOA =
rootPOA->create_POA("bank_servant_locator_poa", rootManager, policies);
Portableserver::P0A_var myPOA =
rootPOA->create_POA("bank_servant_locator_jpoa", null, policies);
Следует помнить о том, чтобы все входящие параметры были предварительно определены. Менеджер РОА будет удален сразу после того, как будут удалены все связанные с ним РОА.
Менеджер РОА может находиться в одном из следующих состояний:
ожидание;
активное;
отклонение;
неактивное..
В свою очередь, состояния менеджера определяют состояние РОА. Ниже мы подробно рассмотрим эти состояния. Чтобы получить значение текущего состояния менеджера РОА, используется следующая конструкция:
enum State(HOLDING, ACTIVE, DISCARDING, INACTIVE};
State get_state();
Состояние ожидания
По умолчанию, после создания менеджер РОА находится в состоянии ожидания. При этом все входящие запросы направляются в очередь. Даже те запросы, которые требуют обращения к активатору адаптера, идут в очередь, если менеджер находится в состоянии ожидания. Чтобы изменить состояние менеджера РОА, используем такую конструкцию:
void hold_requests(wait_for_completion)
raises (Adapterinactive);
Параметр wait_for_completion имеет логическое значение. Если его значение false, то действие возвращается сразу же после изменения статуса на ожидание. Если его значение true, то действие возвращается только после того, как все запросы, начатые до изменения статуса или до изменения менеджера РОА, будут выполнены. Если до вызова данной операции менеджер РОА находился в неактивном состоянии, то будет вызвано исключение Adapterinactive. Менеджер РОА, находящийся в неактивном состоянии, не может быть переведен в состояние ожидания. Все запросы, поставленные в очередь, обработка которых не была начата, останутся в очереди.
Активное состояние
Когда менеджер РОА находится в активном состоянии, связанные с ним РОА осуществляют обработку запросов. Чтобы перевести менеджер РОА в активное состояние, запишем:
void activate()
raises (Adapterinactive);
Исключение Adapterinactive возникает в том случае, если менеджер находился в неактивном состоянии. Неактивный менеджер нельзя перевести в активное состояние.
Состояние отклонения запросов
Когда менеджер РОА находится в состоянии отклонения запросов, то связанные с ним РОА отклоняют все запросы (если запросы не начали выполняться до того, как менеджер вошел в состояние отклонения). Более того, активаторы адаптера также не будут вызываться. Такое состояние оказывается полезным в тех случаях, когда РОА получает избыточно большое количество запросов. Необходимо уведомить клиента о том, что его запрос был
отклонен, чтобы клиент мог повторить запрос. Не существует специально разработанного механизма определения того, получает ли РОА избыточно большое количество запросов. Программист сам должен создать механизм мониторинга, если это необходимо.
Чтобы перевести менеджера в состояние отклонения запросов, используем: void discard_requests(wait_for_completion)
raises (Adapterinactive);
Значение wait_for_completion имеет логический тип. Если менеджер находится в неактивном состоянии, то он не может быть переведен в состояние отклонения запросов.
Неактивное состояние
Если менеджер находится в неактивном состоянии, то связанные с ним РОА игнорируют входящие запросы. Менеджеры РОА, находящиеся в неактивном состоянии, не могут быть переведены ни в какое другое состояние. Чтобы перевести менеджер в неактивное состояние, пишем: void deactivate(etherealize_objects, wait_for_completion)
raises (Adapterinactive);
После того как состояние менеджера было изменено и если etherealize_objects равно true, то все связанные с данным менеджером адаптеры РОА, В которых установлены ПОЛИТИКИ ServantRetentionPolicy: :RETAIN И RequestProcessingPolicy::USE_SERVANT_MANAGER, ВЫЗОВУТ метод etherealize ДЛЯ всех активных объектов. Если etherealize_objects равно false, то метод etherealize не будет вызван.
Свойства приема и перенаправления
Это свойства, специфичные для Visibroker (свойства ServerEnginePolicy), в их число входят:
имя хоста;■
имя прокси-хоста;
менеджер серверных соединений или список таких менеджеров.
Иллюстрация показывает, как все это связано друг с другом в реализации Visibroker (рис. 9.10).
Самый простой случай — когда каждый РОА имеет свой собственный единственный серверный движок-engine. При этом запросы к разным РОА приходят на разные порты. Кроме того, РОА может иметь несколько серверных движков. При этом отдельный РОА поддерживает прием запросов с нескольких портов.
Р0А1Р0А2РОАЗР0А1Р0А2РОАЗServerEngine3ServerEngine4ServerEngine3ServerEngine4ServerEnginelServerEnginelServerEngine2ServerEngine2ServerConnectionManager2ServerConnectionManager2ServerConnectionManager3ServerConnectionManager3ServerConnectionManager4ServerConnectionManager4ServerConnectionManagerlServerConnectionManagerlServerconnection ManagersServerconnection Managers
Р0А1
Р0А2
РОАЗ
Р0А1
Р0А2
РОАЗ
ServerEngine3
ServerEngine4
ServerEngine3
ServerEngine4
ServerEnginel
ServerEnginel
ServerEngine2
ServerEngine2
ServerConnectionManager2
ServerConnectionManager2
ServerConnectionManager3
ServerConnectionManager3
ServerConnectionManager4
ServerConnectionManager4
ServerConnectionManagerl
ServerConnectionManagerl
Serverconnection Managers
Serverconnection Managers
Рис. 9.10. Специфические свойства для Visibroker
Разные РОА могут использовать один и тот же движок. Если такое происходит, то разные РОА прослушивают один и тот же порт. Но запросы будут обработаны корректно, поскольку в них содержатся имена РОА. Такая ситуация может возникнуть, например, тогда, когда мы используем один движок по умолчанию, а создаем несколько РОА, без указания того, что для них нужно создавать новые серверные движки.
Задаем свойства серверных движков
Следующие свойства определяют то, какие движки будут использоваться как движки по умолчанию:
vbroker. se.<server_engine_name>.host
vbroker.se.<server_engine_name>.proxyHost'
vbroker.se.<server_engine_name>.sems'
Если не заданы политики для серверных движков, то РОА устанавливает имя серверных движков в виде Пор, задавая следующие величины по умолчанию:
vbroker.se.iiop_tp.host=null
vbroker.se.iiop_tp.proxyHost=null
vbroker.se.iiop_tp.scms=iiop
vbroker.se.liop_tp.host=null
vbroker.se.liop_tp.proxyHost=null
vbroker.se.liop_tp.scms=liop
Эти значения могут быть изменены. Например:
vbroker.se.default=abc, def
vbroker.se.abc.host=cob
vbroker.se.abc.proxyHost=null
vbroker.se.abc.scms=cobscml, cobscm2
vbroker.se.def.host=gob
vbroker.se.def.proxyHost=null
vbroker.se.def.scms=gobscml
Свойства менеджеров серверных соединений
Менеджер серверного соединения имеет три группы свойств, связанных с соответствующими компонентами: менеджером, прослушивателем, диспетчером.
Свойства менеджера
Можно задать, например, такие значения для менеджера:
vbroker.se.<server_engine>.scm.<server_connection_mgr>.type
Это свойство определяет тип менеджера. Допустимыми значениями являются Socket И Local;
vbroker.se.<server_engine>.scm.<server_connection_mgr>.connectionMax Это свойство задает число соединений, допустимых одновременно. По умолчанию подразумевается 0 — не ограничено;
vbroker.se.<server_engine>.scm.<server_connection_mgr>.connectionMaxIdle Устанавливает максимальное число секунд ожидания перед тем, как соединение будет разорвано, по умолчанию 0 — нет ограничений.
Свойства прослушивателя
Рассмотрим свойства прослушивателя:
vbroker.se.<server_engine>.scm.<server_connection_mgr>.listener.type Тип прослушивателя может быть либо iiop, либо Пор;
vbroker.se.<server_engine>.scm.<server_connection_mgr>.listener.port Задает порт прослушивания, который РОА связывает с данным сервером, используемым в менеджере соединения. По умолчанию принимается значение 0. Это означает, что система будет подбирать случайное значение для порта. Это значение не имеет никакого смысла, если тип прослушивателя равен iiop;
vbroker.se.<server_engine>.scm.<server_connection_mgr>.listener.proxyPort Свойство устанавливает порт для прокси-сервера. По умолчанию 0 (случайное значение, выбираемое системой). Порт не имеет смысла задавать, если тип прослушивателя — iiop.
Свойства диспетчера
Диспетчеру можно задать следующие свойства:
vbroker.se.<server_engine>.scm.<server_connection_mgr>.dispatcher.type В данном случае поддерживаются только два типа: ThreadPooi и Threadsession. Если тип менеджера — Local, то поддерживается только один ТИП ThreadPooi;
vbroker.se.<server_engine>.son. <server_connection_mgr>.dispatcher.threadMax Используется только тогда, когда тип равен ThreadPooi;
vbroker.se.<server_engine>.son. <server_connection_mgr>.dispatcher.threadMaxIdle Используется только тогда, когда тип равен ThreadPooi;
vbroker.se.<server_engine>.scm. <server_connection_mgr>.dispatcher.threadMin Используется только тогда, когда тип равен ThreadPooi.
; Пример создания РОА с указанием свойств серверного движка
AccountRegistry AccountManagerlmpl::_accounts; int main(int argc, char* const* argv)
try {
// Инициализация брокера
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv); VISPropertyManager_ptr pm = orb->getPropertyManager(); pm->addProperty("vbroker.se.mySe.host", ""); pm->addProperty("vbroker.se.mySe.proxyHost", ""); pm->addProperty("vbroker.se.mySe.sems", "scmlist"); pm->addProperty("vbroker.se.mySe.scm.scmlist.manager.type", "Socket"); pm->addProperty("vbroker.se.mySe.scm.scmlist.manager.connectionMax",■
100UL);
pm->
addProperty("vbroker.se.mySe.scm.scmlist.manager.connectionMaxIdle", 300UL);
pm->addProperty("vbroker.se.mySe.scm.scmlist.listener.type", "HOP"); pm->addProperty("vbroker.se.mySe.scm.scmlist.listener.port", 55000UL); pm->addProperty("vbroker.se.mySe.scm.scmlist.listener.proxyPort", OUL) ;
pm->addProperty("vbroker.se.mySe.scm.scmlist.dispatcher.type", "ThreadPooi");
pm->addProperty("vbroker.se.mySe.son.semi1st.dispatcher.threadMax", OOUL);
pm->addProperty("vbroker.se.mySe.scm.scmlist.dispatcher.threadMin", SUL) ;
pm->
addProperty("vbroker.se.mySe.scm.scmlist.dispatcher.threadMaxIdle", 300UL);
// Ссылка на базовый адаптер РОА
CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");
Portableserver::POA_var rootPOA = Portableserver::POA::_narrow(obj);
// Создание политик
CORBA::Any_var seAny(new CORBA::Any);
CORBA::StringSequence_var engines = new CORBA::Stringsequence(1UL);
engines->length(1UL);
engines[OUL] = CORBA::string_dup("mySe");
seAny «= engines;
CORBA::PolicyList_var policies = new CORBA::PolicyList(2UL);
policies->length(2UL);
policies[OUL] = orb->create_policy( PortableServerExt::SERVER_ENGINE_POLICY_TYPE, seAny);
policies[1U1] = rootPOA->
create_lifespan_policy(Portableserver::PERSISTENT) ;
// Создание адаптера с указанными политиками
Portableserver::POAManager_var manager = rootPOA->the_POAManager();
Portableserver::POA_var myPOA = rootPOA->create_POA( "bank_se_policy_poa", manager, policies);
// Создание Servant .
AccountManagerlmpl* managerservant = new AccountManagerlmpl();
// Активизация Servant
Portableserver::Objectld_var oid =
Portableserver::string_to_ObjectId("BankManager");
myPOA->activate_object_with_id(oid,managerservant);
// Получение ссылки
CORBA::0bject_var ref = myPOA->servant_to_reference(managerservant);
CORBA::String_var string_ref = orb->object_to_string(ref.in());
ofstream refFile("ref.dat");
refFile « string_ref « endl;
refFile.close();'
// Активизировать менеджер адаптера manager->activate();
// Ожидание входящих запросов
cout « "AccountManager Server ready" « endl;
orb->run();
}
catch(const CORBA::Exceptions e) { cerr « e « endl;
return (1) ;
}
return (0);
}
Обработка запросов
Запросы содержат идентификатор объекта id и РОА. Когда клиент посылает запрос, ORB первым делом определяет сервер, которому направляется запрос. В случае необходимости он стартует этот сервер. Затем находится соответствующий адаптер РОА внутри этого сервера.
После того как необходимый РОА обнаружен, запрос направляется этому РОА. То, как будет обработан запрос, зависит от установленных на этом РОА политик, а также от состояния объекта.
Если задана политика ServantRetentionPolicy: :Retain, то РОА просматривает карту активных объектов Active Object Мар для того, чтобы найти объект Servant с заданным идентификатором id. Если объект Servant найден, то РОА вызывает соответствующий метод Servant.
Если задано ServantRetentionPolicy::NON_RETAIN ИЛИ ServantRetentionPolicy::Retain, но не найден необходимый объект Servant, то могут произойти такие действия:
если задано RequestProcessingPolicy::USE_DEFAULT_SERVANT, ТО РОА вызывает соответствующий метод Servant по умолчанию;
если задано RequestProcessingPolicy::USE_SERVANT_MANAGER, ТО РОА вызывает метод incarnate или preinvoke в менеджере объектов Servant;
если задано RequestProcessingPolicy::USE_OBJECT_MAP_ONLY, ТО возникает исключение.
Если вызван менеджер объектов servant, но объект не может быть воплощен с использованием incarnate, то может быть вызвано исключение ForwardRequest.
Язык IDL
Немного отвлечемся от рассмотрения внутреннего устройства CORBA-приложений, познакомимся несколько более подробно с языком IDL, языком описания интерфейса. Нас больше будут интересовать принципы работы, нежели формальная сторона построения языка.
Мы используем язык IDL для того, чтобы создать описание интерфейсов в файле idl, который затем компилируется с использованием компилятора idl2.cpp.
При создании IDL-файлов нам может оказать услугу редактор SlickEdit. IDL-файлы представлены в нем в весьма удобном виде (рис. 9.11).
'' Bank.idl
В ■ Bank
Ер ■ AccountЕ
I- f.balanceQ
В lAccountManager Е
|openQ
0 readme.txt
Рис. 9.11. IDL-файл в редакторе SlickEdit
i Пример описания интерфейса
• j
// Описание IDL
interface example {
long opl(in char x, out short y);
1;■
Что получается после компиляции
После компиляции мы имеем два клиентских файла example_c.hh и example_c.cc. В этих файлах содержится класс example, используемый клиентом. Не следует изменять содержимое файлов, полученных в результате работы компилятора idl2.cpp!
Файл example_c.hh
#ifndef example_idlclient
#define _example_idlclient
#include "vpre.h"
{ -'^nNt^STduiBxe) uдnqэд ) Отти"" *эрЗшвхэ DaqBqs ,'jqd" sjqd-aydurexa : aqBAT jd } qno~э"[dшвxэ ssbto
.' (5Два~aydurexa qsuoa 'sшвэдqso) »дoqвдэdo ?uIвэдqso риэтд^ 1 (9двл~ э"[dшвxэ '?uIBэдqsI) «дoqвдэdo sшвэдqsI риэтд} ^(5двл^a7dшвxa '^uiBajqsTgiA) <<дс^вдайо ?uIBЭдqsтsIл pueTjj
1 (?iB/daydurexa qsuoa '?uIвэдqsosIЛ) »дoqвдэdo sшвэдqsosIл pueTjj .'()uqэд— jqd- aydurexa .' () qno ?jqd—aydurexa
{ .^qd- идг^эд } Отпоит 9jqd~aydurexa { ?jqd- uдnqэд } qsuoa ()ит jqd~aydurexa { .'jqd~ uдnqэд } qsuoa ()<-дoqвдэdo ^a^durexa { .'jqd~ uдnqэд } qsuoa O^a^durexa дoqвдэdo .' (j^d-э"[dшвxэ) =joq.BJado ?двл—a^dmaxa 1(двл~ ?двл—a^durexa ^suoa)=jO4Bjado sjba-a^dmaxa (Jdd~aTdurexa) эевэ^эд ртол DTq.Bq.s .'(j^d-a"[durexa) aq.BaT"[dnp"~ j^d-aydurexa aTq.Bq.s .' () двл~aTduiBxa~ ^вп^дтл .'(? двл—aydurexa ^suoa) два-aydurexa .' (д4сГa^durexa) два-aydurexa .' () два-aydurexa
:aT"[qnd .'дЧ-сГ- j^d”a"[durexa :эq.влтдd .'4no~aydurexa ssb^o риэтд^ ) два-::удноэ ofTqnd : два-aydurexa ssbto ,'q.no- aydurexa ssbto (J^d-aydurexa q.suoa '?швэд45О51Л) »дoq.вдэdo ^швад^еодтл
1 (si^d-a^duiBxa '?швэд45Т51Л) «ДO4BДэdo ?швэд45Д31Л .'jeHS^diKBxa д^<5~BTdmBxa japedAq. .^qd—a"[durexa ^a^durexa japedAq .'э"[dшвxэ ssbto ~двл—a^durexa аитдар# —два э"[dшвxэ japuqa# qapua# „Ч’УЯНОЭ,, эрптэит # ^Ч^УШОЭ- japujT#
void operator=(const example_outs);
void operator”(const example_vars);
public:
example_out(const example_outs _o) : _ptr(_o._ptr) {} example_out(example_ptrs _p) : _ptr(_p) { _ptr = _nil();
}
examp le_out(example_vars _v) : _ptr(_v._ptr) {
_v = _nil();
} example_outs operator”(example* _p) { _ptr = _p;
return *this;
}
operator example_ptrs() { return _ptr; } example_ptrs ptr() { return _ptr; } example* operator->() { return _ptr; }
};
#endif
class example : public virtual CORBA_Object { private:
static const CORBA::Typeinfo _class_info;
void operator”(const examples) {} protected: example() {} example(const examples) {}
public:
virtual ~example() {}
static const CORBA::TypeInfо *_desc();
virtual const CORBA::Typeinfo *_type_info() const;
virtual void *_safe_narrow(const CORBA::TypeInfoS) const; static CORBA::Object*_factory();
example_ptr _this();
static example_ptr _duplicate(example_ptr _obj) {
if (_obj) _obj->_ref();
return _obj;
}
static ex.ample_ptr _nil() { return (example_ptr) NULL; } static example_ptr _narrow(CORBA::Object* _obj);
static example_ptr _clone(example_ptr _obj) {
CORBA::Object_var _obj_var(CORBA_Object::_clone(_obj));
#if defined(_HPCC_BUG)
return _narrow(_obj_var.operator CORBA::Object_ptr());
#else
return _narrow(_obj_var);
#endif
}
static example_ptr _bind(const char *_object_name = (const char*)NULL, const char *_host_name = (const char*)NULL, const CORBA::BindOptions* _opt = (CORBA::BindOptions*)NULL, CORBA::ORB_ptr _orb = (CORBA::ORB_ptr)NULL);
static example_ptr _bind(const char *_poa_name, const CORBA::OctetSequence& _id, const char *_host_name = (const char*)NULL, const CORBA::BindOptions* _opt = (CORBA::BindOptions*)NULL, CORBA::ORB_ptr _orb = (CORBA::ORB_ptr)NULL);
virtual CORBA::Long opl(CORBA::Char _x, CORBA::Short_out _y) ;
friend VISostream& operator«(VISostream& _strm, const example_ptr _ob j) ;
. friend VISistream& operator»(VlSistream& _strm, example_ptr& _obj); friend Ostreams operator«(Ostreams _strm, const example_ptr _obj); friend Istream& operator» (Istream& _strm, example_ptr& _obj);
};
class example_ops;
typedef example_ops* example_ops_ptr;
class example_ops {
public:
example_ops() {}
virtual ~example_ops () {}
virtual CORBA::Long opl(CORBA::Char _x, CORBA::Short_out _y) = 0;
static const VISOps_Info *_desc();
static example_ops_ptr _nil() { return (example_ops_ptr)NULL; } static example_ops_ptr _downcast(Portableserver::ServantBase* _servant) ;
protected:
static const VISOps_Info _ops_info;
};
^include "vpost.h"
Dendif
Файлы, содежащие классы Stub-клиентов, сгенерированные компилятором
Компилятор генерирует метод opl. Этот метод представляет собой класс stub, поскольку вызывается клиентской программой, формирует сообщение запроса, посылает это сообщение имплементации объекта, ожидает ответа, раскодирует полученный ответ, возвращает результат программе. Так как класс example унаследован от класса corba: :object, то в этом классе можно использовать несколько методов класса объектов corba.
Задание типа указателя
Компилятор IDL всегда использует задание типа указателя. Пример кода рассмотрен ниже:
typedef example *example_ptr;
Автоматическое управление памятью.
Класс cinterface name>_var
IDL-компилятор также создает класс с именем examplе vai?, который можНО использовать вместо example_ptr. Класс example_var автоматически управляет памятью, когда объект exampie_var уничтожается. При этом объект, связанный с exampie_ptr, высвобождается. Если объект exampie_var примет новое значение, то старая ссылка exampie_ptr также высвобождается.
[ Пример с классом example_var в файле example_c.hh
class example_var : public CORBA::_var {'
public:
static example_ptr —duplicate(example_ptr);
static void _release(example_ptr);
example_var();
example_var(example_ptr);
example_var(const example_var &);
~example_var();
example_var& operator=(example_ptr);
example_var& operator=(const example_var& _var) (/*...*/} operator example* () const ( return _ptr; }
Табл. 9.2 содержит описание методов в классе _var.
Таблица 9.2. Методы в классе _va г
Метод
Описание
example_var()
Конструктор, инициализирующий указатель _ptr значением null
example_var(const example_
Конструктор, который создает копию объек-
vars var)
та, передаваемого в качестве параметра var, и направляет указатель _ptr
-example ()
Деструктор, вызывающий метод _release () для объекта, на который указывает _ptr
operator=(example_ptr p)
Оператор присваивания, вызывающий метод _release() для объекта, на который указывает _ptr, затем сохраняющий значение рв_ptr
operator=(const example_ptr p)
Оператор присваивания, вызывающий метод _release() для объекта, на который указывает _ptr, затем сохраняющий в _ptr копию р, возвращаемую методом -duplicate()
example_ptr operator->()
Возвращает указатель _ptr объекта. Оператор не следует использовать до того, как объект будет инициализирован
Компилятор IDL генерирует два серверных файла: example_s.hh и example_s.cc. Эти файлы описывают класс POA_exampie, который затем имплементируется. Класс POA_exampie создается на основе класса PortabieSeryer_servantBase. Еще раз отметим, что не следует изменять содержимое файлов, сгенерированных компилятором id!2cpp.
|;Код, содержащийся в файле example_s.hh|
♦ifndef example_idlserver
♦define example_idlserver
♦include "vpre.h"
♦include "example_c.hh"
class POA_example : public example_ops,public virtual
PortableServer_ServantBase {
protected:
POA_example() {}
virtual ~РОА_example() {} public:
static const CORBA::Typeinfo _skel_info;
virtual const CORBA::Typeinfo *_type_info() const;
example_ptr _this();
virtual void *_safe_narrow(const CORBA::TypeInfo&) const; static POA_example * _narrow(PortableServer_ServantBase *_obj);
// Пока не имплементирован метод opl
virtual CORBA::Long opl(CORBA::Char _x, CORBA::Short_out _y) = 0;
// Скелетон имплементируется автоматически
virtual void* _safe_downcast—ops(const VISOps_Infos _info) { if (_info == *example_ops::_desc())
return (void*)(example_ops*)this; return (void*)NULL;
}
static void _opl(void *_obj, CORBA::MarshalInBuffer &_istrm, const char *_oper, VISReplyHandler& handler); };
template <class T> class POA_example_tie : public POA_example { private:
CORBA::Boolean _rel;
Portableserver::POA_ptr _poa;
T *_ptr;
POA_example_tie(const POA_example_ties) {} void operator=(const POA_example_ties) {} public:
POA_example_tie (T& t): _ptr(&t), _poa(NULL), _rel((CORBA::Boolean)0) (}
POA_example_tie (T& t, Portableserver::POA_ptr poa): _ptr(&t), _poa(PortableServer_POA::—duplicate(poa)) , _rel((CORBA::Boolean)0) (}
POA_example_tie (T *p, CORBA::Boolean release= 1) : _ptr(p), _poa(NULL), _rel(release) {}
POA_example_tie (T *p, Portableserver::POA_ptr poa, CORBA::Boolean release =1)
: _ptr(p), _poa(PortableServer_POA::—duplicate(poa)), _rel(release) (} virtual ~POA_example—tie() (
CORBA::release(_роа);
if (_rel) { delete _ptr;
} }
T* _tied_object() { return _ptr; } void _tied_object(T& t) { if (_rel) { delete _ptr;
}
_ptr = &t;
_rel = 0;
}
void _tied_object (T *p, CORBA::Boolean release=l) {
if (_rel) { delete _ptr; }
_ptr = p;
_rel = release; }
CORBA::Boolean _is_owner() { return _rel; } void _is_owner(CORBA::Boolean b) { _rel = b; } CORBA::Long op1(CORBA::Char _x, CORBA::Short_out _y) { return _ptr->opl(_x, _y); }
Portableserver::POA_ptr _default_POA() {
if (ICORBA::is_nil(_poa)) { return _poa;
} else {
return PortableServer_ServantBase::_default_POA();
} } };
tfinclude "vpost.h"
ttendif
class POA_example : public virtual PortableServer_ServantBase { protected:
POA_example() {}
virtual ~POA_example() {}
public:
static const CORBA::Typeinfo _skel_info;
virtual const CORBA::TypeInfo *_type_info() const;
example_ptr _this();
virtual void *_safe_narrow(const CORBA::TypeInfo&) const;
static POA_example * _narrow(PortableServer_ServantBase *_obj);
// Еще не имплементирован метод opl
virtual CORBA::Long opl(CORBA::Char _x, CORBA::Short_out _y) = 0;
// Автоматически имплементированы
static void _opl(void *_ob j, CORBA::MarshalInBuffer &_istrm, const char *_oper, VISReplyHandlerS handler);
);
Методы скелетонов, сгенерированные компилятором IDL
Сгенерированы два метода: метод opl, который объявлен в файле IDL, а также метод _opi. С помощью класса POA_exampie определен виртуальный метод opl. При имплементации класса необходимо будеть имплементировать и этот метод. Класс рол_ехатр1е называется скелетоном, а его метод _ор1 вызывается тогда, когда приходит клиентский запрос. Внутренний метод скелетона переправит параметры запроса, вызовет метод opl, вернет параметры (или исключение), после чего брокер ORB возвратит ответ клиенту.
Шаблон класса, создаваемый компилятором IDL
Помимо класса POA_example, компилятор создает класс _tie_example.
Пример создаваемого класса-шаблона.;
template <class Т>
class POA_example_tie : public POA_example {
public:
POA_example_tie (T& t): _ptr(&t), _poa(NULL),
_rel((CORBA::Boolean)0) (}
POA_example_tie (T& t, Portableserver::POA_jptr poa): _ptr(&t), _poa(Portableserver::—duplicate(poa)), _rel((CORBA::Boolean)0) {}
POA_example_tie (T *p, CORBA::Boolean release= 1)
: —ptr(p),_poa(NULL), _rel(release) (}.
POA_example_tie (Т *р, Portableserver::POA_ptr роа, CORBA::Boolean release =1)
: _ptr(p), _poa(Portableserver::_duplicate(poa)), _rel(release) (}
virtual ~POA_example_tie() ( /* . . . */ }
T* _tied_object() {/*...*/}
void _tied_object(T& t) ( /* . . . */ }
void _tied_object(T *p, CORBA::Boolean release=l) {/*...*/}
CORBA::Boolean _is_owner() {/*...*/}
void _is_owner(CORBA::Boolean b) (/*...*/}
CORBA::Long opl(CORBA::Char _x, CORBA::Short_out _y) {/*...*/ } Portableserver::POA_ptr _default_POA() {/*...*/} };
Задание атрибутов интерфейса в IDL
Помимо действий, описываемых в файле описания интерфейса, в IDL можно задавать и атрибуты. По умолчанию все атрибуты могут быть доступны как для чтения, так и для записи. Компилятор IDL создает два метода — один для того, чтобы задавать значения атрибутов, второй — для чтения значений атрибутов. Можно задать также атрибуты, которые будут предназначены только для чтения. Для таких атрибутов генерируется лишь единственный метод, позволяющий читать значения атрибутов.
Рассмотрим пример, где описаны два атрибута:
interface Test {
attribute long count;
readonly attribute string name;
};
Получим такие фрагменты кода:
class test : public virtual CORBA::Object {
virtual CORBA::Long count();
virtual void count(CORBA::Long count);
virtual char * named;
Однонаправленные операции, не возвращающие значений
IDL позволяет нам описывать операции, которые не имеют возвращаемых значений. Это однонаправленные методы, oneway методы. Эти операции имеют исключительно входящие параметры. При обращении к однонаправленному методу происходит отправка запроса серверу, но сервер не посылает никакого подтверждения в ответ. Поскольку для соединения клиента и сервера в Visibroker используется протокол TCP/IP, то можно быть уверенным в том, что запрос будет доставлен серверу, а также в том, что сервер был доступен во время отправки запроса. Однако нет никакой возможности определить, был ли этот запрос обработан сервером. Однонаправленные запросы не могут вызывать исключений и не могут возвращать значения.
* ПримерI
interface oneway_example {
oneway void set_value(in long val) ; };
Описание интерфейса, наследованного от другого интерфейса
Язык IDL позволяет описать интерфейс, который создан как наследник на основе другого интерфейса. Сгенерированные классы будут отражать существующие отношения наследования. Все методы, типы, константы, описанные в родительском интерфейсе, будут видимы в унаследовавшем их дочернем интерфейсе.
[■ММЯ1|||»1^^
interface parent {
void operationl();
};
interface child : parent {
long operation?(in short s);
};
class parent : public virtual CORBA::Object {
void operationl();
};
class child : public virtual parent {
CORBA::Long operation?(CORBA::Short s);
};
Клиентская часть
Рассмотрим более подробно клиентскую сторону приложения.
Инициализация брокера ORB
Связь между клиентом и сервером начинается с обращения к брокеру ORB. После того как клиент создает запрос, брокер ORB находит имплементацию объекта, в случае необходимости, активирует объект, доставляет запрос объекту и возвращает ответ клиенту. При этом клиенту совершенно безразлично, где находится объект, на том же самом компьютере, или где-то далеко в сети. Клиентская программа должна инициализировать ORB в явном виде. Рассмотрим пример кода: ♦include <fstream.h>
♦include "Bank_c.hh"
int main(int argc, char* const* argv) (
CORBA: : ORB_va г orb;
CORBA::Float balance;
try (
// Инициализируем брокер
orb = CORBA::ORB_init(argc, argv);
}
Связь с объектами
Удаленный объект доступен клиенту посредством ссылки на этот объект. Ссылка на объект обычно может быть получена с использованием функции <interface> _bind(). Как происходит поиск имплементации объекта на сервере и установка связи с ним, скрыто внутри ORB.
Что происходит во время связи с объектом
Когда стартует серверный процесс, вызывается метод corba::ORB.init(), при помощи которого серверный процесс сообщает о себе агенту SmartAgent. После этого брокер ORB производит ряд действий:
ORB связывается с агентом SmartAgent для определения местоположения имплементации объекта, в котором реализован запрашиваемый интерфейс. Имя объекта указывается при обращении к функции _bind();
после того как имплементация объекта найдена, ORB пытается установить связь между имплементацией объекта и клиентским приложением;
после того как связь будет благополучно установлена, ORB создает прокси-объект и возвращает ссылку на него. Клиент вызывает методы прокси-объекта, которые в свою очередь взаимодействуют с серверным объектом.
Клиентская программа никогда не взывает конструкторов серверных классов, вместо этого она получает ссылку на объект, используя метод _bind ().
Portableserver::Objectld_var manager_id =
Portableserver::string_to_ObjectId("BankManager");
Bank::AccountManager_var = Bank::AccountManager::_bind("/bank_agent_poa", manager_id);
Вызов операций на сервере
Клиентская программа использует ссылки для того, чтобы вызвать операции на объекте или получить доступ к данным, содержащимся в объекте.
// Вызов операции
balance = account->balance();
cout « "Balance is $" « balance « endl;
Работа co ссылкой на объект
Статический метод _bind() возвращает клиентской программе ссылку на объект CORBA. Клиентская программа имеет возможность использовать эту ссылку для вызова методов объекта. Эти операции должны быть предварительно предусмотрены и описаны в файле IDL. Существует набор методов, которые объекты ORB наследуют от класса corba: :object. Этими методами можно пользоваться для того, чтобы управлять объектом.
Является ли ссылка на объект равной nil
Чтобы проверить, является ли ссылка на объект равной значению nil, используется метод CORBA _nii (). Метод возвращает 1, если ссылка на объект возвращает nil. Если метод возвращает 0, то ссылка на объект не равна nil.
: Пример, проверка на то, равна ли nil ссылка на объект■
class CORBA {
static Boolean is _nil(CORBA::Object_ptr ob j ) ;
};
Получение ссылки nil
Чтобы получить ссылку на объект, равную nil, используется метод класса corba: :Object nil о. Он возвращает значение niii для object_ptr.
class Object {
static CORBA::0bject_ptr _nil();
};
Копирование ссылки на объект
Когда клиентская программа взывает метод -duplicate, увеличивается на единицу значение счетчика, метод возвращает ссылку на тот же самый объект.
class Object {
static CORBA::Object—ptr —duplicate(CORBA::0bject_ptr ob j ) ;
};
Высвобождение ссылки на объект
Если ссылка на объект более не нужна, то ее можно освободить. Один из способов высвобождения ссылки— вызвать метод _release() класса corba: :object. Следует пользоваться именно этой функцией, но не вызывать оператор уничтожения при работе с интерфейсом.
class CORBA {
class Object {
void _release();
};
или
class CORBA {
static void release();
};
Получение количества ссылок на объект
Для каждого объекта можно получить значение количества ссылок на этот объект. Мы имеем возможность узнать, сколько копий ссылок на объект используется в программе. При первом обращении к методу _bind() количество копий устанавливается равным одному. При каждом последующем обращении к _bind() это значение увеличивается на единицу. При освобождении ссылки значение уменьшается на единицу. Если количество ссылок достигает значения 0, то Visibroker удаляет ссылку на объект. Когда клиент изменяет количество ссылок на объект, то это никак не отражается на количестве ссылок на объект, содержащихся на сервере.
class Object (
CORBA::Long _ref_count() const;
};
Преобразование ссылки в строку
Visibroker содержит класс orb, в котором есть метод, позволяющий преобразовывать ссылку на объект в строку, а также есть метод, позволяющий преобразовывать строку назад в ссылку на объект. Этот процесс называется стрингификацией (строкованием, преобразованием в строку). Методы преобразований представлены в табл. 9.3.
Таблица 9.3. Методы преобразований
Метод
Описание
object_to_string
Преобразует ссылку на объект в строку
string_to_object
Преобразует строку в ссылку на объект
Клиентская программа может воспользоваться методом object_to_strlng для преобразования ссылки на объект в строку, а затем передать строку другой клиентской программе. Вторая клиентская программа может затем преобразовать строку в ссылку на объект с использованием метода string_to_object и применять ее без необходимости установки связи с объектом в явном виде.
Определение имен объектов и интерфейсов
В нижеприведенной табл. 9.4 показаны методы класса object, с помощью которых можно определять имена объектов и интерфейсов. Если при вызове метода _bind() не было указано имя объекта, то обращение к функции _object_nameо будет возвращать значение null.
Таблица 9.4. Методы класса object
Метод
Описание■
_interface_name
Возвращает имя интерфейса
_object_name
Возвращает имя объекта
_repository_id
Возвращает идентификатор репозитория
Определение положения объекта
Если задана ссылка на объект, то клиентская программа имеет возможность определить, связан ли данный объект, для чего используется функция _is_bound (). Метод возвращает 1, если объект связан, и 0 в противном случае.
Функция _is_iocai() возвращает значение 1, если клиентская программа и имплементация объекта находятся внутри одного адресного пространства или одного процесса.
Функция _is_remote() возвращает 1, если клиентская программа и имплементация объекта располагаются в различных процессах, вне зависимости от того, находятся они на одном хосте или на разных (табл. 9.5).
Таблица 9.5. Методы определения местоположения объекта
Метод
Описание
_is_bound
Возвращает 1, если для данного объекта в настоящее время существует активная связь
_is_local
Возвращает 1, если имплементация объекта находится в том же адресном пространстве, что и клиент
_is_remote
Возвращает 1, если имплементация объекта не находится в том же адресном пространстве, что и клиент
Несуществующий объект
Метод _non_existent о позволяет определить, существует ли имплементация объекта для данной ссылки объекта. Этот метод запрашивает объект и определяет, существует ли его имплементация, и если объект существует, то возвращает значение 1.
Сужение ссылки на объект'
Процесс преобразования ссылки на объект от общего супер-типа объектной ссылки к более узкому, конкретному типу называется сужением ссылки (norrowing). Метод _narrow() может создать новый класс C++ и возвратить ссылку на этот класс. Если в дальнейшем этот объект более не понадобится, то следует освободить ссылку, созданную при помощи _narrow().
Account *acct;
Account *acct2;
Objec *obj ;
acct = Account::_bind();
obj = (CORBA::Object *)acct;
acct2 = Account::_narrow(obj);
Расширение ссылки
Преобразование ссылки на объект к более широкому типу объектной суперссылки называется расширением ссылки (widening).
Account *acct;
CORBA::Object *obj;
acct = Account::_bind();
obj = (CORBA::Object *)acct;
Резюме
В этой главе мы лишь слегка прикоснулись к технологии CORBA, рассмотрев простейшие приложения и разобрав основные моменты использования ключевых механизмов CORBA. Мы не углублялись в концепцию архитектуры, не изучали возможности. Читатель сам сможет уделить изучению и работе с CORBA столько времени и сил, сколько потребуется.
Глава 10
Примеры интернет-приложений
В этой главе мы рассмотрим два примера интернет-приложений. Первый пример посвящен интернет-аукциону. Второй пример — транспортная интернет-биржа.
Интернет-аукцион
Здесь мы рассмотрим интернет-аукцион, созданный средствами языка PHP. Аукцион содержит основные функции, необходимые для его работы. Он может быть быстро и легко установлен на любой операционной системе. Если используется Windows, то рекомендуется операционная система NT или Windows 2000 (Windows 2000 Server).
Все файлы располагаем в папке auction в каталоге wwwroot, затем конфигурируем папку из менеджера служб Интернета Start -> Programs -> Administrative Tools -> Internet Services Manager (рис. 10.1).
Находим папку auction, щелкаем на ней правой кнопкой мыши, выбираем properties, в появившемся окне идем на закладку Documents (рис. 10.2), нажимаем кнопку Add и вписываем имя стартового документа аукциона. Стартовой страницей аукциона является index.php (рис. 10.3).
Все приводимые примеры файлов являются работающими. Аукцион тестирован на платформах Windows 98, Windows 2000 Server, Windows NT, Solaris, FreeBSD. В настоящей главе приведены все базовые файлы, обеспечивающие функциональность аукциона, графические файлы отсутствуют. При настройке аукциона необходимо учитывать конкретные особенности и настройки сервера MySQL.
internet Information Service:
f Default FTP Site
Default Web Site ®“9l Scripts Й » HSHelp 13 ® IISAdmin Bj S HSSamples {+) ® MSADC Щ Cj Printers Bl (^ _vti_b<n 0- uJ classes q
i Ш П cg-bin : 0 Cl domnin
: 0 О images
У
И Q pay
Щ О upload
ЕВ О vokova i*l a _vti_cnf
Nan*
& cgi-bin a domnin images
£pay
Gl upload
Q vb ^ volkova C3„vtLcnf ^ mail$end.php У auction.jpg У buy.ipg 31 buycategorieslOO... •1 buycategorie$150... § buycategorie$200... 3| buycategories250... 31 buyca(egorie$300... Щ buycategories35O... f®! buycategorie$400... I •! buycategorie$450
ЯШ
i
Рис. 10.1. Конфигурируем Web-сервер
Рис. 10.3. Стартовая страница аукциона
. Файл lndex.php;
I .пи* ft.. .^
<?php
mail("address@address.com", "sajt ya posetil", "poka ".$REMOTE_ADDR); ?>
<html>
<head>.
<meta name="keywords" content="auction, buy, sell, exchange, money, used, new, bid, win, gidder, winner, deal, e-olymp ">
<META name="description" content="best free auction for everyone, you can sell and buy whatever you want, register now by june 15 2002, and get free liftime membership">
<title>Olymp's Auction. WELCOME !</title>
</head>
<frameset rows="70,*" border=0>
Здесь два фрейма, в indexl.html (рис. 10.4).Здесь два фрейма, в indexl.html (рис. 10.4).Register now and get free membership forever!Register now and get free membership forever!
Здесь два фрейма, в indexl.html (рис. 10.4).
Здесь два фрейма, в indexl.html (рис. 10.4).
Register now and get free membership forever!
Register now and get free membership forever!
<frame name="header" scrolling="no" target="main" src="header.html">
<frame name="main" src="indexl.html">
<noframes>
<body>
<font color="#FEF8C0">International market place to sell whatever ■ you want, to buy and exchange.</font>
<p>This page uses frames, but your browser doesn't support them.</p>
</body>
</noframes>
</frameset>
</html>
которые загружаются два файла: header.html и
Файл header.html . - ■‘'
<html>
<head>
<meta http-equiv="Content-Type" content®"text/html;
charset=windows-1252">
<meta name®"keywords" content®"free, no charge, auction, buy, sell, exchange, money, used, new, bid, win, winner, deal, e-olymp">
<title>To registersnbsp;snbsp;Snbsp;Snbsp;
To sellSnbsp;Snbsp;Snbsp;Snbsp; To buy</title>
</head>
<body bgcolor®"#FEF8C0" background=cockroaches.jpg>
<center>
<table width=100% border=Oxbody>
<!— <trxtd width®10%>Snbsp; </tdxtd width=30%x/td> <td width=30%x/td><td width=30%x/td> </tr> —>
<trxtd width=30%ximg src=logo. jpgxpx/tdxtd width=20%>
<font size="4"xa href="register.html" target=main>
<img src=reg.jpg alt='To register' border=0x/ax/font>Sribsp; Snbsp; Snbsp; Snbsp;
</tdxtd width=20%xfont size=4Xa href="sellcategories.html" target=main>
<imgsrc=sell.jpgalt='Tosell’bor-
der=Ox/a>Snbsp; Snbsp; Snbsp; Snbsp; </fontx/tdxtd width=20%xfont size=4> <a href="buycategories.html" target=main>
<img src=buy.jpg alt='To buy' border=0>
</a></font>
</tdx/trx/bodyx/table>
</center>
<font color®"#FEF8C0">Free of charge to all customers international market place to sell whatever you want, to buy and exchange.</font>
</body>
</html>
. Файл index1.html 4•-•
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<META name="description" content="best free auction for everyone">
<ineta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta name="keywords" content="auction, buy, sell, exchange, money, used, new, bid, win, gidder, winner, deal, e-olymp">■
<title>Welcome to Olymp's Auction Starting Page</title>
</head>
<body bgcolor="#FEF8C0">
<p> <font color="#FEF8C0">International market place to sell whatever you want, to buy and exchange. </fontx/p>
<font color="#FEF8C0">Free of charge to all customers international market place to sell whatever you want, to buy and exchange.</font>
<p> </p>
<table border="0" width="100%" onclick="document.location.href= 'buyallcategorieshtml.php'" >
<tr>
<td width="100%">
<p> </td>
</tr>■
<tr>
<td width="100%" valign="middle" align="center">'
<h2 align="center">
<font size=+2 color=magenta><B>Register now and get free membership forever!
</bx/font> <Pxbr><br>
<font color="#3D30D6">Welcome to </fontx/h2>
<P>
<img src=main.jpg align=center>
</td>
</tr>
</table><P>
</body>
</html>
Ссылки есть только в верхнем фрейме header.html. Общая структура сайта показана в табл. 10.1.
Таблица 10.1. Структура сайта
Index.php (два фрейма)
Верхний фрейм header.html
Register.html
Регистрация нового пользователя
Register, php
Внесение нового пользователя в базу данных, отправка почты со ссылкой на regfinal.php новому пользователю для подтверждения регистрации
Regfinal.php
Активация нового пользователя
Sellcategories, html
Выбор категории для товара
Itemregisterhtml.php
Сбор информации о товаре перед регистрацией
Itemregister.php
Внесение информации о товаре в базу данных
Buycategories.html
Выбор категории или подкатегории"
Showitemshtml.php
Выбор товара из всего списка товаров данной категории или подкатегории
Itempresent, php
Детальная информация о товаре и форма для введения новой суммы и пользовательских данных
Bidding.php
Регистрация новой сделки
При создании сайта использовался язык PHP и база данных MySQL на платформе Windows 2000 Server. Предварительно необходимо установить
PHP и MySQL. Каталог сервера будет Inetpub/wwwroot/auction/.
Структура базы данных
База данных имеет достаточно простую структуру. Она названа auction и содержит в себе три таблицы:
таблица event;
таблица item;
таблица user.
Таблица event
Таблица event записывает все события, т. е. все изменения с товарами, приведшие к смене цен или состояний товаров или пользователей. Таблица содержит восемь столбцов. Это самая большая таблица (по количеству строк), она растет быстрее двух других таблиц.
Структура таблицы такова:
type int(2) — тип события (используется для классификации);
login varchar (20) — имя пользователя;
id int (12) — идентификатор товара;'
bdate date — дата совершения сделки;
btime time — время совершения сделки;
bamount doubie(i6,2) — цена сделки;
ip varchar (20) — клиентский IP пользователя;
misc varchar (255) — дополнительное поле (в данное время используется для хранения форматированного времени).
Таблица user
Таблица user используется для хранения информации о пользователях системы. Вот ее структура (всего 8 столбцов):
login varchar (20) — имя пользователя (login);
name varchar (20) — реальное имя пользователя (фамилия и имя);
password varchar(20) —пароль;
email varchar(20) —адрес e-mail;
tel varchar (20) — телефон;
address varchar (255) — ПОЧТОВЫЙ адрес;
active int (1) — активен ли пользователь (если активен, то поле равно 1);
misc varchar (255) — прочая информация.
Таблица item
Таблица item содержит в себе 14 столбцов. В ней хранится информация о продаваемых и проданных товарах. Рассмотрим структуру этой таблицы: □ id int (12) — уникальный идентификатор товара (присваивается при регистрации);
category int (4) — категория товара;
login varchar(20) — имя пользователя, которому принадлежит товар;
iname varchar(20) — название товара;
description varchar (255) — описание товара;
sdate date — дата начала продажи товара;
stime time — время начала продажи товара;
edate date — дата окончания продажи товара;
etime time время окончания продажи товара,
photo int (1) — есть ли картинка товара;
active int (1) — активен ли товар (если активен, т. е. в состоянии текущей продажи, то значение поля 1, 2 соответствует тому, что торги на этот товар закончены, 3 — торги закончены и e-mail уведомления владельцу товара и победившему покупателю разосланы);
userprice doubie(i6,2) —цена товара;
ip varchar (20) — IP-адрес владельца товара в момент регистрации;
misc varchar(255) — прочая информация.
Функционирование сайта
Рассмотрим более подробно устройство сайта. Основной фрейм indexl.html не представляет ничего существенного, с него нет ни одной ссылки, это заставка для входа на сайт. Все ссылки осуществляются из заголовка, который служит меню, этот фрейм всегда присутствует. Вероятно, можно было решить задачу о ссылках более удобным способом, не прибегая к фреймам, но в этом варианте мы использовали фреймы. Меню содержит ссылки на три основные функции сайта:
регистрация новых пользователей;
регистрация новых товаров для продажи;
покупка товаров.
Регистрация новых пользователей
Регистрация новых пользователей начинается со сбора информации о пользователе в форме, которая описана в файле register.html. При переходе по
ссылке to register открывается окно для регистрации, которое показано на рис. 10.5. Здесь пользователь вводит информацию о себе и свой электронный адрес почты.
Рис. 10.5. Окно регистрации нового пользователя
Форма отправляется для обработки на сервере, серверный PHP-скрипт находится в файле register.php.
;.Файл register.html
<html>
<head>
<title></title>
</head>
<body bgcolor="#DDDDDD">
<h2 align="center"> </h2>
<table border="0" width="100%">
<tr>
<td width="40%" align="right">
<h2xfont color="#808000">New user registration.</fontx/h2>
</td>
<td width="60%"x/td>
</tr>
</table>
<p align="center"xixfont color="#4A492F">To register, please, use this form. c/fontx/ix/p>
<p align="center"> </p>
<table border="0" width="100%" height="235">
<form action="register.php" method="post">
<tr>
<td width="100%" height="23" colspan="2"xixfont size=”4" face= "Arial Black">Your personal identification: </fontx/i>
<p> </td>
</tr>
<tr>
<td width="36%" height="23">
Choose your login name: </td>
<td width="64%" height="23"> <input type=text name="login"> <i>(Use letters
and numbers only, do not use space or other special characters, please!) </iX/td>
</tr>
<tr>
<td width="36%" height="23">
Write your full name: </td>
<td width="64%" height="23"> <input type=text name="name" size= "37"></td>
</tr>
<tr>
<td width="36%" height="23">
Choose your password: </td>
<td width="64%" height="23"> <input type=password name= "password" size="16"x/td>
</tr>
<tr>
<td width="100%" height="23" colspan="2">
chr>
<pxfont face="Arial Black"xi>Your contact information :с/ix/font></p>
cp> c/td>
</tr>
ctr>
ctd width="36%" height="23">
Your e-mail: c/td>
<td width="64%" height="23"> cinput type=text name="email" size= "25"x/td>
</tr>
ctr>
ctd width="36%" height="23">
Your telephone number: c/td>
ctd width="64%" height="23"> cinput type=text name="tel" size= "28"x/td>
</tr>
ctr>
ctd width="36%" height="23">
Your address: c/td>
ctd width="64%" height="23"> cinput type=text name="address" size= "62">c/td>
c/tr>■
ctr>
ctd width="36%" height="55">c/td>
ctd width="64%" height="55" valign="bottom" align="right">
cinput type=submit value="Submit registration">
c/td>
c/tr>
С/form> c/table> chr> c/html>
Собранная информация отправляется для обработки на сервер. Серверный скрипт register.php производит запись полученной информации в базу данных и отправляет e-mail по указанному в форме адресу. Сообщение содержит случайным образом сгенерированную информацию, которая копируется в базу данных и содержится в HTML-ссылке, указанной в сообщении. После того как пользователь получит e-mail, он должен перейти по ссылке,
это нужно, чтобы завершить регистрацию (изменить значение поля active таблицы user, которое должно быть равно 1 для активного пользователя). Во время создания нового пользователя в поле active таблицы user заносится случайное число. Если при обращении по ссылке из письма файл registerfmal.php получает число, которое совпадает со сгенерированным ранее случайным числом, которое хранится в базе данных, то поле active изменяется на 1, пользователь становится активным и может покупать товар или продавать свой.
Отметьте, что почти все PHP-скрипты отслеживают и записывают в базу данных клиентские IP. После предварительной регистрации пользователю предлагается проверить свою почту (рис. 10.6).
Registering andreil
User andreil have been registered.
Please, check your mail to finalize registration.
Рис. 10.6. Предварительная регистрация завершена
; Файл register.php
<?php
$date = date("F j, Y") ;
$time = date("g:i a");
$ip=$REMOTE_ADDR;
$misc=$date.'; *.$time.'; '.$ip;
function make_seed() {
list($usec, $sec) = explode(' ', microtime());
return (float) $sec + ((float) $usec * 100000);
}
srand(make_seed());
$c=mysql_connect("localhost:3306", "frggrr", "Dgtggtgggg");
mysql_select_db("frggrr",$c);■
$stroka= "select * from user where login='".$login.'";";
$result = mysql_query($stroka);
if (mysql_num_rows($result) == 0){
$activel= rand(2,9999)*23;
echo "<htmlxheadxtitle>Registering ". $ login. ". </titlex/head>";
echo "Registering <bxi>".$login. "</bx/i>.<P>";
$string="insertintouservalues
(' ".$login."','".$name."','".^password."','".$email."', 1".$tel."', '".$add ress."','".$activel."',1".$misc."')";
$res = mysql_db_query("frggrr", $string);
$stringl="To finalize registration go to http://e- olymp.com/regfinal,php?login=".$login."&active=".$activel;
<scriptlan-
guage='javascript'>document.location.href='http://olymp/auction/ mailregister.asp?address=".$email."&string=".$stringl."';</script>;";
$m = mail($email, "Races Administration", $stringl,"From:
olymp@ked.de\r\n" ."Reply-То: olymp@ked.de\r\n" ."X-Mailer: PHP/" . phpversion());
if ($m)(echo "<P>Mail is successful.";} else (echo "Mail was not successful. Contact mailto:olymp@ked.de";};
echo "User <bxi>".$login.'</bx/i> have been registered.<Pxh2 align=centerxfont color=green>Please, check your mail to finalize registration. </fontx/h2>' ;
}.
else (echo "<BXH3 align=center>Login name <bxixfont color=green size=+2>". $login." </fontx/bx/i>already exists, please, choose other
login name.</h3x/b><P>returningback ...<script lan-
guage='javascript'>history.back(); alert('User with this name already exists, choose another login name.');</script>";);
echo "</html>";
В файле registr.php происходит также проверка того, существует ли указанный пользователь, если заданное имя пользователя существует, предлагается выбрать другое имя. Собранная информация вносится в базу данных, создается неактивный пользователь. Пользователь считается активным, когда в записи для этого пользователя в столбце active таблицы user хранится значение 1.
Файл regfinal.php активизирует пользователя. Для того чтобы пользователь стал активным, необходимо обратиться к файлу regfinal.php, указав значение поля active для данного пользователя, созданное при предварительной регистрации в файле register.php. Это число передается почтой пользователю при предварительной регистрации.
; ■
} Файл regfinal.php=
<?php
$c=mysql_connect("localhost:3306", "frggrr", "Dgtggtgggg") ;
mysql_select_db("frggrr",$c);
$stroka= "update user set active=l where active='".$active."' and login='".$login."';";
$result = mysql_query($stroka);
if ($result) (echo "User cixfont color=green>" ,$login. "</ix/font> registration completed sucssefully.";) else (echo "Try to register once again or contact Races administration";);
?>
После того как пользователь перешел по присланной ссылке, регистрация завершена. Пользователю необходимо запомнить указанные им имя и пароль, они понадобятся в дальнейшем.
Продажа товаров
Стартовой страницей для продажи товаров служит файл sellcategories.html. В этом файле пользователь выбирает категорию, к которой относится продаваемый товар. По ссылке с номером категории происходит переход (рис. 10.7).
Рис. 10.7. Главная страница регистрации нового продаваемого товара
Файл sellcategories.html
<html>
<head>
<!— categories ended with two zeros are categories headings. —>
<title>Categories for BUYING</title>
</head>■
<body bgcolor="#DDDDDD">
<hr>
<h2 align="center">Choose item category and sell.</h2xhr>
<h3><!— a href=itemregisterhtml.php?category=1000 target=main —>
Art <!— /a —X/h3>
<center>
<a href=itemregisterhtml.php?category=1005 target=main> Antiques
</axbr>
<a href=itemregisterhtml.php?category=1010 target=main> Art </axbr>
</center>
<h3><!— a href=itemregisterhtml.php?category=1500 target=main —> Automotive<!— /a —x/h3>
<center>
<a href=itemregisterhtml.php?category=1505 target=main>Automobilia
</a><br>
<a href=itemregisterhtml.php?category=1510 target=main>Classic & Collectors</a><br>
<a href=itemregisterhtml,php?category=1515 target=main>Motorcycles
</a><br>
<a href=itemregisterhtml.php?category=1520 target=main>Parts & Accessories</a><br>
<a href=itemregisterhtml.php?category=1525 target=main>Tools </axbr>
<a href=itemregisterhtml.php?category=1530 target=main>Toys</a><br>
<a href=itemregisterhtml.php?category=1535 target=main>Vehicles </axbr>
<a href=itemregisterhtml.php?category=1540 target=main>Other</a><br>
</center>
<h3x!— a href=itemregisterhtml,php?category=2000 target=main —> Accessories & Clothes <!— /a —x/h3>
<center>
<a href=itemregisterhtml.php?category=2005 target=main>Women</axbr>
<a href=itemregisterhtml.php?category=2010 target=main>Men </a><br>
<a href=itemregisterhtml.php?category=2015 target=main> Children</axbr>
<a href=itemregisterhtml.php?category=2020 target=main>Baby </a><br>
<a href=itemregisterhtml.php?category=2025 target=main>Accessories</axbr>
<а href=itemregisterhtml.php?category=2030 target=main>Sport Wear </axbr>
<a href=itemregisterhtml.php?category=2035 target=main>Leather & Fur</a><br>
<a href=itemregisterhtml.php?category=2040 target=main>Shoes </axbr>
<a href=itemregisterhtml.php?category=2045 target=main>Other</axbr>
</center>
<h3x!— a href=itemregisterhtml,php?category=2500 target=main —> Books <!— /a —></h3> <center>
<a href=itemregisterhtml.php?category=2505 target=main>Bestsellers</a><br>
<a href=itemregisterhtml.php?category=2510 target=main>Braille </a><br>
<a href=itemregisterhtml.php?category=2515 target=main>Children</axbr>
<a href=itemregisterhtml,php?category=2520 target=main>Classic </axbr>
<a href=itemregisterhtml.php?category=2525 target=main>Comics</axbr>
<a href=itemregisterhtml,php?category=2530 target=main>Fiction</axbr>
<a href=itemregisterhtml,php?category=2535 target=main> Food, Wine, Cooking </axbr>
<a href=itemregisterhtml.php?category=2540 target=main> Large Print </axbr>
<a href=itemregisterhtml.php?category=2545 target=main> Literature</axbr>
<a href=itemregisterhtml.php?category=2550 target=main> Magazines </aXbr>
<a href=itemregisterhtml.php?category=2555 target=main> Non-Fiction </axbr>
<a href=itemregisterhtml.php?category=2560 target=main> Other Languages </a><br>
<a href=itemregisterhtml,php?category=2565 target=main> Poetry </axbr>
<a href=itemregisterhtml.php?category=2570 target=main> Rare & Antique </a><br>■
<a href=itemregisterhtml.php?category=2575 target=main> Reference Books </a><br>
<a href=itemregisterhtml,php?category=2580 target=main> Textbooks & Education </aXbr>
<a href=itemregisterhtml.php?category=2585 target=main> Travel, Reference & Education </axbr>
<a href=itemregisterhtml ,php?category=2590 target=main> Other </aXbr>
</center>
<h3x!— a href=itemregisterhtml.php?category=3000 target=main —>
Business <!— /a —x/h3>
<center>
<а href=ltemregisterhtml.php?category=3005 target=main> Business & Office </axbr>
<a href=itemregisterhtml,php?category=3010 target=main> Holesale & Bilk Quantities </a><br>
<a href=itemregisterhtml.php?category=3015 target=main>Real Estate </a><br>
<a href=itemregisterhtml.php?category=3020 target=main> Tickets </a><br>
<a href=itemregisterhtml.php?category=3025 target=main> Transportation
</a><br>'
<a href=itemregisterhtml.php?category=3030 target=main> Travel </axbr>
<a href=itemregisterhtml.php?category=3035 target=main> Weddings </aXbr>
<a href=itemregisterhtml.php?category=3040 target=main> Other </a><br>
</center>
<h3><1— a href=itemregisterhtml.php?category=3500 target=main —> Collectibles <!— /a —x/h3>
<center>
<a href=itemregisterhtml.php?category=3505 target=main> Advertising
</axbr>
<a href=itemregisterhtml,php?category=3510 target=main> Animals </a><br>
<a href=itemregisterhtml.php?category=3515 target=main> Autographs </axbr>
<a href=itemregisterhtml,php?category=3520 target=main> Kitchenware </axbr>
<a href=itemregisterhtml.php?category=3525 target=main> Memorabilia </axbr>
<a href=itemregisterhtml,php?category=3530 target=main> Novelties </axbr>
<a href=itemregisterhtml.php?category=3535 target=main> Science & Nature </a><br>
<a href=itemregisterhtml.php?category=3540 target=main> Science Fiction </a><br>
<a href=itemregisterhtml.php?category=3545 target=main> Toys </a><br>
<a href=itemregisterhtml.php?category=3550 target=main> Transportation </a><br>
<a href=itemregisterhtml.php?category=3555 target=main> Other </a><br>
</center>
<h3><!— a href=itemregisterhtml,php?category=4000 target=main —> Computers <!— /a —></h3>
<center>
<a href=itemregisterhtml.php?category=4005 Macintosh </aXbr>
target=main>
Apple,
<a href=itemregisterhtml.php?category=4010
Compatible </a><br>
target=main>
PC, IBM
<a href=itemregisterhtml.php?category=4015
</a><br>
target=main>
Hosting
<a href=itemregisterhtml,php?category=4020
</axbr>
target=main>
Domain Names
<a href=itemregisterhtml.php?category=4025
</axbr>
target=main>
Drives, Media
<a href=itemregisterhtml,php?category=4030 Peripherals </axbr>
target=main>
Input/Output
<a href=itemregisterhtml,php?category=4035
</axbr>
target=main>
Monitors
<a href=itemregisterhtml.php?category=4040
IT </aXbr>
target=main>
Networking &
<a href=itemregisterhtml,php?category=4045 Hardware</axbr>
target=main>
Other
<a href=itemregisterhtml.php?category=4050 Supplies </axbr>
target=main>
Printers &
<a href=itemregisterhtml,php?category=4055
</a><br>
target=main>
Scanners
<a href=itemregisterhtml,php?category=4060 </a><br>
target=main>
Services
<a href=itemregisterhtml,php?category=4065
</a><br>
target=main>
Software
<a href=itemregisterhtml,php?category=4070
</a><br>
target=main>
Computer Books
</center>
<h3> <!— a href=ltemregisterhtml,php?category=4500 target=main —> Electronics & Cameras <!— /a —x/h3>
<center>
<a href=itemregisterhtml,php?category=4505 target=main> Audio
</axbr>
<a href=itemregisterhtml.php?category=4510 target=main> Calculators & Machines </axbr>
<a href=itemregisterhtml.php?category=4515 target=main> Photo Cameras & Equipment </aXbr>
<a href=itemregisterhtml.php?category=4520 target=main> Computers </a><br>
<a href=itemregisterhtml.php?category=4525 target=main> Phones
</a><br>
<а href=itemregisterhtml,php?category=4530 target=main>Video </a><br>
<a href=itemregisterhtml,php?category=4535 target=main>Other
</a><br>
</center>
<h3><!— a href=itemregisterhtml.php?category=5000 target=main —> Jewelry, Gems & Watches <!— /a —x/h3>
<center>
<a href=itemregisterhtml,php?category=5005 target=main> Beads, Amulets </a><br>.
<a href=itemregisterhtml,php?category=5010 target=main> Costume Jewelry </a><br>
<a href=itemregisterhtml.php?category=5015 target=main> Ethnic, Tribal Jewelry </axbr>
<a href=itemregisterhtml.php?category=5020 target=main>Fine Jewelry </a><br>
<a href=itemregisterhtml,php?category=5025 target=main> Hair Jewelry
</axbr>
<a href=itemregisterhtml.php?category=5030 target=main> Designer
Jewelry </a><br>
<a href=itemregisterhtml,php?category=5035 target=main> Jewelry Boxes
</a><br>
<a href=itemregisterhtml.php?category=5040 target=main> Jewelry
Supplies </axbr>
<a href=itemregisterhtml,php?category=5045 target=main> Loose Gemstones </axbr>
<a href=itemregisterhtml,php?category=5050 target=main> Men </axbr>
<a href=itemregisterhtml,php?category=5055 target=main> Watches
</a><br>
</center>
<h3><!— a href=itemregisterhtml,php?category=5500 target=main —>Home & Garden <!— /a —></h3>.
<center>
<a href=itemregisterhtml.php?category=5505 target=main>Appliances
</axbr>
<a href=itemregisterhtml.php?category=5510 target=main> Food & Beverage </axbr>
<a href=itemregisterhtml.php?category=5520 target=main> Furnishings
</aXbr>
<a href=itemregisterhtml,php?category=5525 target=main> Housewares
</axbr>
<a href=itemregisterhtml,php?category=5530 target=main> Kitchen & Cooking </a><br>
target=main>
Lawn & Garden
target=main>
Pet Supplies
target=main>
Saunas, Pool:
target=main>
Real Estate
target=main>
Services
target=main>
Textiles,
target=main>
Other
<а href=itemregisterhtml.php?category=5535 </a><br>
<a href=itemregisterhtml.php?category=5540 </a><br>
<a href=itemregisterhtml.php?category=5545 </axbr>
<a href=itemregisterhtml.php?category=5550 </axbr>
<a href=itemregisterhtml.php?category=5555 </axbr>
<a href=itemregisterhtml.php?category=5560 Linens & Quilts </aXbr>
<a href=itemregisterhtml.php?category=5565 </axbr>
</center>
<h3x!— a href=itemregisterhtml,php?category=6000 target=main —> Money, Coins, Stamps <!— /a —x/h3>
<center>'
<a href=itemregisterhtml.php?category=6005 target=main> Coins </axbr>
<a href=itemregisterhtml.php?category=6010 target=main> Medals &
Tokens </axbr>
<a href=itemregisterhtml.php?category=6015 target=main> Paper Money
</axbr>
<a href=itemregisterhtml.php?category=6020 target=main> Stamps
</axbr>
<a href=itemregisterhtml.php?category=6025 target=main> Other </aXbr>
</center>
<h3x!— a href=itemregisterhtml,php?category=6500 target=main —>
Movies & TV <!— /a —x/h3>
<center>
<a href=itemregisterhtml.php?category=6505 target=main>DVDs </axbr>
<a href=itemregisterhtml.php?category=6510 target=main> Video Tapes </axbr> "
<a href=itemregisterhtml,php?category=6515 target=main> Disks </a><br>
<a href=itemregisterhtml.php?category=6520 target=main> Equipment & Services </axbr>
<a href=itemregisterhtml.php?category=6525 target=main> Books </a><br>
<a href=itemregisterhtml,php?category=6530 target=main>Tickets </axbr> .
<a href=itemregisterhtml.php?category=6535 target=main> Other</axbr>
</center>
<h3><!— a href=itemregisterhtml.php?category=7000 target=main —> Music <! — /a __></h3>
<center>
<a href=itemregisterhtml,php?category=7005 target=main> CDs </a><br>
<a href=itemregisterhtml.php?category=7010 target=main> Tapes and Vinyl
</a><br>'
<a href=itemregisterhtml,php?category=7015 target=main> Tickets
</a><br>
<a href=itemregisterhtml.php?category=7020 target=main> Instruments & Equipment </a><br>
<a href=itemregisterhtml.php?category=7025 target=main> Sheet Music
</a><br>
<a href=itemregisterhtml,php?category=7030 target=main> Music Lessons
</a><br>
<a href=itemregisterhtml.php?category=7035 target=main> Books </axbr>
<a href=itemregisterhtml.php?category=1040 target=main> DVDs . </axbr>
<a href=itemregisterhtml.php?category=7045 target=main> Music Videos
</a><br>
<a href=itemregisterhtml,php?category=7050 target=main> Magazines
</a><br>'
<a href=itemregisterhtml.php?category=7055 target=main> Other </axbr>
</center>
<h3><!— a href=itemregisterhtml,php?category=7500 target=main —>Sports
<!— /a — ></h3>
<center>
<a href=itemregisterhtml.php?category=7510 target=main>Sporting Goods
</aXbr>'
<a href=itemregisterhtml.php?category=7520 target=main> Tickets
</a><br>
</center>
<h3><!— a href=itemregisterhtml.php?category=8000 target=main —> Toys, Hobbies, Games <!— /a —></h3>
<center>
<a href=itemregisterhtml.php?category=8005 target=main> Baby Toys
</a><br>
<a href=itemregisterhtml.php?category=8010 target=main> Dolls </axbr>
<а href=itemregisterhtml,php?category=8015 target=main> Games
</axbr>
<a href=itemregisterhtml,php?category=8020 target=main> Hobbies & Crafts </axbr>
<a href=itemregisterhtml,php?category=8025 target=main> Miscellaneous </a><br>
</center>
<h3x!— a href=itemregisterhtml.php?category=8500 target=main —> Other
<1— /a — ></h3>
<center>
<a href=itemregisterhtml.php?category=8505 target=main>Body Art, Tattoos </axbr>
<a href=itemregisterhtml.php?category=8510 target=main> Costumes </axbr>
<a href=itemregisterhtml.php?category=8515 target=main> Genealogy
</axbr>
<a href=itemregisterhtml.php?category=8520 target=main>Gifts & Party Supplies </axbr>
<a href=itemregisterhtml,php?category=8525 target=main> Health & Wellness </axbr>
<a href=itemregisterhtml.php?category=8530 target=main>Memberships
</axbr>
<a href=itemregisterhtml.php?category=8535 target=main> Metaphysical
</axbr>
<a href=itemregisterhtml,php?category=8540 target=main> Optics </axbr>
<a href=itemregisterhtml.php?category=8545 target=main> Personal Security </a><br>
<a href=itemregisterhtml,php?category=8550 target=main> Personalized, Customized </a><br>
<a href=itemregisterhtml.php?category=8555 target=main> Religious Products & Supplies </aXbr>
<a href=itemregisterhtml.php?category=8560 target=main> Services </axbr>
<a href=itemregisterhtml.php?category=8565 target=main> Shipping & Packing Supplies </axbr>
<a href=itemregisterhtml.php?category=8570 target=main> Subscriptions </a><br>
<a href=itemregisterhtml,php?category=8575 target=main> Show Supplies </axbr>
<a href=itemregisterhtml.php?category=8580 target=main> Uniforms
</a><br>
<а href=itemregisterhtml.php?category=8585 target=main> Other </a><br>
<center>
</body>
</html>
Файл sellcategories.html содержит ссылки на различные категории и подкатегории товаров. Категории товаров имеют свой номер — идентификатор категории. Подкатегории товаров имеют свой идентификатор подкатегории. Идентификатором категории считается число, кратное 100, идентификатором подкатегории считается число, кратное 10, но не кратное 100. Идентификатор категории или подкатегории передается скрипту itemregisterhtml.php в виде значения имени category. Все ссылки в файле sellcategories.html выписаны в явном виде. Планируется создание XML-файла описания структуры страницы выбора категории товаров для того, чтобы страницы выбора категории генерировались на сервер автоматически. Категория товара выбирается щелчком мыши, после чего происходит переход на форму сбора информации о товаре (рис. 10.8).
Рис. 10.8. Сбор информации о товаре
Здесь задается наименование товара, описание товара, стартовая цена на товар, заданная продавцом. Затем вводится продолжительность аукциона и информация о пользователе (рис. 10.9). Здесь же выбираем картинку для размещения на сервере.
.'гаи.'гаиj 4“ Back * •# • (^ it) Tjj i.^Search' |*1 Favorites Q}History j 1ф» £J >.! * -J j Address |#J hup //localhost/aucbon/j 4“ Back * •# • (^ it) Tjj i.^Search' |*1 Favorites Q}History j 1ф» £J >.! * -J j Address |#J hup //localhost/aucbon/:^ лпг 20:^ лпг 20on auction auction «action a^tira «исиопTo resisterTo sellon auction auction «action a^tira «исиопTo resisterTo sellliftMliftMд] J?Go j jlH« ?Jд] J?Go j jlH« ?Jion -auction auction auctionTo buyion -auction auction auctionTo buy■3 Olymp’s Auction. WE LCO M E I - Microsoft Internet Explorer
.'гаи
.'гаи
j 4“ Back * •# • (^ it) Tjj i.^Search' |*1 Favorites Q}History j 1ф» £J >.! * -J j Address |#J hup //localhost/aucbon/
j 4“ Back * •# • (^ it) Tjj i.^Search' |*1 Favorites Q}History j 1ф» £J >.! * -J j Address |#J hup //localhost/aucbon/
:^ лпг 20
:^ лпг 20
on auction auction «action a^tira «исиоп
To resisterTo sell
on auction auction «action a^tira «исиоп
To resisterTo sell
liftM
liftM
д] J?Go j jlH« ?J
д] J?Go j jlH« ?J
ion -auction auction auction
To buy
ion -auction auction auction
To buy
Enter starting price in euro: [<00
Auction duration.
For this item enter ending date and time:
How many days this item should be in auction (dd): How many hours this item should be in auction (hh):
You can upload a picture presenting your item. To do it, please, select *.jpg file here.
|C:\temp\boat.gifB'owSe |
Seller identification.
To register your item you need to enter valid login and password.
Enter your login name: juser
Enter your password: |““I
|®~7
Рис. 10.9. Задаем продолжительность аукциона и вводим логин и пароль
Через мгновение после того, как форма будет отправлена серверу, в окне браузера на миг появится информация об успешной регистрации сервера, затем в окно браузера загрузится информация о только что зарегистрированном товаре с информацией о текущей цене на него, а в отдельном появившемся окне будет выведена информация, что товар успешно зарегистрирован (рис. 10.10).
Рис. 10.10. Товар успешно зарегистрирован
■■Файл itemregisterhtml.php
<html>
<head>
<title></title>
</head>
<body bgcolor="#FEF8C0">
ch2 align="center"xfont color="#EC2F97">Nc/font>
cfont color="#83E2D9">ec/fontxfont color="#223344">wc/font>
cfont color="#E98B36">ic/fontxfont color="#1250DE">tc/font>
cfont color="#7C806A">ec/font>cfont color="#EC2F97">mc/font>
cfont color="#94D51C">rc/fontxfont color="#D03704">ec/font>
cfont color="#314AFD">gc/font>cfont color="#HFFFF">ic/font>
cfont color="#D03704">sc/font>cfont color="#008000">tc/font>
cfont color="#800080">rc/font>cfont color="#AAAAAA">ac/font>
cfont color="#D2B775">tc/fontxfont color="#FF0000">ic/font>
cfont color="#808000">o</fontxfont coior="#FF00FF">nc/font>
cfont color="#FFFF00">.c/font>c/h2>chr>
cform enctype="multipart/form-data" action="itemregister.php" method="post">
cinput type=hidden name="active" value=l><input type=hidden name="active" value=lxinput type=hidden name="photo" value="0">
ctable border="0" width="100%" height="304">
<tr>
<td width="100%" height="23" colspan="2"xfont color=
"#D2B775" size="4"xb>Item description. </bx/fontx/td>.
</tr>
<tr>
<td width="46%" height="23">
Enter item short name(up to 20 characters): cinput type= text name="iname">
<p> </td>
<td width="54%" height="23">
Enter item category ’<?php echo $category; ?>'. cinput type= hidden name="category" value='c?php echo $category ?>’>
cp> c/td>
c/tr>
Ctr>
ctd width="100%" height="23" colspan="2" align="center">Enter item
description (up to 255 characters):■
ctextarea rows="4" cols="60" name="description" cols="20"> c/textarea>
cl— cp> cinput type=text name="description" size="126"x/p> —>
Cp> c/td>
C/tr>
Ctr>
ctd width="100%" height="23" colspan="2"xfont size="4" color= "#808000">cb>Starting
price. c/bx/font> cp> c/p>
<p>Your need to set up minimal starting price for this item. </td> </tr> <tr>
<td width="46%" height="23">
Enter starting price in euro: <input type=text name="userprice" size= "10"x/td>
<td width="54%" height="23"x/td>
</tr>
<tr>
<td width="100%" height="23" colspan="2">
<p align="center"> </p>
<p align="center"> </p>
<p align="left"Xfont size="4" color="#008080"xb>Auction duration. </bx/fontx/p>
<p align="center">For this item enter ending date and time:</td> </tr> <tr>
<td width="33%" height="23">
How many days this item should be in auction (dd): <input type=text name= "days" size="17"X/td>
<td width="33%" height="23">
How many hours this item should be in auction (hh): <input type=text name= "hours" size="17"x/td>
</tr>
<tr><td>You can upload a picture presenting your item. To do it, please, select *.jpg file here.
<input type=file name="userfile">
</tdxtdx/td> </tr>
<tr>
<td width="100%" height="23" colspan="2">
<hr>
<pxfont color="#808080" size="4"xb>Seller identification.</b> </fontx/p>
<p> </p>
<p>To register your item you need to enter valid login and password.</p>
<p> </td>
</tr>
<tr>
<td width="46%" height="23">
Enter your login name: <input type=text name="login" size="14"x/td>
<td width="54%" height="23"X/td>
</tr>
<tr>
<td width="46%” height="23">
Enter your password: <input type=password name="password" size="14 "x/td>
<td width="54%" height="23"x/td>
</tr>
<tr>
<td width="100%" height="66" colspan="2" valign="bottom" align="right">
<p align="right"xfont face="Century Gothic" color=-
"#1250DE"xb>Register
new item here</bx/font> </p>
<p align="right">
<input type=submit value="submit registration'^
</td>■
</tr>
</table>
</form>
</html>
Файл itemregisterhtml.php определяет номер выбранной подкатегории товара и выводит форму (подкатегория выводится в качестве скрытого поля формы) для сбора информации о пользователе и о продаваемом товаре, а также для ввода начальной цены и срока истечения аукциона на товар. Здесь же может быть выбрана картинка, которая будет показана покупателю товара. Собранная информация передается скрипту itemregister.php, ему же передается прилагаемая картинка.
j Файл itemregister.php '■i
<?php
$date = date("Y-m-d");
$time = date("G:i:s");
$ip=$REMOTE_ADDR;
$c=mysql_connect("localhost:3306", "frggrr", "Dgtggtgggg"); mysql_select_db("frggrr",$c);
$stroka= "select * from user where login=,".$login."' and active=l;";
$result = mysql_query($stroka) ;
if (mysql_num_rows($result) == 1)(
$stroka= "select * from user where login=’".$login."' and password='".$password."’;";
$result = mysql_query($stroka);
if (mysql_num_rows($result) == 1){
if ($photo == 'on') {$p=l;} else {$p=0; $photo=3;};
echo "Registering item <bxl>" . $iname. "</bx/i>. <P>" ;
$stringl="select * from item order by id;";
$resl = mysql_query($stringl);
$noro=mysql_num_rows($resl);■
for ($kk=0; $kk < $noro; $kk++) {$ro=mysql_fetch_row ($resl);};
$idl=$ro[0]+1;
//вычисление времени окончания аукциона и преобразование дат //текущие дата и время
echo 'Current date: '.date("G:i:s Y-m-d").'<P>';
$Ydate = date("Y");
$Mdate = date("m");
$Ddate = date("d");
$Htime = date("G");
$Mtime = date("i");
$Stime = dateC's");
$ip=$REMOTE_ADDR;
$Ddate+=$days;
$Htime+=$hours ;
$etime = date ("G:i:s", mktime
($Htime,$Mtime,$Stime,$Mdate,$Ddate,$Ydate));
$edate = date ("Y-m-d", mktime
($Htime,$Mtime,$Stime,$Mdate,$Ddate,$Ydate)) ;
if (is_uploaded_file($userfile)) {
copy($userfile, "./images/".$idl); $p=l;}
//move_uploaded_file($userfile, "./images/".$idl); $p=l;}
else { echo "Possible file upload attack: filename ’$userfile'."; } //завершение загрузки рисунка
$string="insert into item values
('".$idl."','".$category."','".$login."', '".$iname."',1".$description."', ' ". $date."',"'. $time."','". $edate."',"'. $etime."',".$p.",'". $active."',". $userprice.",'".$ip."1,'".$timestamp."');";
$res = mysql_db_query("frggrr", $string);
$type=l;
$string2="insert into event values
("’.$type."', "'.$login.'",'".$idl."','".$date."',
"'.$time.'", 1".$userprice."','".$ip."', '');";
$res2 = mysql_db_query ("frggrr", $string2);
if ($res == FALSE) echo "<h2 align=centerxfont color=red>Your input contains mistakes. </fontx/hlxdiv align=center>(Data format was probably wrong).</div><p> Check your input and try again. Return to the item registration page <a href=javascript/history.back()>here.</a>";
if ($res <> 0) {
echo "Item <b><I>".$iname.'</bx/i> has been registered with id= '.$idl.
'.<script language=javascript>myWin=window.open("","newWindow","width=500 ,height=100,status=no,toolbar=no,menubar=no");myWin.document.open();myWin . document, write ("<htmlxheadxtitle>Item have been registered. </titlex/headxbody><b><centerxP>Item <font size=+l color=blue> ' .$iname.'</font> has been successfully registered.</centerx/body> </html>")/document.location.href="itempresent.php?id='.$idl. "'</script>';};
}
else {echo "<B><H3 align=center>Password does not match. Please, re-enter your password. <script language='javascript'>history.back(); alert('Password is incorrect! Please, retry!');</script>";};
} else {echo "<B><H3 align=center>Login name <b><ixfont color= red size=+2>". $login." </fontx/bx/i>does not exists, please register. </h3x/b><P>Forwarding to user registration page ..,<script language='javascript'>document.location='register.html'; alert('User does not exist. Please, register!');</script>";};
mysql_close($c);
?>
Файл itemregister.php собирает информацию о товаре, проверяет имя и пароль пользователя, вносит информацию в базу данных, возвращается на страницу демонстрации товара.
Покупка товаров
Стартовая страница для совершения покупок, ее внешний вид показан на рис. 10.11. Здесь перечислены все категории товаров и количество товара в каждой категории.
Рис. 10.11. Стартовая страница для совершения покупок
Страница описана в файле buyallcategorieshtml.php.
Файл buyallcategorieshtml.php
<html>
<head>
<!— categories ended with two zeros are categories headings. —>
<title>Categories for BUYING</title>
</head>
<body bgcolor="#FEF8C0" fortestonload="document.location.href= 'buyallcategorieshtml.php'">
<?php
$c=mysql_connect("localhost:3306", "olymp", "ddeddd");
mysql_select_db("olymp",$c);
function rows ($cat)(
$catl=$cat+100;
$t = floor($cat/100)*100;
if($t == $cat) ($stringl="select * from item where category < '".$catl."'
AND category > "'.$cat.'" AND active='1';"; }
else ($stringl="select * from item where categcry='".$cat."'
AND active='1';";};
$resl = mysql_db_query("auction",$stringl);
$noro = mysql_num_rows($resl) ;
echo $noro;
}
?>
<tablextrxtd width="50%"x/tdxtd width="50%">
<h2>Choose item category and buy.</h2x/tdx/trx/tablexhr>
<h3 align=center><a href=showitems,php?page=l&category=1000 target= main >Art (<?php rows (1000); ?>)</a x/h3>
<a href=showitems.php?page=l&category=1005 target=main> Antiques </a> (<?php rows(1005); ?>)<br>
<a href=showitems,php?page=l&category=1010 target=main> Art
</a>(<?php rows(1010); ?>) <br>
<h3 align=center><a href=showitems.php?page=l&category=1500 target=main
>Automotive (<?php rows(1500); ?>) </a x/h3>
<a href=showitems.php?page=l&category=1505 target=main>Automobilia
</a>(<?php rows(1505); ?>) <br>
<a href=showitems,php?page=l&category=1510 target=main>Classic &
Collectors</a>(<?php rows(1510); ?>) <br>
<a href=showitems.php?page=l&category=1515 target=main>Motorcycles
</a>(<?php rows(1515); ?>) <br>
<a href=showitems.php?page=l&category=1520 target=main>Parts & Accessories</a>(<?php rows(1520); ?>) <br>
<а href=showitems,php?page=l&category=1525 target=main>Tools </а> (<?php rows(1525); ?>) <br>
<a href=showitems,php?page=l&category=1530 target=main>Toys</a> (<?php rows(1530); ?>) <br>
<a href=showitems.php?page=l&category=1535 target=main>Vehicles
</a>(<?php rows(1535); ?>) <br>
<a href=showitems.php?page=l&category=1540 target=main>Other</a> (<?php rows(1540); ?>) <br>
<h3 align=center><a href=showitems.php?page=l&category=2000 target= main >Accessories & Clothes (<?php rows(2000); ?>)</a x/h3>
<a href=showitems.php?page=l&category=2005 target=main>Women</a> (<?php rows(2005); ?>) <br>
<a href=showitems,php?page=l&category=2010 target=main>Men </a> (<?php rows(2010); ?>) <br>
<a href=showitems,php?page=l&category=2015 target=main>
Children</a>(<?php rows(2015); ?>) <br>
<a href=showitems.php?page=l&category=2020 target=main>Baby </a> (<?php rows(2020); ?>) <br>
<a href=showitems.php?page=l&category=2025 target= main>Accessories</a>(<?php rows(2025); ?>) <br>
<a href=showitems,php?page=l&category=2030 target=main>Sport Wear </a>(<?php rows(2030); ?>) <br>
<a href=showitems,php?page=l&category=2035 target=main>Leather & Fur</a>(<?php rows(2035); ?>) <br>
<a href=showitems.php?page=l&category=2040 target=main>Shoes </a> (<?php rows(2040); ?>) <br>
<a href=showitems.php?page=l&category=2045 target=main>Other</a> (<?php rows(2045); ?>) <br>
<h3 align=center><a href=showitems.php?page=licategory=2500 target= main >Books (<?php rows(2500); ?>) </a x/h3>
<a href=showitems,php?page=l&category=2505 tar-
get=main>Bestsellers</a>(<?php rows(2505); ?>) <br>
<a href=showitems.php?page=l&category=2510 target=main>Braille
</a>(<?php rows(2510); ?>) <br>
<a href=showitems.php?page=l&category=2515 tar-
get=main>Children</a>(<?php rows(2515); ?>) <br>
<a href=showitems.php?page=l&category=2520 target=main>Classic
</a>(<?php rows(2520); ?>) <br>
<a href=showitems,php?page=l&category=2525 target=main>Comics</a> (<?php rows(2525); ?>) <br>
<a href=showitems,php?page=l&category=2530 target=main>Fiction
</a>(<?php rows(2530); ?>) <br>
<a href=showitems,php?page=l&category=2535 target=main> Food, Wine, Cooking </a>(<?php rows(2535); ?>) <br>
<а href=showitems,php?page=l&category=2540 target=main> Large Print </a>(<?php rows(2540); ?>) <br>
<a href=showitems,php?page=l&category=2545 target=main> Literature
</a>(<?php rows(2545); ?>) <br>
<a href=showitems.php?page=l&category=2550 target=main> Magazines
</a>(<?php rows(2550); ?>) <br>
<a href=showitems.php?page=l&category=2555 target=main> Non-Fiction </a>(<?php rows(2555); ?>) <br>
<a href=showiterns,php?page=l&category=2560 target=main> Other
Languages </a>(<?php rows(2560); ?>) <br>
<a href=showi terns.php?page=l&category=2565 target=main> Poetry
</a>(<?php rows(2565); ?>) <br>
<a href=showitems.php?page=l&category=2570 target=main> Rare &
Antique </a>(<?php rows(2570); ?>) <br>
<a href=showitems.php?page=l&category=2575 target=main> Reference Books </a>(<?php rows(2575); ?>) <br>
<a href=showiterns.php?page=l&category=2580 target=main> Textbooks & Education </a>(<?php rows(2580); ?>) <br>
<a href=showitems.php?page=l&category=2585 target=main> Travel, Reference & Education </a>(<?php rows(2590); ?>) <br>
<a href=showitems,php?page=l&category=2590 target=main> Other
</a>(<?php rows(2595); ?>) <br>
<h3 align=center><a href=showitems,php?page=l&category=3000 target=main > Business (<?php rows(3000); ?>)</a ></h3>
<a href=showitems,php?page=l&category=3005 target=main> Business & Office </a>(<?php rows(3005); ?>) <br>
<a href=showitems,php?page=l&category=3010 target=main> Holesale &
Bilk Quantities </a>(<?php rows(3010); ?>) <br>
<a href=showitems.php?page=l&category=3015 target=main>Real Estate
</a>(<?php rows(3015); ?>) <br>
<a href=showitems,php?page=l&category=3020 target=main> Tickets
</a>(<?php rows(3020); ?>) <br>
<a href=showitems,php?page=l&category=3025 target=main> Transportation </a>(<?php rows(3025); ?>) <br>
<a href=showitems,php?page=l&category=3030 target=main> Travel
</a>(<?php rows(3030); ?>) <br>
<a href=showitems.php?page=l&category=3035 target=main> Weddings
</a>(<?php rows(3035); ?>) <br>
<a href=showitems,php?page=l&category=3040 target=main> Other
</a>(<?php rows(3040); ?>) <br>
<h3 align=center><a href=showitems,php?page=l&category=3500 target=main > Collectibles (<?php rows(3500); ?>)</a x/h3>
<a href=showitems,php?page=l&category=3505 target=main> Advertising
</a>(<?php rows(3505); ?>) <br>
<а href=showitems.php?page=l&category=3510 target=main> Animals </a>(<?php rows(3510); ?>)<br>
<a href=showitems.php?page=l&category=3515 target=main> Autographs </a>(<?php rows(3515); ?>) <br>
<a href=showitems.php?page=l&category=3520 target=main> Kitchenware </a>(<?php rows(3520); ?>) <br>
<a href=showitems.php?page=l&category=3525 target=main> Memorabilia </a>(<?php rows(3525); ?>) <br>
<a href=showitems.php?page=l&category=3530 target=main> Novelties
</a>(<?php rows(3530); ?>) <br>
<a href=showitems.php?page=l&category=3535 target=main> Science & Nature </a>(<?php rows(3535); ?>) <br>
<a href=showitems.php?page=l&category=3540 target=main> Science Fiction </a>(<?php rows(3540); ?>) <br>
<a href=showitems.php?page=l&category=3545 target=main> Toys
</a>(<?php rows(3545); ?>) <br>
<a href=showitems.php?page=l&category=3550 target=main> Transportation </a>(<?php rows(3550); ?>) <br>
<a href=showitems.php?page=l&category=3555 target=main> Other </a>(<?php rows(3555); ?>) <br>
<h3 align=center><a href=showitems.php?page=l&category=4000 target=main > Computers (<?php rows(4000); ?>)</a x/h3>
<a href=showiterns.php?page=l&category=4005 Macintosh </a>(<?php rows(4005); ?>) <br>
target=main>
Apple,
<a href=showitems.php?page=l&category=4010 target=main> IBM Compatible </a>(<?php rows(4010); ?>) <br>
PC,
<a href=showitems,php?page=l&category=4015
</a>(<?php rows(4015); ?>) <br>
target=main>
Hosting
<a href=showiterns,php?page=l&category=4020
</a>(<?php rows(4020); ?>) <br>
target=main>
Domain Names
<a href=showitems.php?page=l&category=4025
</a>(<?php rows(4025); ?>) <br>
target=main>
Drives, Media
<a href=showiterns.php?page=l&category=4030 Peripherals </a>(<?php rows(4030); ?>) <br>
target=main>
Input/Output
<a href=showitems.php?page=l&category=4035
</a>(<?php rows(4035); ?>) <br>
target=main>
Monitors
<a href=showitems.php?page=l&category=4040
IT </a>(<?php rows(4040); ?>) <br>
target=main>
Networking &
<a href=showitems,php?page=l&category=4045 Hardware</a>(<?php rows (4045); ?>) <br>
target=main>
Other
<a href=showitems.php?page=l&category=4050
Supplies </a>(<?php rows(4050); ?>) <br>
target=main>
Printers &
<a href=showitems,php?page=l&category=4055
target=main>
Scanners
</a>(<?php rows(4055); ?>) <br>
<а href=showiterns.php?page=l&category=4060 target=main> Services </a>(<?php rows(4060); ?>) <br>
<a href=showitems,php?page=l&category=4065 target=main> Software
</a>(<?php rows(4065); ?>) <br>
<a href=showitems.php?page=l&category=4070 target=main> Computer Books </a>(<?php rows(4070); ?>) <br>
<h3 align=center> <a href=showiterns.php?page=l&category=4500 target=main > Electronics & Cameras (<?php rows(4500); ?>)</a x/h3>
<a href=showitems.php?page=l&category=4505 target=main> Audio
</a>(<?php rows(4505); ?>) <br>
<a href=showitems.php?page=l&category=4510 target=main> Calculators & Machines </a>(<?php rows(4510); ?>) <br>
<a href=showitems.php?page=l&category=4515 target=main> Photo Cameras
& Equipment </a>(<?php rows(4515); ?>) <br>
<a href=showitems.php?page=l&category=4520 target=main> Computers </a>(<?php rows(4520); ?>) <br>
<a href=showitems.php?page=l&category=4525 target=main> Phones
</a>(<?php rows(4525); ?>) <br>
<a href=showitems,php?page=l&category=4530 target=main>Video
</a>(<?php rows(4530); ?>) <br>
<a href=showitems.php?page=l&category=4535 target=main>Other
</a>(<?php rows(4535); ?>) <br>
<h3 align=center><a href=showitems,php?page=l&category=5000 target=main > Jewelry, Gems & Watches (<?php rows(5000); ?>)</a x/h3>
<a href=showiterns.php?page=l&category=5005 target=main> Beads, Amulets
</a>(<?php rows(5005); ?>) <br>
<a href=showitems.php?page=l&category=5010 target=main> Costume Jewelry </a>(<?php rows(5010); ?>) <br>
<a href=showitems.php?page=l&category=5015 target=main> Ethnic, Tribal Jewelry </a>(<?php rows(5015); ?>) <br>
<a href=showitems.php?page=l&category=5020 target=main>Fine Jewelry
</a>(<?php rows(5020); ?>) <br>
<a href=showiterns.php?page=l&category=5025 target=main> Hair Jewelry
</a>(<?php rows(5025); ?>) <br>
<a href=showiterns.php?page=l&category=5030 target=main> Designer
Jewelry </a>(<?php rows(5030); ?>) <br>
<a href=showitems.php?page=l&category=5035 target=main> Jewelry Boxes
</a>(<?php rows(5035); ?>) <br>
<a href=showitems.php?page=l&category=5040 target=main> Jewelry
Supplies </a>(<?php rows(5040); ?>) <br>
<a href=showitems,php?page=l&category=5045 target=main> Loose
Gemstones </a>(<?php rows(5045); ?>) <br>
<а href=showitems,php?page=l&category=5050 target=main> Men
</a>(<?php rows(5050); ?>) <br>
<a href=showitems,php?page=l&category=5055 target=main> Watches
</a>(<?php rows(5055); ?>) <br>
<h3 align=centerxa href=showitems,php?page=l&category=5500 target=main
>Home & Garden (<?php rows(5500); ?>)</a x/h3>
<a href=showitems,php?page=l&category=5505 target=main>Appliances
</a>(<?php rows(5505); ?>) <br>
<a href=showitems.php?page=l&category=5510 target=main> Food & Beverage </a>(<?php rows(5510); ?>) <br>
<a href=showitems,php?page=l&category=5520 target=main> Furnishings </a>(<?php rows(5520); ?>) <br>
<a href=showitems.php?page=l&category=5525 target=main> Housewares
</a>(<?php rows(5525); ?>) <br>
<a href=showitems.php?page=l&category=5530 target=main> Kitchen & Cooking </a>(<?php rows(5530); ?>) <br>
<a href=showitems.php?page=l&category=5535 target=main> Lawn & Garden </a>(<?php rows(5535); ?>) <br>
<a href=showitems.php?page=l&category=5540 target=main> Pet Supplies
</a>(<?php rows(5540); ?>) <br>
<a href=showitems.php?page=l&category=5545 target=main> Saunas, Pools
</a>(<?php rows(5545); ?>) <br>
<a href=showitems.php?page=l&category=5550 target=main> Real Estate
</a>(<?php rows(5550); ?>) <br>
<a href=showitems,php?page=l&category=5555 target=main> Services
</a>(<?php rows(5555); ?>) <br>
<a href=showiterns,php?page=l&category=5560 target=main> Textiles, Linens & Quilts </a>(<?php rows(5560); ?>) <br>
<a href=showitems,php?page=l&category=5565 target=main> Other
</a>(<?php rows(5565); ?>) <br>
<h3 align=centerxa href=showitems,php?page=l&category=6000 target=main > Money, Coins, Stamps (<?php rows(6000); ?>) </a ></h3>
<a href=showitems.php?page=l&category=6005 target=main> Coins </a>(<?php rows(6005); ?>) <br>
<a href=showitems.php?page=l&category=6010 target=main> Medals & Tokens </a>(<?php rows(6010); ?>) <br>
<a href=showitems.php?page=l&category=6015 target=main> Paper Money </a>(<?php rows(6015); ?>) <br>
<a href=showitems.php?page=l&category=6020 target=main> Stamps
</a>(<?php rows(6020); ?>) <br>
<a href=showitems.php?page=l&category=6025 target=main> Other
</a>(<?php rows(6025); ?>) <br>
<а href=showitems,php?page=l&category=6505 target=main>DVDs
</a>(<?php rows(6505); ?>) <br>
<a href=showitems.php?page=l&category=6510 target=main> Video Tapes
</a>(<?php rows(6510); ?>) <br>
<a href=showitems,php?page=l&category=6515 target=main> Disks
</a>(<?php rows(6515); ?>) <br>
<a href=showitems,php?page=l&category=6520 target=main> Equipment & Services </a>(<?php rows(6520); ?>) <br>
<a href=showitems.php?page=l&category=6525 target=main> Books
</a>(<?php rows(6525); ?>) <br>
<a href=showitems,php?page=l&category=6530 target=main>Tickets
</a>(<?php rows(6530); ?>) <br>
<a href=showitems,php?page=l&category=6535 target=main> Other</a>(<?php rows(6535); ?>) <br>
<a href=showitems,php?page=l&category=7005 target=main>
</a>(<?php rows(7005); ?>) <br>
CDs
<a href=showitems,php?page=l&category=7010
</a>(<?php rows(7010); ?>) <br>
target=main>
Tapes and Vinyl
<a href=showitems,php?page=l&category=7015
</a>(<?php rows(7015); ?>) <br>
target=main>
Tickets
<a href=showitems.php?page=l&category=7020 Equipment </a>(<?php rows(7020); ?>) <br>
target=main>
Instruments &
<a href=showitems,php?page=l&category=7025
</a>(<?php rows(7025); ?>) <br>
target=main>
Sheet Music
<a href=showitems.php?page=l&category=7030
</a>(<?php rows(7030); ?>) <br>
target=main>
Music Lessons
<a href=showitems,php?page=l&category=7035
</a>(<?php rows(7035); ?>) <br>
target=main>
Books
<a href=showitems,php?page=l&category=1040
</a>(<?php rows(7040); ?>) <br>
target=main>
DVDs
<a href=showitems,php?page=l&category=7045
</a>(<?php rows(7045); ?>) <br>
target=main>
Music Videos
<a href=showitems.php?page=l&category=7050
</a>(<?php rows(7050); ?>) <br>
target=main>
Magazines
<a href=showitems.php?page=l&category=7055
</a>(<?php rows(7055); ?>) <br>
target=main>
Other
<h3 align=centerxa href=showitems,php?page=l&category=7000 target=main >
/h3>
Music (<?php rows(7000); ?>)
<h3 align=center><a href=showitems.php?page=l&category=7500 target=main
>Sports (<?php rows(7500); ?>) . </a ></h3>
<а href=showitems,php?page=l&category=7520 target=main> Tickets </a>(<?php rows(7520); ?>) <br>
<h3 align=centerxa href=showitems.php?page=l&category=8000 target=main > Toys, Hobbies, Games (<?php rows(8000); ?>)</a x/h3>
<a href=showitems.php?page=l&category=8005
</a>(<?php rows(8005); ?>) <br>
target=main>
Baby Toys
<a href=showitems,php?page=l&category=8010
</a>(<?php rows(8010); ?>) <br>
target=main>
Dolls
<a href=showitems,php?page=l&category=8015
</a>(<?php rows(8015); ?>) <br>
target=main>
Games
<a href=showitems,php?page=l&category=8020
Crafts </a>(<?php rows(8020); ?>) <br>
target=main>
Hobbies &
<a href=showiterns,php?page=l&category=8025
</a>(<?php rows(8025); ?>) <br>
target=main>
Miscellaneous
<h3 align=centerxa href=showitems.php?page=l&category=8500 target=main > Other (<?php rows (8500); ?>)</a x/h3>
<a href=showitems.php?page=l&category=8505 target=main>Body Art, Tattoos
</a>(<?php rows(8505); ?>) <br>
<a href=showitems,php?page=l&category=8510 target=main> Costumes
</a>(<?php rows(8510); ?>) <br>
<a href=showitems,php?page=l&category=8515 target=main> Genealogy
</a>(<?php rows(8515); ?>) <br>
<a href=showitems.php?page=l&category=8520 target=main>Gifts & Party
Supplies </a>(<?php rows(8520); ?>) <br>
<a href=showitems.php?page=l&category=8525 target=main> Health &
Wellness </a>(<?php rows(8525); ?>) <br>
<a href=showitems.php?page=l&category=8530 target=main>Memberships
</a>(<?php rows(8530); ?>) <br>
<a href=showitems,php?page=l&category=8535 target=main> Metaphysical
</a>(<?php rows(8535); ?>) <br>
<a href=showitems,php?page=l&category=8540 target=main> Optics
</a>(<?php rows(8540); ?>) <br>
<a href=showitems.php?page=l&category=8545 target=main> Personal
Security </a>(<?php rows(8545); ?>) <br>
<a href=showitems,php?page=l&category=8550 target=main> Personalized, Customized </a>(<?php rows(8550); ?>) <br>
<a href=showitems.php?page=l&category=8555 target=main> Religious Products & Supplies </a>(<?php rows(8555); ?>) <br>
<a href=showitems,php?page=l&category=8560 target=main> Services
</a>(<?php rows(8560); ?>) <br>
<a href=showitems.php?page=l&category=8565 target=main> Shipping &
Packing Supplies </a>(<?php rows(8565); ?>) <br>
<a href=showitems,php?page=l&category=8570 target=main> Subscriptions
</a>(<?php rows(8570); ?>) <br>
<а href=showitems.php?page=l&category=8575 target=main> Show Supplies </a>(<?php rows(8575); ?>) <br>
<a href=showitems,php?page=l&category=8580 target=main> Uniforms
</a>(<?php rows(8580); ?>) <br>
<a href=showitems,php?page=l&category=8585 target=main> Other
</a>(<?php rows(8585); ?>) <br>
</html>
Этот файл состоит из ссылок на категории и подкатегории продаваемых товаров. Каждая ссылка содержит информацию о том, сколько единиц товара представлено к продаже в той или иной категории или подкатегории. Информация извлекается из базы данных. Это наиболее ресурсопотребляющий файл на сайте.
При переходе на страницу той или иной категории товаров по ссылке, мы видим список всех продаваемых товаров этой категории или подкатегории (рис. 10.12).
"3 ^Go Inks*"3 ^Go Inks*on «action auction auction muTo buyon «action auction auction muTo buy3 Olymp't Auction. W L L (, О М Е ! - Microsoft Internet Explorer
"3 ^Go Inks*
"3 ^Go Inks*
on «action auction auction mu
To buy
on «action auction auction mu
To buy
j Ffa JMT ViewF«y«ta Tools Help ~_
j'4»Beck V/»*". ^ iy Д ^Search QjFavorites (JTH*» i У)г tit §8 ’ У
|Acd.«s[®7http: //localhost/auction/
•on «action action «action «xtion auction me
To registerTo sell
Items from category 1000
photo?'-
item name
owner
bids
current price .
liutrid^tiniet^
Р
Krtiiia
user
№
400:00 €
2002-10-27 at 10:23:48
Р . '
rekordare ’ =
' user
(2)-
. -3.00€ ,
' 2005-04-25 at 01:12:25 ' •
4
Р
koleaso
• user . ■
(1)
15.00 €
2001-08-08 at 00:07:39
Р "
• K'artina ,
user
. 0)'.'
305.00.€,.
2001-08-20 at. 14:36:22 ■
Р
Karima
user
XD
350.00 €
2001-08-29 at 11:11:27
Рис. 10.12. Таблица продаваемых товаров данной категории или подкатегории
Таблица товаров отдельной категории или подкатегории выводится с помощью файла showitems.php.
| Файл showitems.php;
<?php
echo 1<htmlxheadxtitle>Item list</titlexbody bgcolor="#DDDDDD">1 ;
$c=mysql_connect("localhost:3306", "olymp", "ddeddd");
mysql_select_db("auction",$c);
$t=floor($category/100)*100;
$cat=$category+100;
if ($t==$category)($stroka= "select * from item where category > '".$category."' and category < ’".$cat."' and active ='l' order by misc;"; }
else ($stroka= "select * from item where category='".$category."' and active =4' order by misc;";};
$result = mysql_db_query("auction", $stroka);
$rows = mysql_num_rows ($result);
echo "Items from category ".$category."<hr>";
echo "<table border='0’ cellpadding=’3' width=100%>";
echo '<tr><td> photo </tdxtd> item name </tdxtd> owner </tdxtd> bids</td> <td> current price </td> <td>endinig time</tdx/tr>';
$i temspe rpage=25;
$itemcount=($page-l)*$itemsperpage;
$min=$itemcount;
$max=$min+$itemsperpage;
$pagescount=ceil($rows/$itemsperpage);
$colorl='#EEEEEE';
$color2='#DlDlDl' ;
$color=$color2 ;
$getcount=0;.
while($i = mysql_fetch_row($result)) (
if ($color == $colorl) ($color=$color2;} else ($color=$colorl;};
$getcount=$getcount+l;
$stringl="select * from event where id='".$i[0]."' order by" bamount;";
$resl = mysql_query($stringl);
$noro=mysql_num_rows($resl);
for ($kk=0; $kk < $noro; $kk++) {$ro=mysql_fetch_row ($resl);};
$price=$ro[ 5 ];
if ($getcount <= $max AND $min < $getcount) {
$secho= '<tr bgcolor=' .$color. 'Xtd>' ;
echo $secho;
$nor=$noro-l;
if ($i['9'] == 1) {$sout='<img src=photo. jpgx/td>';} else {$sout='</td>';};
$sout.= '<td><a href=itempresent.php?id=1.$i[0].'>'.$i[3].'</a>
</tdxtd>'.$i[2] . '</td> <tdxfont color="blue") > (' . $nor. 1) </fontx/td> <tdxfont color="blue">'.$price.' € ; </color></td> ' ;
$sout. =' <td> ' . $i [7 ] . ' at ' . $i [8] . '</tdx/tr>' ;
echo $sout;
};
};
echo '</table>';
$lm=$page-l;"
$la=$page+l;
if ($pagescount >1) {$gostring="<Pxhr><P> Go to page";} else
{$gostring="<Pxhr><P>Pages:"; } ;
if ($lm >0)$gostring.=" <a href=showitems.php?category=
".$category."&page=".$lm."> «< </a>. ";
for ($1=1; $1 <= $pagescount; $1++) {
if ($l==$page)($gostring.=' '.$1.' ';}
else($gostring.='<ahref=showitems.php?category=
'.$category.'&page='.$!.'> '.$1.'</a>';}
}
if ($la <= $pagescount)$gostring.=" <a href=showitems.php?category= ".$category."&page=".$la."> >» </a> ";
echo '<center>'.$gostring.'</center>';
echo ' </bodyx/html>';
Каждому товару в списке, представленном в виде таблицы, сопоставлена ссылка, перейдя по которой, мы попадаем на страницу, где представлена полная информация о товаре, включая картинку, приложенную продавцом (рис. 10.13).
Рис. 10.13. Информация о товаре
Информация о товаре выводится с помощью скрипта itempresent.php.
1 Файл itempresentphp
<?php
$Ydate = date("¥");
$Mdate = date("m");
$Ddate = date("d");
$Htime = date("G");
$Mtime = date("i");
$Stime = datefs"); $ip=$REMOTE_ADDR;
$c=mysql_connect("localhost:3306", "olymp", "ddeddd"); mysql_select_db("auction",$c);
$stringl="select * from event where id='".$id."' order by bamount;";
$resl = mysql_query($stringl);
$noro=mysql_num_rows($resl);
for ($kk=0; $kk < $noro; $kk++) ($ro=mysql_fetch_row ($resl);};
$price=$ro[5];
$priceincrement=round($price*0.01,2)+ 0.01;.
$newprice=$price+$priceincrement;
$sitem="select * from item where id=".$id.";";
$sevent="select * from event where id=".$id.";";
$resitem = mysql_query($sitem);
$ritem= mysql_fetch_array ($resitem);
$resevent = mysql_query($sevent) ;
$revent= mysql_fetch_array ($resevent);
// далее формируем HTML-текст для отправки клиенту echo '<html><head><title>01ymp Cockroaches Races AUCTION. Item '.$id.' </title></headxbody bgcolor="#FEF8C0">';
$outstring= '<div align=centerxfont size=-l>Item '.$ritem['id'].'</font> </divxhr><hl align=centerxfont color=blue><u><b> ' .$ritem[ 'iname' ] .
</bx/u></fontx/hl> ' ;
$outstring.='<Pxfont size=+l>'.$ritem['description'].'</font>';
$outstring. = '<hrxtable border="0" width="100%"Xtr><td width="40%" valign="middle" align="left"> Starting price: <font color=green> <b> ' . $ritem[ 'userprice' ] . ' €</bx/font>.</td>';
$outstring.='<td width="60%" valign="middle" align="left”>Seller: <font color=blue size=+l>',$ritem['login'].'</font> <P>Starting time for this item: '.$ritem['sdate'].' at '.$ritem['stime']. '<px/tdx/trxtr>' ;
$outstring.='<td width="40%" valign="middle" align="left">Current bidding price is <font size=+2 color=green>'.$price.'</fontxfont size=+l color=green> €</font>.</td>';
$bidder=$ro[' 1' ] ;
if ($ro['l'J == $ritem[' login' ]) $bidder='</fontxfont color=redxb>no bids placed or owner placed bid</b>';
$norol=$noro-l;
$outstring.='<td width="60%" valign="middle" align="left">Current winning bidder: <font size=+l color=maroon>'.$bidder.'</font>.';
$outstring.='<P>Bids placed: <font color=green size=+l>'.$norol.'</font>';
$outstring.=' <P>Current time: '.date("Y-m-d G:i:s").'.<br> Bidding time: ' . $ revent [ 'bdate' ] . ' at '.$revent['btime'].'.</tdx/tr><PXP>';
//$outstring.='<P>Bidding time: ',$revent['bdate'].' at
/ /' .$revent['btime'].'. <P>';
//Для windows
//$check=FALSE;
//$d=$ritem['edate'] — date ("Y-m-d"); $dd=$ritem['edate']; //$t=$ritem['etime'] — date ("G:i:s"); $tt=$ritem['etime']; //$e=$ritem['edate'] — date ("Y-n-d");
H^V ($d > 0) {$check=' 1';} else (if ($e == 0) {if($t > 0) ($check='1';}}};
//для Windows и для Unix
$check=FALSE;'
$timenow=mktime ($Htime,$Mtime,$Stime,$Mdate,$Ddate, $Ydate);
$compare=$ritem['misc']-$timenow;
//echo "<P>Difference ".$compare."<P>current timestamp
".$timenow."<P>From database ".$ritem['misc'];
if ($compare > 0) $check=TRUE;
//Вычисление времени, которое остается до окончания аукциона $stampleft=$ritem['misc']-$timenow;
$numdays=floor($stampleft/86400) ;
$stamphours=$stampleft-$numdays*86400;
$numhours=floor($stamphours/3600);
$stampminutes=$stamphours-$numhours*3600;
$numminutes=floor($stampminutes/60);
$stampseconds=$stampminutes-$numminutes* 60; $numseconds=$stampseconds;
$outstring.='<tr>';
if ($check) {
$outstring.='<td width="40%"x/tdxtd width="60%" valign="middle" align="left"> Ending time for this item: '.$ritem['edate'].' at ' .$ritem[ 'etime' ] . ' </tdx/trx/table>' ;
} else ($butstring. = '<td width="40%"x/tdxtd width="60%" valign="middle" align="left"> Ending time for this item: '.$ritem['edate'].' at '.$ritem['etime'].'. <font size=+l color=red> Auction has ended. </fontx/tdx/tr></tablexhr>'; } ;
if ($check){
$outstring. ='<Pxtable width="25%"xtrxtd>Time left: </tdxtdxfont size=+l color=maroon>' .$numdays. '</font> days</tdx/trxtrxtdx/tdxtd> <font size=+l color=maroon>'.$numhours.'</font> hours </tdx/trxtrxtdx/tdxtdxfont size=+l color=maroon>
' . $numminutes . '</font> minutes</tdx/trxtrxtdx/tdxtdxfont size= +1 color=maroon>' . $numseconds. ' </font> seconds </tdx/trx/tablexhr>';
$isphoto=$ritem['photo'];
if ($isphoto == 1){
$outstring.='<P><center><img src=./images/'.$ritem['id'].' border= 2x/centerxhr>' ;
}
$outstring.='<P>Bidding. <form action=bidding.php method="post">Your amount <font size=+l>(should be greater than <font size=+2 color=braun >'.$newprice.' €</font>)</font> <input type=text name="amount">.<P>';
$outstring.='<P>Your login name: <input type=text name="login"> and password: <input type=password name="password">,';
$outstring.='<P><input type=submit value="Place your bid"xinput type=hidden name="id" value=' ,$id. 'x/form>' ;
}
if ($check) {echo;} else (if ($ritem['active']=1) $string4="update item set active='2' where id=".$id.";";
$res4 = mysql_db_query ("frggrr", $string4);}
echo $outstring;
mysql_free_result($resitem);
mysql_free_result($resevent) ;
echo '</bodyx/html>';
?>
На этой странице мы можем указать свою цену на товар, ввести свои логин и пароль и зарегистрировать покупку (рис. 10.14). Если к моменту окончания аукциона никто не предложит более высокой цены, то пользователь окажется победителем аукциона. После того как мы ввели имя, пароль и свою цену, зарегистрируем покупку, нажав кнопку Place your bid. После этого в окно браузера через пару мгновений вновь будет загружена информация о том же самом товаре, но с учетом только что сделанного повышения цены (рис. 10.15).
Рис. 10.15. Обновленная информация о товаре
Новая цена и информация о пользователе передается скрипту bidding.php, который вносит новые записи в базу данных в таблицу event.
:т ••1
I Файл bidding.php=
<?php
$c=mysql_connect("localhost:3306", "olymp", "ddeddd"); mysql_select_db("auction",$c);
$date = date("Y-m-d");
Stime = date("G:i:s");
$ip=$REMOTE_ADDR;
$stringl="select * from user where login='".$login.'" and password= ' ".$password."';";
$resl = mysql_query($stringl);
$ruser= mysql_fetch_array ($resl);
$string2="select * from item where id='".$id."';";
$res2 = mysql_query($string2);
$ritem= mysql_fetch_array ($res2);
$string3="select * from event where id='".$id.'" order by bamount;";
$res3 = mysql_query($string3);
$noro=mysql_num_rows($res3);
for ($kk=0; $kk < Snoro; $kk++) {$ro=mysql_fetch_array ($res3);}; $price=$ro['bamount'];
$check=$ritem['edate'] >= date ("Y-m-d") and $ritem['etime'] > date ("G:i:s") and $ruser['active'] == '1';
$checkl=true;
if ($ruser['active'] <> 1) $checkl=false;
$priceincrement=$price*O.01;
$incremprice=$price+$priceincrement;
if ($incremprice > Samount OR Sprice == Samount) {echo "Your price is not correct";} else {
if (mysql_num_rows($resl) <>0) {
$string="insert into event values
(' 1', "'.$login."','".$id."', '".$date."','".$time."','".$amount."', * ".$ip. '",");";.
if ($check and $checkl) {$res = mysql_db_query("auction", Sstring);echo "Your bid has been registered.<script language=
'javascript'>document.location.href='itempresent,php?id=".$id."'</script> ";} else if($checkl) {mysql_query("update item set active='2' where
id='".$id."';"); echo "Auction for this item has ended. Please, return to the auction page.";} else echo "you are not completely registered, check your mail and finalize registration.";
} else {echo "password is incorrect";};
}
mysql_free_result($resl);
mysql_free_result($res2);
mysql_free_result($res3);
В разборе сайта с аукционом мы остановились на базовых функциях и не стали даже рассматривать работу с сессиями, которые очень полезны при работе с сайтом аукциона. Данный аукцион может быть приспособлен под различные нужды. Заинтересованные в приобретении или использовании аукциона могут обратиться с предложениями, оставив информацию на сайте http://www.e-olymp.com при регистрации или написав по адресу info@e-olymp.com. Отладочная версия сайта находится по адресу http://www.e-olymp.com.
Транспортная интернет-биржа
Транспортная интернет-биржа предназначена для сбора сведений о перевозчиках грузов, их заказчиков — владельцев грузов, отслеживания движения транспортных средств в реальном времени (обработка SMS-сообщений), отображение положения транспортных средств на карте в окне браузера. Полная программа включает в себя несколько модулей, в том числе базу данных о положении транспортных средств и грузов, которая пополняется путем обработки SMS-сообщений, двух серверов отображения местоположений на карте и обработки географических координат и адресов, географической и адресной баз данных, Web-сервера, выполняющего функциональную обработку запросов. Общий объем программного обеспечения довольно велик. Только для одной европейской страны (необходимо учитывать размер географических баз данных) дистрибутив занимает несколько гигабайт. Основной язык выполнения серверных заданий — VBScript. Сайт рассчитан на работу с Windows, рекомендуемая система — Windows 2000 Server, рекомендуемая конфигурация — два независимых компьютера, один вмещает в себя базы данных, второй служит для размещения Web-сервера.
Интернет-биржа состоит из следующих основных модулей:
сервер eLocate;
сервер eMap;
база географических данных;
база данных карт и координат;
база данных транспортных средств и товаров;
серверные программы Web-сервера."
Транспортная интернет-биржа заказана компанией для закрытия рыночной ниши отсутствующих программных продуктов в области сети Интернет,
поддерживающих транспортные компании и клиентов, обращающихся за услугами перевозчиков. Мы не будем подробно описывать структуру сайта, приведем лишь несколько примеров. Отметим, что развившийся в конце 2001 — начале 2002 года кризис привел к тому, что заказчик стал не в состоянии поддерживать приобретенное программное обеспечение, интерес к которому проявили конкуренты, в том числе крупнейшие европейские телекоммуникационные компании, такие, как T-systems. На основе существующего программного обеспечения могут быть созданы крупные распределенные или компактно реализованные транспортные интернет-системы как в западной Европе, так и в других регионах.
Сервер eMap
Автором сервера является компания, выпускающая программное обеспечение, из города Карлсруе (Германия). Сервер выводит географические карты в разном масштабе, отображает на картах графическую информацию, вводимую пользователем, которая берется из прилагаемой к серверу независимой базы данных.
Необходимо установить сервер и запустить его. Дистрибутив сервера занимает 17 Мбайт. Кроме сервера, необходимо установить базы данных карт. После установки карт необходимо внести изменения в файл eMapServer.ini. В нем необходимо указать местоположение карт не компьютере. Затем стартуем сервер. Если сервер стартовал успешно, в окне появятся соответствующие сообщения (рис. 10.16).
Можно запустить программу тестер и проверить работу сервера оттуда (рис. 10.17).
Рис. 10.17. Программа для тестирования работы сервера
После того как мы убедились, что еМар-сервер работает, напишем ASP- скрипт, в котором создадим экземпляр объекта для еМар-сервера. Но прежде всего необходимо правильно сконфигурировать сервер, задав параметры в файле global.asa, где необходимо верно указать пути к файлам географической базы данных и названия карт (соответствующих папок).
Серверные скрипты
Создаем файл eMapOlymp и помещаем его в папку сервера wwwroot/maps.
; Файл eMapOlymp.asp
<%@ EnableSessionState=False LANGUAGE="VBSCRIPT" %>
<% Response.Buffer = TRUE %>
' START
If (TRIM(Request("С")) о "") or (TRIM(Request("XY")) <> "") then MappingResult
else
StartForm
end if
' You can activate the Systemwork to delete all maps (*.gif) in the folder
' defined by -> Application("eMapServer_Physical-Path")
' ATTENTION: Be sure that the right path-variable is set
' Systemwork(Application("eMapServer_Physical-Path"))
Response.End
' END
%>
<%
Sub StartForm
%>
<html>
<head>
<title>eMap01ymp© Demo</title>
</head>
<body bgcolor=fef8c0>
<table border="0" cellspacing="l" cellpadding="l">
<tr>
<td colspan="3">
<img SRC="../auction/main.jpg" align="left" hspace="10" vspace= "0" WIDTH="179" HEIGHT="64">
<bxbr>eMapOlymp© <brxfont з£ге="-1">демонстрация cepBepa</bx/td>
</tr>
<tr><td colspan="3"xhrx/tdx/tr>
<! — 1,— >
<form action="eMapOlymp.asp" method="GET" id="forml" name="forml">
<tr>
<td colspan="3"xb>l.Показать область по 4 KOopflHHaTaM</td>
</tr>
<tr>
<td со!зрап="3"Жоординаты: <brxinput type="text" size=
"50" name="C" value="913946_6288708_969946_6246708"Xbr>
Формат:
"neBan"_"BepxHnn"_"npaBa4"_"нижняя& quot;(меркатор)
</td>
</tr>
<tr>
<td colspan="3" align="right"><input type="submit" value= "Показать карту" name="Button"x/td>
</tr>
</form>
<1—1.—>
<tr><td colspan="3"xhrx/tdx/tr>
<!—2,—>
<form action="eMapOlymp.asp" method™"GET" id="form2" name="form2">
<input type="hidden" name="LAY" value="Location">
<tr>
<td colspan="3"Xb>2. Показать область по 2 KOopwiHaTaM</td>
</tr>
<tr>
<td со1зрап="3"Жоординаты:<brxinput type="text" size="50" name™ "XY" value="933030_6269453"xbr>
Формат: "BepxHnn"_"npaBan" (меркатор)
</td>
</tr>
<tr>
<td colspan="3" align="right"xinput type="submit" value= "Показать карту" name="Button"x/td>
</tr>
</form>
<!—2.—>
<tr><td colspan="3"xhrx/tdx/tr>
<!— 3.— >
<form action="eMap01ymp.asp" method="GET" id="form2" name="form2">
<input type="hidden" name="LAY" value="Locations">
<tr>
<td colspan="3"xb>3. Показать область по одной координате и информации о соседних пунктах из внешней базы данных</РЬ>
</tr>
<tr>
<td со1зрап="3"Жоординаты: <brxinput type="text" size="50" name= "XY" value= " 933030_62 6 9 4 53 " xbr>
Формат: "BepxH44"_"npaBa4" (меркатор)
</td>'
</tr>
<tr>
<td colspan="3" align="right"xinput type="submit" value= "Показать карту" name="Button"x/td>
</tr>
</form>
<!— 3,— >
<tr><td colspan="3"xhrx/tdx/tr>
<!—4.—>
<form action="eMap01ymp.asp" method="GET" id="form2" name="form2">
<input type="hidden" name="LAY" value="TestDrive">
<tr>
<td colspan="3"xb>4. Показать область по двум координатам, а также адресную информацию </td>
</tr>
<tr>
<td со1зрап="3"Жоорданаты: <brxinput type="text" size="50" name= "XY" value="933030_6269453"xbr>
Формат: "BepxH44"_"npasa4" (меркатор)
</td>
</tr>
<tr>
<td colspan="3" align="right"Xinput type="submit" value= "Показать карту" name="Button"x/td>
</tr>
</form>
<!—4.—>
<tr><td colspan="3 "xhrx/tdx/tr>
</table>
</body>
</html>
<%
end sub
%>•
Sub MappingResult
if Application("eServer_ApplicationRunning") = "" then
Response.Write("ERROR ASP -> No application defined or application not running!")
Response.End
end if
Set MapObj = CreateObject("MapRequestObj.MapRequest")
MapObj.ServerAddr = Application("eMapServer_Server-IP")
MapObj.MapName = Application("eMapServer_Server-Map")
MapObj.SendTimeOut = 10
MapObj.ReceiveTimeOut = 60
MapObj.CoordFormat = 0
LAYER-REQUEST = Trim(Request("LAY"))
RECT_ACTION = Replace(Trim(Request("ACT")),"_",chr(164))
MapObj.CoordParams = RECT_ACTION
RECT_REQUEST = Trim(Request("C"))
RECT_ARRAY = Split(Trim(Request("XY")),"_")
If RECT_REQUEST = "" then
RECT_REQUEST = RECT_ARRAY(0) - 1000 & "_" & RECT_ARRAY(1) + 1000 & "_" & RECT_ARRAY(0) + 1000 & "_" & RECT_ARRAY(1) - 1000
End If
If UBound(RECT_ARRAY) > 0 then
If LAYER_REQUEST = "Location" then
MapObj.ShowLayer = "Locations" & chr(183) & "1" & chr(183) & chr(183) & "1" & _
chr(183) & CLng(RECT_ARRAY(0)) & chr(183) & CLng(RECT_ARRAY(1)) & chr (183) & "location.bmp" & chr (183) & "Location"
Elself LAYER_REQUEST = "Locations" then.
MapObj.ShowLayer = "Locations" & chr(183) & "1" & chr(183) & chr(183) & "5" & _
chr(183) & CLng(RECT-ARRAY(0)) & chr(183) & CLng(RECT_ARRAY(1)) & chr(183) & "location.bmp" & chr(183) & "Location" & _
chr(183) & CLng(RECT_ARRAY(0)) - 500 & chr(183) &
CLng(RECT_ARRAY(1)) - 500 & chr(183) & "dealer.bmp" & chr(183) & "Dealer 1" & _
chr(183) & CLng(RECT_ARRAY(0)) + 250 & chr(183) &
CLng(RECT_ARRAY(1)) - 500 & chr(183) & "dealer.bmp" & chr(183) & "Dealer 2" & _
chr(183) & CLng(RECT_ARRAY(0)) - 150 & chr(183) &
CLng(RECT_ARRAY(1)) + 100 & chr(183) & "dealer.bmp" & chr(183) & "Dealer 3" & _
chr(183) & CLng(RECT_ARRAY(0)) + 250 & chr(183) &
CLng(RECT_ARRAY(1)) - 100 & chr(183) & "dealer.bmp" & chr(183) & "Dealer 4"
elseif LAYER_REQUEST = "TestDrive" then
MapObj.ShowLayer = "AdrMon TestDrive" & chr(183) & "1" end if end if
MapObj.Rect = Replace(RECT_REQUEST,"_",chr(164))
MapObj.ImageSize = "400" & chr(166) & "300"
MAPFILENAME = GetUniqueFileName("eMapServer") & ".gif"
MapObj.FileName = Application("eMapServer_Physical-Path") & MAPFILENAME
STATUS = MapObj.MapRequest
If UBound(RECT_ARRAY) > 0 then
If LAYER_REQUEST = "Location" or LAYER_REQUEST = "Locations" then DEVICE_STR = MapObj.DeviceCoordinates("Locations")
elseif LAYER_REQUEST = "TestDrive" then
DEVICE_STR = MapObj.DeviceCoordinates("AdrMon TestDrive") end if
DEVICE_OBJ = Split(DEVICE_STR,chr(183))
For I = 0 to DEVICE_OBJ(0) - 1
IMAGEMAP_INFO = IMAGEMAP_INFO & "<area shape=""circle"" coords=' IMAGEMAP_INFO = IMAGEMAP_INFO & DEVICEJOBJ((I * 7) + 1) & ", " IMAGEMAP_INFO = IMAGEMAP_INFO & DEVICE_OBJ((I *7) +2) & "," IMAGEMAP_INFO = IMAGEMAP_INFO & "11"" href=
""eMapServerImageMapTest.asp?ID=" & DEVICE_OBJ((I * 7) + 7) & "&NAME=" & DEVICE_OBJ((I * 7) + 5) & """ target=""_new"" title=""" &
DEVICE_OBJ((I * 7) + 5) & ’>" & chr(10)
next
end If
RECT_REQUEST_BACK = MapObj.Rect RESP = MapObj.Response
Set MapObj = nothing
if STATUS <> 0 then
Response.Write("STATUS eMapServer -> " & STATUS & " RESP:" & RESP & " IP:" & Application("eMapServer_Server-IP"))
Response.End end if
/
BaseURL = "eMapOlymp.asp?C=" & Replace(RECT_REQUEST_BACK,chr(164),"_") & "&XY=" & Trim(Request("XY")) & "&LAY=" & LAYER_REQUEST
ZoomlN=BaseURL&"&ACT=70_0_0"
ZoomOUT=BaseURL&"&ACT=200_0_0"
MoveW=BaseURL&"&ACT=100_-70_0"
MoveNW=BaseURL&"&ACT=100_-70_70"
MoveN=BaseURL&"&ACT=100_0_70"
MoveNE=BaseURL&"&ACT=100_70_70"
MoveE=BaseURL&"&АСТ=100_70_0"
MoveSE=BaseURL&"&ACT=100_70_-70"
Moves=BaseURL&"&ACT=100_0_-70"
MoveSW=BaseURL&"&ACT=100_-70_-70"
%>
<html>
<head>
<title>eMapOlymp© Demo</title>
<script LANGUAGE="JavaScript"> function chimg(imgname, action){ //Событие onmouseover — изменение рисунка mapimagespath = 'images/eMapServer/' document[imgname],src = mapimagespath + imgname + '_' + action + '.gif';
document[imgnamet'1'].src = mapimagespath + action + '.gif';
document[imgnamet'2'].src = mapimagespath + action + '.gif'; }
</script>
<script LANGUAGE="JavaScriptl.1">
// предварительная загрузка рисунков mapimagespath = 'images/eMapServer/'■
pic = new Array();
pic[l] = new Image();
pic[l].src = mapimagespath + 'arr_n_on.gif;
pic[2] = new Image();
pic[2].src = mapimagespath + 'arr_nw_on.gif;
pic[3] = new Image();
pic[3].src = mapimagespath + 'arr_w_on.gif;
pic[ 4 ] = new Image();
pic[4].src = mapimagespath + 'arr_sw_on.gif;
pic[5] = new Image();
pic[5] .src = mapimagespath + 'arr_s_on.gif; '
pic[6] = new Image();
pic[6].src = mapimagespath + 'arr_se_on.gif;
pic[7] = new Image();
pic[7].src = mapimagespath + 'arr_e_on.gif;
pic[ 8 ] = new Image();
pic[8].src = mapimagespath + 'arr_ne_on.gif;
</script>
c/head>
cbody bgcolor=fef8c0>
ctable border="0" cellspacing="l" cellpadding="l">
ctr>
<td colspan="3">
cimg SRC="../auction/main.jpg" align="left" hspace="10" vspace= "0" WIDTH="179" HEIGHT="64">
cbxbr>eMapOlymp© <brxfont з12е="-1">демонстрация cepBepac/bx/td>
</tr>
ctrxtd colspan="3"xhrx/tdx/tr>
ctr>
ctd>
ctable border="0" cellpadding="0" cellspacing="0" width="438">
ctr>
<td align="right"xa href="<%=ZoomIN%>"ximg SRC="images/eMapServer/ zoomin.gif" border="0" WIDTH="27" HEIGHT="27"x/td>
<td align="left"Xa href="<%=ZoomIN%>"xb>Увeличить</td>
<td align="right"xa href="<%=ZoomOUT%>"ximg SRC="images/eMapServer/ zoomout.gif" border="0" WIDTH="27" HEIGHT="27"x/td>
<td align="left"><a Нге1="<%=Зоот0ит%>"хЬ>Уменьшить</ЬЬ>
</tr>
</table>
</td>
</tr>
<tr>
<td>
Ctable BORDER="0" CELLSPACING="0" CELLPADDING="0" WIDTH="438">
ctr>
ctd>
Ctable BORDER="0" CELLSPACING="0" CELLPADDING="0">
ctr>
ctd BGCOLOR="#lc2f75"xa href="c%=MoveNW%>" onmouseout=
"chimg('arr_nw','off'); window.status='';return true;" onmouseover= "chimg('arr_nw','on'); window.status=''; return true;"ximg SRC= "images/eMapServer/arr_nw_off.gif" height="18" width="18" border= "0" name="arr_nw"x/ax/td>
<td BGCOLOR="#lc2f75"><a href="<%=MoveNW%>" onmouseout-
"chimg('arr_nw','off'); window.status-'';return true;" onmouseover- "chimg('arr_nw','on'); window.status-''; return true;"ximg SRC- "images/eMapServer/off.gif" width-"92" height="18" border="0" name= "arr_nwl"x/ax/td>
<tdximg SRC="images/eMapServer/split_vert.gif" height="18" width-
"1" border="0"x/td>
<td BGCOLOR="#lc2f75"Xa href="<%=MoveN %>" onmouseout-
"chimg('arr_n','off'); window.status-'';return true;" onmouseover-
"chimg('arr_n','on'); window.status-''; return true;"ximg SRC- "images/eMapServer/off.gif" border="0" width="98" height="18" name- "arr_nl"x/ax/td>
<td BGCOLOR="#lc2f75"><a href="<%=MoveN %>" onmouseout-
"chimg('arr_n','off'); window.status—'';return true;" onmouseover-
"chimg('arr_n','on'); window.status-''; return true;"ximg SRC- "images/eMapServer/arr_n_off.gif" height="18" width="18" border="0" name- "arr_n"x/a></td>
<td BGCOLOR="#lc2f75"><a href="<%=MoveN %>" onmouseout-
"chimg('arr_n','off'); window.status-'';return true;" onmouseover=
"chimgt'arr_n','on'); window.status=''; return true;"ximg SRC= "images/eMapServer/off.gif" border="0" width="98" height="18" name= "arr_n2"x/ax/td>
<tdximg SRC="images/eMapServer/split_vert.gif" border="0" WIDTH=
"1" HEIGHT="18"x/td>
<td BGCOLOR="#lc2f75"Xa href="<%=MoveNE%>" onmouseout=
"chimg('arr_ne','off'); window.status='';return true;" onmouseover= "chimg('arr_ne','on'); window.status=''; return true;"ximg SRC= "images/eMapServer/off.gif" height="18" width="92" border="0" name= "arr_nel"x/ax/td>
<td BGCOLOR="#lc2f75"><a href="<%=MoveNE%>" onmouseout=
"chimg('arr_ne','off'); window.status='';return true;" onmouseover=
"chimg('arr_ne','on'); window.status=''; return true;"ximg SRC= "images/eMapServer/arr_ne_off.gif" height="18" width="18" border= "0" name="arr_ne"x/ax/td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<table BORDER="0" CELLSPACING="0" CELLPADDING="0">
<tr>
<td>
ctable border="0" cellspacing="0" cellpadding="0">
<tr><td BGCOLOR="#lc2f75"xa href="<%=MoveNW%>" onmouseout=
"chimg('arr_nw','off'); window.status-'';return true;" onmouseover- "chimg('arr_nw','on'); window.status-''; return true;"ximg SRC=
"images/eMapServer/off.gif" width="18" height="70" border="0" name= "arr_nw2 "x/ax/tdx/tr>
<trxtdximg SRC="images/eMapServer/split_horiz.gif" border= "0" WIDTH="18" HEIGHT="l"X/tdx/tr>
<trxtd BGCOLOR="#lc2f75"xa href="<%=MoveW %>" onmouseout= "chimg('arr_w', 'off'); window.status='';return true;" onmouseover= "chimg('arr_w','on'); window.status=''; return true;"ximg SRC= "images/eMapServer/off.gif" width="18" height="70" border="0" name= "arr_wl"x/ax/tdx/tr>
<trxtd BGCOLOR="#lc2f75"Xa href="<%=MoveW %>" onmouseout= "chimg('arr_w','off'); window.status='';return true;" onmouseover= "chimg('arr_w','on'); window.status=''; return true;"ximg SRC= "images/eMapServer/arr_w_off.gif" height="18" width="18" border="0" name= "arr_w"x/ax/tdx/tr>
<trxtd BGCOLOR="#lc2f75"Xa href="<%=MoveW %>" onmouseout= "chimg('arr_w','off'); window.status='';return true;" onmouseover= "chimg('arr_w','on'); window.status=''; return true;"ximg SRC= "images/eMapServer/off.gif" width="18" height="70" border="0" name= "arr_w2"x/ax/tdx/tr>
<trxtdximg SRC="images/eMapServer/split_horiz.gif" border= "0" WIDTH="18" HEIGHT="l"x/td></tr>
<trxtd BGCOLOR="#lc2f75"Xa href="<%=MoveSW%>" onmouseout= "chimg('arr_sw','off'); window.status='';return true;" onmouseover= "chimg('arr_sw','on'); window.status=''; return true;"ximg SRC= "images/eMapServer/off.gif" width="18" height="70" border="0" name= "arr_swl"x/ax/tdx/tr>
</table>
</td>
<td COLSPAN="5"ximg SRC="<%=Application("eMapServer_URL-Path")%> <%=MAPFILENAME%>" height="300" width="400" border="0" align= "absmiddle" hspace="0" vspace="0" usemap="Showcase.asp#im" name= "map"></td>
<td>
<table border="0" cellspacing="0" cellpadding="0">
<tr><td BGCOLOR="#lc2f75"Xa href="<%=MoveNE%>" onmouseout= "chimg('arr_ne','off'); window.status='';return true;" onmouseover= "chimg('arr_ne','on'); window.status=''; return true;"ximg SRC= "images/eMapServer/off.gif" width="18" height="70" border="0" name= "arr_ne2"x/a></tdx/tr>
<trxtdximg SRC="images/eMapServer/split_horiz.gif" border= "0" WIDTH="18" HEIGHT="l"x/tdX/tr>
<trxtd BGCOLOR="#lc2f75"Xa href="<%=MoveE %>" onmouseout= "chimg('arr_e','off'); window.status='';return true;" onmouseover= "chimg('arr_e','on'); window.status=''; return true;"ximg SRC= "images/eMapServer/off.gif" width="18" height="70" border="0" name= "arr_el"x/ax/tdx/tr>
<trxtd BGCOLOR="#lc2f75"Xa href="<%=MoveE %>" onmouseout= "chimg ('arr_e','off'); window.status='';return true;" onmouseover=
"chimg('arr_e','on'); window.status=''; return true;"ximg SRC= "images/eMapServer/arr_e_off.gif" width="18" height="18" border="0" name= "arr_e"x/a></tdx/tr>
<trxtd BGCOLOR="#lc2f75"Xa href="<%=MoveE %>" onmouseout= "chimg('arr_e','off); window.status='';return true;" onmouseover= "chimg('arr_e','on'); window.status=''; return true;"ximg SRC= "images/eMapServer/off.gif" width="18" height="70" border="0" name= "arr_e2"x/ax/tdx/tr>
<trxtdximg SRC="images/eMapServer/split_horiz.gif" border= "0" WIDTH="18" HEIGHT="l"x/tdx/tr>
<trxtd BGCOLOR="#lc2f75"Xa href="<%=MoveSE%>" onmouseout= "chimg('arr_se','off'); window.status='';return true;" onmouseover= "chimg('arr_se','on'); window.status=''; return true;"ximg SRC= "images/eMapServer/off.gif" width="18" height="70" border="0" name= "arr_sel"x/a></tdx/tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<table BORDER="0" CELLSPACING="0" CELLPADDING="0">
<tr>
<td BGCOLOR="#lc2f75"xa href="<%=MoveSW%>" onmouseout=
"chimg('arr_sw','off'); window.status='';return true;" onmouseover= "chimg('arr_sw','on'); window.status=''; return true;"ximg SRC= "images/eMapServer/arr_sw_off.gif" height="18" width="18" border= "0" name="arr_sw"x/ax/td>
<td BGCOLOR="#lc2f75"><a href="<%=MoveSW%>" onmouseout=
"chimg('arr_sw','off'); window.status='';return true;" onmouseover= "chimg('arr_sw','on'); window.status=''; return true;"ximg SRC= "images/eMapServer/off.gif" height="18" width="92" border="0" name= "arr_sw2"x/ax/td>
<td><img SRC="images/eMapServer/split_vert.gif" border="0" WIDTH="1" HEIGHT="18"x/td>
<td BGCOLOR="#lc2f75"xa href="<%=MoveS %>" onmouseout=
"chimg('arr_s','off'); window.status='';return true;" onmouseover= "chimg('arr_s','on'); window.status=''; return true;"ximg SRC= "images/eMapServer/off.gif" border="0" width="98" height="18" name= "arr_sl"x/a></td>
<td BGCOLOR="#lc2f75"xa href="<%=MoveS %>" onmouseout=
"chimg('arr_s','off'); window.status='';return true;" onmouseover= "chimg('arr_s','on'); window.status=''; return true;"ximg SRC= "images/eMapServer/arr_s_off.gif" height="18" width="18" border= "0" name="arr_s"x/a></td>
<td BGCOLOR="#lc2f75"xa href="<%=MoveS %>" onmouseout=
"chimg('arr_s','off); window.status='';return true;" onmouseover= "chimg('arr_s','on'); window.status=''; return true;"ximg SRC= "images/eMapServer/off.gif" border="0" width="98" height="18" name= "arr_s2"x/ax/td>
<tdximg SRC="images/eMapServer/split_vert.gif" border="0" WIDTH="1" HEIGHT="18"X/td>
<td BGCOLOR="#lc2f75"Xa href="<%=MoveSE%>" onmouseout=
"chimg('arr_se','off'); window.status='';return true;" onmouseover=
"chimg('arr_se','on'); window.status=''; return true;"ximg SRC= "images/eMapServer/off.gif" height="18" width="92" border="0" name= "arr_se2"x/ax/td>
<td BGCOLOR="#lc2f75"Xa href="<%=MoveSE%>" onmouseout=
"chimg('arr_se','off'); window.status='';return true;" onmouseover= "chimg('arr_se','on'); window.status=''; return true;"ximg SRC= "images/eMapServer/arr_se_off.gif" height="18" width="18" border= "0" name="arr_se"x/ax/td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<trxtd colspan="3"xhrx/tdx/tr>
<trxtd colspan="3"><a href="eMap01ymp.asp">Ha3afl к форме . . ,</tdx/tr>
</table>
<!—Imagemap—>
<map name="im">
<%=IMAGEMAP_INFO%>
</map>
<!—Imagemap—>
</body>.
</html>
<%
end sub
%>
<%
Private Function GetUniqueFileName(FilePrefix)
Datum = Date ()
Zeit = Time()
Obergrenze = 100000.
Untergrenze = 1000
Randomize
RandomNr = Int((Obergrenze — Untergrenze + 1) * Rnd + Untergrenze)
GetUniqueFileName = FilePrefix & "_" & RandomNr & "_" & Hour(Zeit) & "-" & Minute(Zeit) & "-" & Second(Zeit) & "_" & Day(Datum) & "-" & Month(Datum) & "-" & Year(Datum)
End Function
%>
Sub Systemwork(MAPPATH)
TimeDifference = 1
If DateDiff("s",Application("SystemWorkTimeStamp"),Now()) > TimeDifference then
Application("SystemWorkTimeStamp") = Now()
Set fso = CreateObject("Scripting.FileSystemObject") Set f = fso.GetFolder(MAPPATH) Set fc = f.Files For Each fl in fc
If ((Right(UCase(fl.name),4) = ".GIF") and (DateDiff("s",fl.DateCreated,Now()) > TimeDifference)) then fso.deletefile MAPPATH & fl.name end if
Next
Set fso = nothing
Set f = nothing
Set fc = nothing end if End sub %>
Этот файл включает в себя различные фрагменты, которые могли бы быть записаны в самостоятельных файлах. В нашей версии все они сведены в один общий файл.
ЛЛоказать область по 4 координатам. ■'
Координаты: .:■ ■' '■ ■.
Формат:‘лсвая,_*всрхняя,_еправая*_,'нижняя,(мерхдтор)
Псмип карту |
Показать область по 2 координатам'
Координаты: ■ , .
|933030_6269453:
Формат; 'верхнмя'.'правая' (меркатор) '.
Показать область по одной координате и информации о соседних пунктах из внешней базы данных Координаты;
|933030_6269453•
Формат: ’верхкалн^'правая* (меркатор)
Похееть харту
4. Показать область по двум коордитнатам, а также адресную информацию Координаты:
Рис. 10.18. Форма для ввода координат
Рис. 10.19. Карта по указанным координатам
В окне браузера после загрузки файла eMapOlymp.asp, расположенного на сервере, увидим форму (рис. 10.18), в которую введем координаты в установленном формате (формат описан в документации по серверу).
После ввода координат (можно оставить координаты, указанные по умолчанию) в окне появится карта (рис. 10.19).
Карту можно выводить в разном масштабе (рис. 10.20). Скрипт также позволяет перемещаться по карте.
Рис. 10.20. Изменение масштаба карты
Транспортная биржа может быть полезна не только как коммерческая база данных перевозчиков и владельцев грузов, но и как географический online- справочник.
Приложение 1
Элементы HTML
Элементы формирования структуры HTML-документа
<HTML>
Этот элемент является контейнером. Указывает, что документ является HTML-документом.
Атрибуты отсутствуют.
Пример■
<HTML>... все содержимое HTML-страницы помещается здесь... </HTML>
<HEAD>
Этот элемент является контейнером. Описывает заголовок HTML-документа. <HEAD>... </HEAD> Атрибуты отсутствуют.
Пример
<HTML>■
<HEAD>'
... заголовок документа... </HEAD>
... прочие элементы HTML-страницы...
</HTML>
<BASE>
Самостоятельный элемент (не контейнер). Задает базовый URL.
<BASE HREF="base_url">
<BASE TARGET="frame_name">
Атрибуты:
HREF;
TARGET.
Примерi
<HEAD>
<BASE HREF="http://www.whatever.com/index.html">
<BASE TARGET="yourframe">
</HEAD>
<ISINDEX>
Самостоятельный элемент (не контейнер).
<ISINDEX PROMPT="Please enter the value to search for.">
l|li®M|i|i|liii|iliii|IM^
<HEAD>
<ISINDEX PROMPT="Enter the last name of the employee you want to search for:">
</HEAD>
Этот элемент использовался тогда, когда еще не было элемента <form>, с его помощью сервер получал пользовательскую информацию.
<МЕТА>
Самостоятельный элемент (не контейнер). Содержит мета-информацию.
<МЕТА HTTP-EQUIV="header" CONTENT="value">
ИЛИ
<МЕТА NAME="name" CONTENT="value">
Атрибуты:
HTTP-EQUIV;
NAME (AUTHOR, KEYWORDS, GENERATOR, DESCRIPTION);
□ SCHEME;
□ CONTENT.
|||||^е|!|||||1|||8|||Я
<HEAD>
<!— The first <META> tag instructs the browser to load a new page after 10 seconds. —>
<!— This is useful for creating a splash screen effect. —>
<META HTTP-EQUIV="Refresh" CONTENT="10, URL=http://www.myserver.com/ index2.html">
<!— The remaining <META> tags specify author and keyword information. —
<META NAME="AUTHOR" CONTENT="Eric Ladd">
<META NAME="KEYWORDS" CONTENT="Main page, welcome, neat stuff">
</HEAD>
<UNK>
Самостоятельный элемент (не контейнер).
Задает связь между файлами.
<LINK HREF="url_of_linked_file" TITLE="title"
REL="forward_relationship" REV="reverse_relationship">
Атрибуты:
HREF;
TITLE;
REL;
REV.
Значения rel и rev приведены в табл. П1.1.
Табл. ГН. 1. Значения атрибутов rel и rev
ЗначениеПояснение
CopyrightСтраница с описанием copyright
GlossaryСтраница описания терминов
Табл. П1.1 (окончание)
Значение
Пояснение
Help
Страница помощи-подсказки
Home
Домашняя страница сайта
Index
Указатель сайта
URL на e-mail автора
Next
Следующая страница сайта
Previous
Предыдущая страница сайта
Stylesheet
Файл с описанием стилей
TOC
Содержание сайта
up
Вышестоящая страница в иерархии сайта
j Пример ■■
<HEAD>
<LINK HREF="/style/styles.css" REL="Stylesheet">
CLINK HREF="/index.html" REL="Home">
<LINK HREF="/help.html" REL="Help">
<LINK HREF="back_one.html" REV="Next"
</HEAD>.
<SCRIPT>
Этот элемент является контейнером. Содержит код скрипта или ссылку на скрипт.
<SCRIPT LANGUAGE="scripting_language">
... script code goes here...
</SCRIPT>
Атрибуты:
DEFER — скрипт будет/не будет создавать содержимое документа;
LANGUAGE;
SRC — URL скрипта, если он не выписан внутри HTML-страницы;
TYPE.
jПример
<SCRIPT LANGUAGE="VBScript">.
Sub ScriptEx '
document.write("<HR>")
document.write("<H1 ALIGN=CENTER>Thank you for your submission!</Hl>") document.write("<HR>")
</SCRIPT>
<STYLE>
Этот элемент является контейнером.
<STYLE TYPE="mime_type" MEDIA="media_type" TITLE="title"> ... информация о стилях... </STYLE>
Атрибуты: □ MEDIA; □ TITLE; □ TYPE.■
Пример
<STYLE TYPE="text/cssl"> <! —
BODY {font: 10 pt Palatino; color: silver margin-left: 0.25 in} Hl (font: 18 pt Palatino; font-weight: bold) H2 (font: 16 pt Palatino; font-weight: bold}
P (font: 12 pt Arial; line-height: 14 pt; text-indent: 0.25 in}
</STYLE>
<TITLE>
Этот элемент является контейнером.
<TITLE>... заголовок документа... </TITLE>
Заголовок выводится на верхней панели окна браузера.
Атрибуты отсутствуют.
МрйЖр111ДЯИН1В
<TITLE>
The Advantages of a Corporate Web Site
</TITLE>
<BODY>
Этот элемент является контейнером.
Содержит тело HTML-документа.
<BODY BGCOLOR="background_color" BACKGROUND="background_irnage" LINK="unvisited_link_color" ALINK="active_link_color"
VLINK="visited_link_color" TEXT="text_color">
...ярлыки HTML, описывающие тело документа ...
</BODY>
Атрибуты:
ALINK;
BACKGROUND;
BGCOLOR;
LINK;
TEXT;
VLINK.
: Пример
<BODY BGCOLOR="white" TEXT="#FF0088" LINK="#DD0F00" VLINK="#00FF9A">
... все содержимое HTML-документа...
</BODY>
Некоторые элементы помещаются в элементе < head>:
<HTML>
<HEAD>
<TITLE>Document Template</TITLE>
... <META>, <BASE>, <LINK>, <SCRIPT>, <STYLE>, <ISINDEX> tags...
</HEAD>
<BODY>
... элементы тела документа...
</BODY>
</HTML>
Элементы форматирования текста
Далее приводятся элементы форматирования шрифта.
<в>
Этот элемент является контейнером.
Текст выводится полужирным шрифтом.
<В>... этот текст будет полужирным... </В> Атрибуты отсутствуют.
Пример
<В>Внимание!</В>
<BASEFONT>
Самостоятельный элемент (не контейнер). Задает свойства основного шрифта.
<BASEFONT SIZE="size" COLOR="color" FACE="list_of_typefaces"> Атрибуты:
COLOR;
FACE; □ SIZE.
Пример.
<BASEFONT SIZE=5 COLOR="navy" FACE="Arial,Helvetica,Times">
<BIG>
Этот элемент является контейнером.
Выделяет текст крупным шрифтом.
<BIG>... этот текст пишется крупными буквами... </BIG> Атрибуты отсутствуют.
|8|ЙйеВ|||1|||||^
Это <В1С>очень важно</В1С> прочитать!
<FONT>
Этот элемент является контейнером.
Задает параметры шрифта.
<FONT SIZE="size" COLOR="color" FACE="list of typefaces"> ... текст с заданными параметрами ...
</FONT>
<l>
Этот элемент является контейнером.
Выводит текст курсивом.
1>... этот текст будет показан курсивом... </!>
Атрибуты отсутствуют.
1 Пример
Моя любимая газета <1>"Коммерсант"</1>.
<S>, <STRIKE>
Эти элементы являются контейнерами.
Выводят перечеркнутый текст.
<S>... этот текст будет перечеркнут... </S>
ИЛИ
<STRIKE>... этот текст будет перечеркнут... </STRIKE>
Атрибуты отсутствуют.
| Пример•
Далее следующий текст выглядит, как перечеркнутый : <5>мы удалили этот фрагмент</5>.
<SMALL>
Этот элемент является контейнером.
Выводит текст мелким шрифтом.
<SMALL>... этот текст будет выведен мелким шрифтом... </SMALL>
Атрибуты отсутствуют.
ГПример-'■’ 1 |
Это едва заметное примечание <5МАЬВ>записано мелким шрифтом</5МАЪЬ> для меньшей убедительности!
<SUB>
Этот элемент является контейнером.
Текст выводится в виде нижнего индекса.
<SUB>... этот текст выводится как нижний индекс... </SUB>
Атрибуты отсутствуют.
Пример'-
Для записи индексов используем мелкий индексный шрифт, например, x<SUB>K/SUB> и x<SUB>2</SUB>.
<SUP>
Этот элемент является контейнером.
Верхний индекс.
<SUP>... верхний индекс... </SUP>
Атрибуты отсутствуют.■
;Пример|
Площадь квадрата со стороной 1 равняется 1<SUP>2</SUP>.
<тт>
Этот элемент является контейнером.
Выводи телеграфный текст (текст фиксированной ширины).
<ТТ>... телеграфный текст... <ТТ>
Атрибуты отсутствуют.
'Пример■ I
The computer will then display the <TT>Login:</TT> prompt.
<и>
Этот элемент является контейнером.
Подчеркнутый шрифт. '
<U>... подчеркнутый текст... </U>
Атрибуты отсутствуют.
: Пример‘'
Самая большая книга, которую я читал, — это <и>"Война и мир"</и>.
Элементы форматирования фраз
<ACRONYM>
Этот элемент является контейнером.
<ACRONYM>... аббревиатура... </ACRONYM>
Для вывода аббревиатур.
Атрибуты отсутствуют.
а||ДеЯ1|1ЯИЯЯ16|8ЯИ^
Аббревиатура слов Hypertext Markup Language <ACRONYM>(HTML)</ACRONYM> — это частный случай языка Standard Generalized Markup Language, t. e.
<ACRONYM>SGML</ACRONYM>.
<ADDRESS>
Этот элемент является контейнером.
Выводит адрес.
<ADDRESS>... адрес... </ADDRESS>
Атрибуты отсутствуют.
1ИДВДаИ!Д^
Пишите мне <ADDRESS>feedback@myserver.com</ADDRESS>.
<CITE>
Этот элемент является контейнером.
Выводит цитату. <С1ТЕ>... текст цитаты... </С1ТЕ> Атрибуты отсутствуют.
!Пример
Пословица гласит:<С1ТЕ>"Чем дальше влез, тем ближе вылез"</С1ТЕ>.
<CODE>
Этот элемент является контейнером.
Выводит программный код.
<CODE>... фрагмент кода... </CODE>
Атрибуты отсутствуют.
:Пример
<CODE> for n = 1 to 10 value(n) = (n++)A2;
</CODE>
<DEL>
Этот элемент является контейнером.
Выделяет текст, удаленный из документа.
<DEL>... этот фрагмент текста удален... </DEL>
Атрибуты отсутствуют.
■ Пример
Просто он был большой <ОЕЬ>и огромный</ВЕЕ>, как танк.
<DFN>
Этот элемент является контейнером.
Текст определения.
<DFN>... здесь определение... </DFN>
Атрибуты отсутствуют.
Пример .!
Этот фрагмент раскрывает понятие <ОЕМ>сёрвант</ОЕМ>, которое используется для обозначения программного класса, не являющегося классом CORBA, но имплементирующего абстрактный класс.
<ЕМ>
Этот элемент является контейнером.
Выделяет текст.
<ЕМ>... выделенный текст... </ЕМ>.
Атрибуты отсутствуют.
jПример\
Выделенный текст: <ЕМ>выделенные слова</ЕМ>.
<INS>
Этот элемент является контейнером.
Вставленный текст.
<!№>.. . этот текст вставлен... </!№>
Атрибуты отсутствуют.
Д|ДеМ111|81В1^^^
Макароны изобрел <DEL>MaKapoa</DEL> <1№>Спагеттин</1№> много лет назад.
<KBD>
Этот элемент является контейнером.
Текст, введенный с клавиатуры.
<KBD>... ввод с клавиатуры... </KBD>
Атрибуты отсутствуют.
|||Й1|||118111$11111^^
После приглашения введите <KBD>2002-1495-9A</KBD>.
<Q>
Этот элемент является контейнером.
Он используется для вставки в HTML-текст цитат.
<Q CITE="URL_of_cited_document">... цитата... </Q>
Атрибуты: если цитируется источник, расположенный в сети, то необходимо использовать атрибут cite, значение которого равно URL источника.
: Пример."
<Q>To be or not to be. That is the question.</Q>, he said dramatically.
<SAMP>
Этот элемент является контейнером.
Для печати того, что выдает программа на выходе.
<SAMP>... результат работы программы... </SAMP>
Атрибуты отсутствуют.
iПример:
Как правило, первая программа выводит сообщение <SAMP>Hello World</SAMP>.
<STRONG>
Этот элемент является контейнером.
Выделяет текст.
<STRONG>... strongly emphasized text goes here... </STRONG>
Атрибуты отсутствуют.
i7:1
; Примерi
Do <STRONG>not</STRONG> install the software until you've closed all other running applications.
<VAR>.
Этот элемент является контейнером.
Переменная в компьютерной программе.
<VAR>... переменная... </VAR>
Атрибуты отсутствуют.
: Пример
Это <УАН>переменная</VAR>.
Блочные элементы форматирования
<BLOCKQUOTE>
Этот элемент является контейнером.
Выделенная цитата.
<BLOCKQUOTE СITE="URL_of_cited_document"> ... quoted text goes here...
</BLOCKQUOTE>
||||Ий|||111||в
Fans of Schoolhouse Rock will always be able to recite the preamble of the United States Constitution:
<BLOCKQUOTE>
We, the people, in order to form a more perfect Union... </BLOCKQUOTE>
<BR>
Самостоятельный элемент (не контейнер).
Конец строки.
<BR CLEAR="LEFT|RIGHT|ALL">
Атрибуты:
CLEAR.
Пример
Адрес президента O1IA<BR>
The White House<BR>
1600 Pennsylvania Avenue NW<BR>
Washington, DC 20500
<CENTER>
Этот элемент является контейнером.
Выравнивание по центру.
<CENTER>... компоненты страницы, выравниваемые по центру... </CENTER>
Атрибуты отсутствуют.
|||gyg|g|g||j|g|||g^^
<CENTER>'
<Н2>Годовой отчет </Н2>
составлен бригадой аудиторов от бога
</CENTER>
<DIV>
Этот элемент является контейнером.
Выделяет сегмент HTML-страницы, который может быть подвергнут специальным условиям форматирования.
<DIV ALIGN="LEFT|RIGHT|CENTER|JUSTIFY">
</DIV>
Атрибуты:
ALIGN.
|МДеМ11||И|||Я|»|^^
<DIV ALIGN="JUSTIFY">
этот фрагмент может состоять из большого количества HTML-элементов, форматируемых специальным (порой довольно сложным) образом.
</DIV>
<HR>
Самостоятельный элемент (не контейнер).
Вставляет горизонтальную линию.
<HR ALIGN="alignment" NOSHADE SIZE="thickness"
WIDTH="pixels_or_percentage_of_screen">
Атрибуты:
ALIGN;
NOSHADE;
SIZE;
WIDTH.
; Пример
<HR NOSHADE WIDTH=80% SIZE=4>
<DIV ALIGN="CENTER"XB>Welcome! </B></DIV>
HR NOSHADE WIDTH=80% SIZE=4>
<H1>...<H6>
Эти элементы являются контейнерами.
Заголовки различных уровней.
<Нл ALIGN="LEFT|RIGHT|CENTER|JUSTIFY">... Level л heading... </Нл>
здесь л = 1, 2, 3, 4, 5 или 6.
Атрибуты:
□ ALIGN.
Значения align:
left (по умолчанию);
RIGHT;■
CENTER;
JUSTIFY.
Пример
<H1 АЕ1СН="СЕНТЕР">Заголовок первого уровня</Н1>
<Н2>Глава 1 — заголовок второго уровня</Н2>
<Н2>Глава 2 — заголовок второго уровня</Н2>
<Р>
Этот элемент является контейнером.
Начало нового параграфа.
<Р ALIGN="LEFT|RIGHT|CENTER IJUSTIFY">
текст параграфа
</Р>
Атрибуты:
ALIGN (LEFT (по умолчанию), RIGHT, CENTER, JUSTIFY).
||||В|1й|1||1||1|^^
<P ALIGN="CENTER">
Это текст параграфа...
</P>
<PRE>
Этот элемент является контейнером.
Заранее отформатированный текст.
<PRE WIDTH="mnpnHa самой широкой строки"> ... это заранее сформатированный текст...
</PRE>
Атрибуты:
□ WIDTH.
: Пример■
<PRE WIDTH=34>
НомерНазвание
31390Сумка
10081Пальто
139334Пояс
</PRE>
Цена 4300 12100 750
<SPAN>
Этот элемент является контейнером.
Элемент используется для задания фрагменту условий форматирования.
<SPAN 5ТУЕЕ="информация о стиле"> текст для форматирования
</SPAN>
Атрибуты:
style (информация о стилях содержится в спецификации CSS).
Mffl|lltot||ll*li|Hl||lli|IH
<SPAN STYLE="font-weight: bold; color: red; text-indent: 0.25 in"> Пример форматируемого текста.
</SPAN>
Элементы для работы со списками
<LI>
Этот элемент является контейнером.
Список.
<LI TYPE="list_type" START="start_value">... элемпент списка... </Ы> Атрибуты:.
START;
TYPE.
Типы упорядоченных списков:
1 — арабские цифры;
а — алфавит, верхний регистр;,
а — алфавит, нижний регистр;
I — прописные римские цифры;
i — строчные римские цифры.
Типы неупорядоченных списков:
disc — сплошная круглая метка;
square — черный квадрат;
circle — незакрашенный круг.
||Йи|М1|н1|111|Я|е||1^^
<Ы>Виктор</Ы>
<Ы>Сергей</Ы>
<LI>Андрей</LI>
<DIR>
Этот элемент является контейнером.
Листинг каталога.
<DIR СОМРАСТ>
<Ы>Вход 1</LI>
<Ы>Вход 2</LI>
</DIR>
Атрибуты:
□ COMPACT.
Пример
<DIR>
<LI>Mary Garrison, x52K/LI>
<LI>Tom Hinkle, x629</LI>
<LI>Pat Joseph, x772</LI>
</DIR>
<DL>
Этот элемент является контейнером. Определение.
<DL COMPACT> ... термины и определения...
</DL>
Атрибуты:
□ СОМР.
М|р|Ме||1|й||[||||8^
<DL>
<DT>Browser</DT>
<DD>A program that allow a user to view World Wide Web pages</DD> <DT>Server</DT> .
<DD>A program that fields requests for web pages</DD>
</DL>
<DT>
Этот элемент является контейнером.
Определяемый термин в списке определений.
<DT>... определяемый термин... </DT>
Атрибуты отсутствуют.
■||р|^|||||||||||11||||||Я#^
<DL>
<ОТ>Витамин</ОТ>
<00>нечто полезное для организма</00>
</DL>
<DD>
Этот элемент является контейнером.
Определение термина.
<DD>... определение термина... </DD>■
Атрибуты отсутствуют.
: Пример|
<DL>
<DT>HTML</DT>
<00>Язык описания гипертекстовой разметки</00>
</DL>
<MENU>
Этот элемент является контейнером..
Меню.
<MENU COMPACT>
<Ы>Элемент меню 1</Ы>
<Ы>Элемент меню 2</Ы>
</MENU>
Атрибуты:
COMPACT.
П1ит»1п«|<нии>штн»ин*»
<MENU COMPACT>'
<LI>Hamburgers</Ll>
<LI>Hot dogs</LI>
<LI>BBQ chicken</LI>
</MENU>.
<OL>
Этот элемент является контейнером. Организует нумерованный (упорядоченный) список.
<0L TYPE="l|A|a|I|i" ЗТАРТ="начальное значение" СОМРАСТ>
<Ы>Элемент списка 1</Ы>
<Ы>Элемент списка 2</Ы>
</0L>
Атрибуты:-
COMPACT;
START;
TYPE.
|МЯИИД1||1В|1||||1О
Book Outline
<0L TYPE="A">
<LI>HTML</LI>
<LI>Dynamic HTML</LI>
<LI>Java</LI>
<LI>JavaScript</LI>
</0L>
<UL>
Этот элемент является контейнером.
Неупорядоченный список.
<UL TYPE="DISC|SQUARE(CIRCLE" COMPACT> <Е1>Элемент списка 1</Ы>.
<Е1>Элемент списка 2</LI>
</UL>
Атрибуты:..'
COMPACT; □ TYPE.
|Й11й|®11||1!|8е11В11в|11В|11^
Web-браузеры
<UL TYPE="SQUARE">
<LI>Netscape Navigator</LI>
<LI>Microsoft Internet Explorer</LI>
<LI>NCSA Mosaic</LI>
</UL>
Элементы гиперссылок
<A>
Этот элемент является контейнером.
Гиперссылка.
<!— задаем гиперссылку —>
<А НКЕГ="иКЬ_документа" ТАВСЕТ="имя фрейма"
REL="forward_link_type" REV="reverse_link_type"
ACCESSKEY="key_letter" TABINDEX="tab_order_position">
... элемент, указывающий на ссылку...
</А>
ИЛИ
<!—задаем якорь внутри страницы —>
<А NAME="anchor__name">
... элемент, указывающий на якорь...
</А>
Атрибуты:
ACCESSKEY;
HREF;
NAME;
REL;
REV;
TABINDEX;
TARGET.
JiBiiijliilllliliBliiSfc^^
Гиперссылка
<A HREF="file.html TARGET="main" ACCESSKEY="P">
листья и ветки </A> as well.
Перейти по ссылке можно либо с помощью мыши, либо нажав Alt+P.
А это якорь:
<А NAME="toc">
<Н1>Содержание</Н1>
</А>
Переход к якорю:
<А HREF="index.html#toc">Ha3afl к содержанию</А>.
Рисунки и карты ссылок
<IMG>
Самостоятельный элемент (не контейнер).
Вставляет рисунок в HTML-страницу.
<IMG SRC="URL_of_image_file"
WIDTH="width_in_pixels" HEIGHT="height_in_pixels"
ALT="text_description" BORDER="thickness_in_pixels"
ALIGN="TOP|MIDDLE I BOTTOM|LEFT|RIGHT"
HSPACE="horizontal_spacing_in_pixels"
VSAPCE="vertical_spacing_in_j)ixels"
ISMAP USEMAP="map_name">
Атрибуты:
SRC;
WIDTH;
HEIGHT;
ALT;
BORDER;
ALIGN;
HSPACE;
VSPACE;
ISMAP;
USEMAP.
| Пример
<IMG SRC="/images/grain.gif" WIDTH=600 HEIGHT=120
ALT="Bac приветствует ЗЕРНОХРАНИЛИЩЕ — картинка не загрузилась" USEMAP="#main"
VSPACE=10>
<МАР>
Этот элемент является контейнером.
Задает области на рисунке.
<МАР NAME="map_name">
... описания областей ...
</МАР>
<МАР NAME="navigation">
<AREA SHAPE="RECT" COORDS="23,47,58,68" HREF="search.html">
<AREA SHAPE="CIRCLE" COORDS="120,246,150,246" HREF="about.html">
</MAP>
<AREA>
Самостоятельный элемент (не контейнер).
Описывает область на рисунке.
<AREA SHAPE="RECT|CIRCLE|POLY|DEFAULT" COORDS="coordinate_list"
HREF="URL_ccbMKH" TARGET="hmh фрейма"
АТТ="альтернативный текст" ТАВ1К0ЕХ="порядок по табуляции" NOHREF>
Атрибуты:
alt — альтернативный текст;
coords — координаты;
href — URL ссылки;
nohref — область указывает в никуда;
shape — форма области:
rect — прямоугольник;
circle — круг;
poly — многоугольник;
default — любая неописанная часть картинки;
tabindex — позиция при доступе с помощью клавиши табуляции;
target — имя фрейма, куда будет загружаться ссылка.
Пример
<МАР NAME="main">
<AREA SHAPE="POLY" COORDS="35,80,168,99,92,145" HREF="profile.html">
<AREA SHAPE="CIRCLE" COORDS="288,306,288,334" HREF="feedback.html">
<AREA SHAPE="DEFAULT" HREF="index.html">
</MAP>
Элементы таблицы
<TABLE>
Этот элемент является контейнером.
Содержит в себе элементы таблицы.
CTABLE ALIGN="LEFT|CENTER|RIGHT" BORDER="thickness_in_j>ixels" BGCOLOR="color" WIDTH="pixels_orjoercentage_of_browser_width" COLS="number_of_columns" CELLPADDING="pixels" CELLSPACING="pixels" FRAME="outer_border_rendering" RULES="inner_border_rendering">
</TABLE>
Атрибуты:
align (значения: left, center, right);
BORDER;
BGCOLOR;
CELLPADDING;
CELLSPACING;
COLS;
FRAME:
ABOVE;
BELOW;
BORDER;
BOX;■
HSIDES;
LHS ;
RHS ;
VSIDES;
VOID;'
□ RULES:
ALL;
GROUPS;
ROWS;
WIDTH.
|1||»11||||В||11|1В1|в|1|^^
Шив1й1«шгДшийша^ивм«аа1в4аш»
CTABLE BORDER=2 CELLPADDING=4 FRAME=BORDER RULES=ALL ALIGN=CENTER>
</TABLE>
<CAPTION>
Этот элемент является контейнером.
Способ отображения таблицы.
<CAPTION ALIGN="TOP|BOTTOM|LEFT|RIGHT"> ... caption text goes here...
</CAPTION>
Атрибуты:
□ ALIGN.
(It|ifl|||||i8lilliilll|j^
<CAPTION ALIGN="BOTTOM">
Таблица 3 — Результаты экзаменов
</CAPTION>
<THEAD>
Этот элемент является контейнером.
Заголовок таблицы.
<THEAD ALIGN="LEFT|CENTER|RIGHT|JUSTIFY"
VALIGN="TOP|MIDDLE|BOTTOM|BASELINE">
... заголовок таблицы...
</THEAD>
Атрибуты:
□ ALIGN:
LEFT;
RIGHT;
CENTER;
JUSTIFY;
□ VALIGN:
TOP;
MIDDLE;
BOTTOM;
BASELINE.
Пример
<THEAD ALIGN="CENTER" VALIGN="BASELINE">
<TR>
<ТН>Номер по списку</ТН>
<ТН>Описание</ТН>
<ТН>Цена</ТН>
</TR>
</THEAD>
<TFOOT>
Этот элемент является контейнером.
Нижняя подпись к таблице.
<TFOOT ALIGN="LEFTI CENTER|RIGHT|JUSTIFY"
VALIGN="TOPI MIDDLE|BOTTOM|BASELINE">
</TFOOT>
Атрибуты:
□ ALIGN:
LEFT;
RIGHT;
CENTER;
JUSTIFY;
VALIGN:
TOP;
MIDDLE;
BOTTOM;
BASELINE.
Пример■
<TFOOT ALIGN="JUSTIFY" VALIGN="TOP">•
<TR>
<TD><I>Source:</I> The Washington Post, 9/22/97</TD>
</TR>
</TFOOT>
<TBODY>
Этот элемент является контейнером.
Содержит в себе основную часть таблицы — тело таблицы.
<TBODY ALIGN="LEFT|CENTER|RIGHT|JUSTIFY"
VALIGN="TOPI MIDDLE|BOTTOM|BASELINE">
</TBODY>
Атрибуты:
ALIGN:
LEFT;
RIGHT;
CENTER;
JUSTIFY;■
VALIGN:
TOP;
MIDDLE;
BOTTOM;
BASELINE.
iПример;
CTBODY ALIGN="LEFT" VALIGN="BASELINE">
<TR>
<ТО>Сарай из досок</ТО>
<TD>npopa6</TD>
<ТО>Сергей</ТО>
</TR>..
</TBODY>'
<COLGROUP>
Этот элемент является контейнером.
Группирует столбцы таблицы.
<COLGROUP SPAN="number_of_columns" WIDTH="width_of_column_group" ALIGN="LEFT|RIGHT|CENTER|JUSTIFY" VALIGN="TOP|MIDDLE|BOTTOM|BASELINE">
</COLGROUP>
Атрибуты:
ALIGN:'
LEFT;
RIGHT;
CENTER;
JUSTIFY;
SPAN;
VALIGN:
TOP;
MIDDLE;
BOTTOM;
BASELINE;
WIDTH.
Пример '
<COLGROUP SPAN=3 ALIGN-"CENTER" VALIGN="TOP">
</COLGROUP>
<TR>_
<ТОСтолбец 1 — по центру сверху</ТО>
<ТО>Столбец 2 — по центру сверху</ТО
<ТО>Столбец 3 — по центру сверху</ТО
<ТО>Столбец 4 — по умолчанию</ТО>
</TR>.
</TFOOT>'
<COL>
Самостоятельный элемент (не контейнер).
Задает свойства столбца или группы столбцов таблицы.
<COL ЗРАЛ="количество столбцов в группе" WIDTH="ширина"
ALIGN=”LEFT |RIGHT|CENTER I JUSTIFY"
VALIGN="TOPI MIDDLE I BOTTOM|BASELINE">
Атрибуты:
ALIGN:
LEFT;
RIGHT;
CENTER;
JUSTIFY;
SPAN;
VALIGN:
TOP;
MIDDLE;
BOTTOM;
BASELINE;
WIDTH.
. Пример
<TABLE BORDER=1>
<COLGROUP>
<COL ALIGN=CENTER>
<COL ALIGN=RIGHT>
</COLGROUP>
<COLGROUP>
<COL ALIGN=CENTER SPAN=2>
</COLGROUP>
<TBOBY>'
<TR>
<ТВ>Первый столбец первой группы (по центру)</ТВ>
<ТВ>Второй столбец первой группы (по правой границе)</ТВ>
<ТВ>Первый столбец второй группы (по центру)</ТВ>
<ТВ>Второй столбец второй группы (по центру)</ТВ>
</TR>'
</TBOBY>
</TABLE>
<TR>
Этот элемент является контейнером.
Строка таблицы.
<TR BGCOLOR="color" ALIGN="LEFT|RIGHT|CENTER|JUSTIFY" VALIGN="TOPIMIBBLE|BOTTOM|BASELINE">
</TR>
Атрибуты:
ALIGN:
LEFT;
RIGHT;
CENTER;
JUSTIFY;
BGCOLOR;
valign:
TOP;
MIBBLE;
BOTTOM;
BASELINE.
: Пример
<TR BGCOLOR="white" VALIGN="TOP">
<ТВ>Ячейка #1</TD>
<ТВ>Ячейка #2</TB>
</TR>
<TD>, <ТН>
Эти элементы являются контейнерами.
Задают ячейки в таблице (<td> — обычная ячейка, <тн> — ячейка заголовка).
<TD ALIGN="LEFT|RIGHT|CENTER|JUSTIFY"
VALIGN="TOP l-MIDDLE | BOTTOM | BASELINE"
BGCOLOR="uBeT" NOWRAP ROWSPAN="кoличecтвo строк" СОЬЗРАМ="количество столбцов">
ИЛИ
<ТН ALIGN="LEFT|RIGHT|CENTER|JUSTIFY" VALIGN="TOP|MIDDLE|BOTTOM|BASELINE" ВССОЕОР="цвет" NOWRAP ROWSPAN="кoличecтвo строк" СОЕЗРАН="количество столбцов">
Атрибуты:
□ ALIGN:
LEFT;
RIGHT;
CENTER;
JUSTIFY;
BGCOLOR;
COLSPAN;
NOWRAP;
ROWSPAN;
VALIGN:
TOP;
MIDDLE;
BOTTOM;
BASELINE.
|||f||||j|f|jjj|^^
<TR VALIGN="BOTTOM">
<ТН>Столбец — center/bottom</TH>
<TD УАЕ1СН="М100ЕЕ">Столбец 2 - left/middle</TD>
<TD ALIGN="JUSTIFY">Cтoлбeц 3 - justify/bottom</TD>
<TD СОЕ5РАН=2>Столбцы 4 и 5 - left/bottom</TD>
</TR>
Элементы формы
<FORM>
Этот элемент является контейнером.
Содержит тело формы.
<FORM ACTION="URL_of_processing_script" METHOD="GET|POST" TARGET="frame_name" ENCTYPE="MIME_type_of_file_to_upload" ACCEPT-CHARSET="acceptable_character_sets">
</FORM>
Атрибуты:
ACCEPT-CHARSET;
ACTION;
ENCTYPE;
METHOD;
TARGET.
Пример
<FORM ACTION="/cgi-bin/script.php" METHOD="POST" TARGET="response">
</FORM>
<INPUT>
Самостоятельный элемент (не контейнер).
Используется для создания элементов управления на HTML-странице:
поле для ввода текста;
поле для ввода пароля;
скрытые поля;
переключатели;
поле для отправки файла;
кнопки-изображения;
кнопки выполнения скриптов;
кнопки отправки формы и очистки формы.
<1 — Текстовые поля и поля для ввода пароля —>
<INPUT TYPE="TEXT|PASSWORD" ЫАМЕ=”имя поля" VALUE="значение по умолчанию"
512Е="размер поля" МАХЕЕКСТН="максимальная длина вводимого значения" DISABLED READONLY> '
ИЛИ
<!—Скрытый элемент input —>
CINPUT TYPE="HIDDEN" МАМЕ="имя поля" VALUE="значение">
ИЛИ
<! — Поле для галочки —>
<INPUT TYPE="CHECKBOX" МАМЕ="имя поля" VALUE="значение"
CHECKED DISABLED>
ИЛИ
<!— Радиокнопка —>
<INPUT TYPE="RADIO" МАМЕ="имя поля" 7АЫ)Е="значение"
CHECKED DISABLED>
ИЛИ
<!-- Отправка файла -->
<INPUT TYPE="FILE" МАМЕ="имя поля" 7АЫ)Е="значение по умолчанию"
АССЕРТ="допустимые типы MIME" DISABLED>
ИЛИ
<!— Кнопка-изображение —>
<INPUT TYPE="IMAGE" SRC="URL файла с картинкой" АЬТ="альтернативный текст" ALIGN="TOP|MIDDLE|BOTTOM|LEFT |RIGHT" иЗЕМАР="карта ссылок" DISABLED>
ИЛИ
<!— Кнопки запуска скрипта —>
<INPUT TYPE="BUTTON" УАШЕ="надпись на кнопке" опс!1ск="функция_скрипт" DISABLED>
ИЛИ
<!— Кнопка отправки или очистки формы —>
<INPUT TYPE="SUBMITI RESET" УАШЕ="надпись на кнопке" DISABLED>
Атрибуты:
□ TYPE="TEXT|PASSWORD";
□ TYPE="HIDDEN";
□ TYPE="CHECKBOX";
□ TYPE="RADIO";
□ TYPE-"FILE";
□ TYPE="IMAGE";
□ TYPE="BUTTON";
□ TYPE="SUBMIT|RESET".
Пример “
<FORM ACTION="/cgi-bin/form.cgi">
Имя пользователя: <INPUT TYPE="TEXT" NAME="login" SIZE=12>
Пароль: <INPUT TYPE="PASSWORD" NAME="passwd" SIZE=12>
<INPUT TYPE="HIDDEN" NAME="browser" VALUE="IE4">
Пол: <INPUT TYPE="RADIO" NAME="sex" VALUE="F">Female
<INPUT TYPE="RADIO" NAME="sex" VALUE="M">Male
<INPUT TYPE="BUTTON" VALUE="Check data" onclick="dofunction()">
<INPUT TYPE="SUBMIT" VALUE="Login">
<INPUT TYPE="RESET" VALUE="Clear">
</FORM>.
<SELECT>
Этот элемент является контейнером.
Список выбора.
<SELECT NAME="имя поля" SIZE="visible rows" MULTIPLE DISABLED>
</SELECT> Атрибуты: □ disabled; □ MULTIPLE; □ NAME; □ SIZE.
Пример
<SELECT NAME="toppings" SIZE=5 MULTIPLE>
<OPTION>Mushrooms</OPTION>
<OPTION>Onions</OPTION>
<OPTION>Sausage</OPTION>
</SELECT>
<OPTION>
Этот элемент является контейнером.
Задает одну опцию в списке выбора.
«OPTION VALUE="значение опции" SELECTED DISABLED> ... текст опции...
</OPTION>
Атрибуты:
DISABLED;
SELECTED;
VALUE.
jПример ''..
<SELECT NAME="state" SIZE=5>
«OPTION VALUE="AL">Alabama</OPTION>
«OPTION VALUE="NM" SELECTED>New Mexico</OPTION>
<OPTION VALUE="OK">Oklahoma</OPTION>
</SELECT>
<TEXTAREA>
Этот элемент является контейнером.
Многострочное текстовое поле.
<TEXTAREA НАМЕ="имя поля" ROWS="кoличecтвo строк"
С0Ь5="количество столбцов (символов)" DISABLED READONLY> ... текст, показываемый в окне по умолчанию...
</TR>
Атрибуты:
COLS;
DISABLED;
NAME;
READONLY;
ROWS.
Пример•'■.
<TEXTAREA NAME="feedback" ROWS=10 COLS=40>
Оставьте здесь свой комментарий. Спасибо!
</TEXTAREA>
<BUTTON>
Этот элемент является контейнером.
Кнопка отправки формы или очистки полей формы.
<BUTTON TYPE="SUBMIT|RESET" NAME="button_name" VALUE="button_value"
DISABLED>
... надпись на кнопке или элементе <IMG>...
</виттоы>
Атрибуты:
ISABLED;
NAME;
TYPE;
VALUE.
,Пример ''
<BUTTON ЫАМЕ="скрытая связь" VALUE="link">
<IMG SRC="images/clickme.gif">
</BUTTON>
<LABEL>
Этот элемент является контейнером.
Задает метку на форме.
<LABEL FOR="field_ID" ACCESSKEY="shortcut_key" DISABLED> ... текст метки...
</LABEL>
Атрибуты:
ACCESSKEY;
DISABLED;
FOR.
' Пример
<LABEL FOR="PW" ACCESSKEY="P">Enter your password:</LABEL>
<INPUT TYPE="PASSWORD" ID="PW" NAME="passwd">
<FIELDSET>
Этот элемент является контейнером.
Группирует элементы формы.
<FIELDSET>
. . . элементы формы. .■.
</FIELDSET>
Атрибуты отсутствуют.
|ИВЙЮёИ!№а!М^
CFIELDSET>
Имя: CINPUT TYPE="TEXT" NAME="login">
Пароль: CINPUT TYPE="PASSWORD" NAME="passwd"> C/FIELDSET>
<LEGEND>
Этот элемент является контейнером.
Используется для задания значений имен в элементе <FIELDSET>.
CLEGEND ALIGN="LEFT|RIGHT|TOP I BOTTOM" ACCESSKEY="shortcut_key"> ... текст...
C/LEGEND>
Атрибуты:
ACCESSKEY;
ALIGN:
LEFT;
RIGHT;
TOP;
BOTTOM.
; Пример
CFIELDSET>
CLEGEND АП1СН="Т0Р">Информация об аутентификации пользователяс/ПЕСЕН0> Имя: CINPUT TYPE="TEXT" NAME="login">
Пароль: CINPUT TYPE="PASSWORD" NAME="passwd"> C/FIELDSET>
Элементы фрейма
<FRAMESET>
Этот элемент является контейнером.
Делит окно браузера на фреймы.
CFRAMESET ROWS="cnncOK размеров строк" СОП5="список размеров столбцов">
Атрибуты:
□ ROWS;
□ COLS.
Пример
<1— делим окно на три столбца: 90 пикселов, 60% от ширны окна и все, что осталось. —>
<FRAMESET COLS="90,60%,*">
</FRAMESET>
<FRAME>
Самостоятельный элемент (не контейнер).
Создает тело фрейма.■.
<FRAME SRC="URL документа во фрейме" NAME-"имя фрейма" FRAMEBORDER-"0|1" MARGINWIDTH="width_in_pixels" MARGINHEIGHT="height_in_pixels" NORESIZE SCROLLING="YESI NO|AUTO">
Атрибуты:
FRAMEBORDER;
MARGINHEIGHT;
MARGINWIDTH;
NAME;
NORESIZE;
SCROLLING;
SRC.
BnfMig|Hll|iI|lO
<FRAMESET COLS="25%,75%"> <!—Двухстолбцовая страница с фреймами —>
<!—Загрузка первого фрейма —>
<FRAME SRC="leftframe.html" NORESIZE NAME="left" FRAMEBORDER-O>
<!—Загрузка второго фрейма —>
<FRAME SRC="rightframe.html" NORESIZE NAME="right" FRAMEBORDER-0>
<NOFRAMES>
Этот элемент является контейнером.
Содержит текст, который выводится в том случае, если нет возможности отобразить фреймы (если фреймы не поддерживаются).
<NOFRAMES>
... содержание без фреймов...
</NOFRAMES>
Атрибуты отсутствуют.
Пример■
<FRAMESET COLS="25%,75%"> <!—страница с фреймами в два столбца —>
<!—загрузка первого фрейма —>
<FRAME SRC="leftframe.html" NORESIZE NAME="left" FRAMEBORDER=0>
<!— загрузка второго фрейма —>
<FRAME SRC="rightframe.html" NORESIZE NAME="right" FRAMEBORDER=0>
<NOFRAMES>
Браузер не поддерживает фреймы, посетите другую страницу:
<А HREF="/noframes/index.html">, она без фреймов</А>.
</NOFRAMES>
</FRAMESET>
<1FRAME>
Этот элемент является контейнером.
Задает плавающий фрейм.
<IFRAME SRC="URL_of_document" NAME="frame_name" FRAMEBORDER="0|1"
WIDTH="frame_width_in_pixels_or_percentage"
HEIGHT="frame_height_in_pixels_or_percentage"
MARGINWIDTH="margin_width__in_pixels"
MARG INHEI GHT= "ma r g i n_he i gh t_in_p i хе 1 s "
SCROLLING="YES|NO|AUTO" ALIGN="TOPI MIDDLE|BOTTOM I LEFT |RIGHT">
... текст или прочее содержимое фрейма...
</IFRAME>
Атрибуты:
□ ALIGN:
TOP;
MIDDLE;
BOTTOM;
LEFT;
RIGHT;
FRAMEBORDER;
HEIGHT;
MARGINHEIGHT;
MARGINWIDTH;
NAME;
SCROLLING;
SRC;
WIDTH.■
!Пример
<IFRAME SRC="floating.html" WIDTH="50%" HEIGHT="50%" ALIGN=LEFT SCROLLING="NO" NAME="floater" FRAMEBORDER=1>
В вашем браузере фреймы не работают.
</IFRAME>■
Элементы выполняемых программ
<APPLET>
Этот элемент является контейнером."
Размещает Java-апплет.
<APPLET WIDTH="mnpnHa в пикселах" НЕIGHT="высота в пикселах" С0ВЕВАЗЕ="базовый URL файла класса апплета" СОВЕ="файл класса апплета" ОВЦЕСТ="сериализованное имя класса апплета" ПАМЕ="имя апплета" АРСН1\7Е="список архивов" АЕТ="альтернативный текст" ALIGN="TOP|MIDDLE I BOTTOM|LEFT|RIGHT" НЗРАСЕ="пикселы" УЗРАСЕ="пикселы">
</APPLET>
Атрибуты:
□ ALIGN:
TOP;
MIDDLE;
BOTTOM;
ALT;
ARCHIVE;
CODE;
CODEBASE;
HEIGHT;
HSPACE;
NAME;
OBJECT;
VSPACE;
WIDTH.
||||||н||1|||1||Я
<APPLET WIDTH=250 HEIGHT=200 CODE="appletflie.class" NAME="appletname" АЬТ="Здесь альтернативный текст" ALIGN="RIGHT" HSPACE=5 VSPACE=12>
<PARAM NAME="message" VALUE="Hello World!">
</APPLET>
<PARAM>
Самостоятельный элемент (не контейнер).-
Задает параметры для Java-апплета или другого выполняемого объекта.
<PARAM ПАМЕ="имя параметра" VALUE="значение параметра" VALUETYPE="DATA|REF|OBJECT" ТYPE="тип">
Атрибуты:
NAME;
TYPE;
VALUE;
VALUETYPE:
DATA;
REF;
OBJECT.
<APPLET WIDTH=300 HEIGHT=224 CODE="test.class ALT="Test applet" ALIGN="TOP" NAME="test" >
<PARAM NAME="tolerance" VALUE="O.001" VALUETYPE="DATA">
<PARAM NAME="pi" VALUE="3.14159" VALUETYPE="DATA">
</APPLET>
<OBJECT>
Этот элемент является контейнером.
Помещает на страницу исполняемый объект.
OBJECT СЬА5510="идентификатор класса" CODEBASE="URL объекта"
CODETYPE="MIME тип" TYPE="MIME тип данных"
STANDBY="TeKCT для показа во время загрузки" иЗЕМАР="имя карты"
ALIGN="TEXTTOPI MIDDLE|TEXTMIDDLE|BASELINE|TEXTBOTTOM|LEFT|CENTER|RIGHT"
Ы10ТН="ширина в пикселах или процентах" ЫАМЕ="имя объекта"
НЕ1СНТ="высота в пикселах или процентах"
Н5РАСЕ="пикселы" 75РАСЕ="пикселы" В0Р0ЕР="пикселы">
</OBJECT>
Атрибуты:
align;
width;
height;
border;
hspace;
vspace;
classid;
CODEBASE;
codetype;
standby;
type;
USEMAP.
i|y98i|||lli|j|||itli||ii^^
<OBJECT WIDTH=100% HEIGHT=100 CODETYPE="application/x-oleobject" CLASSID="CLSID: 1C9YA620-6217-11CF-EE62-0087T72EDD2D" CODEBASE="http://activex.Microsoft.com/object. ocx" HSPACE=5 VSPACE=10 ALIGN=MIDDLE BORDER=0>
<PARAM NAME="image" VALUE="pic.gif">
<PARAM NAME="speed" VALUE="7">
<PARAM NAME="repeat" VALUE="1">
</OBJECT>
Приложение 2
Основные встроенные объекты Microsoft ASP IIS
Стандартные объекты, встроенные в IIS:
Application;
ASPError Object;
Objectcontext;
Request;
Response;
ScriptingContext;
Server;
Session.
Объект Application
Коллекции
Стандартные коллекции, используемые при работе с объектом Application, представлены ниже:
Contents — содержит все элементы, вставленные в приложение с помощью команд стрипта;
staticobjects — все объекты, вставленные при помощи ярлыка
<object>.
Методы
Объект Application содержит следующие методы:
Contents.Remove;
Contents. RemoveAll;
Lock;
Unlock.
События
В объекте Application предусмотрены события:
Application_OnEnd;
Application_OnStart.
■Bl||B||iBlii|i||||l|lilil^^
<% Application("greeting") = "Welcome to My Web World!" Application("num") = 25
%>
Объект ObjectContext
Методы
Объект objectcontext содержит методы:
SetAbort;
SetComplete.
События
В объекте objectcontext предусмотрены следующие события:
□ OnTransactionAbort;
□ OnTransactionCommit.
Объект Request
Request[.collection|property I method](variable)
Коллекции
Стандартные коллекции, используемые при работе с объектом Request, представлены ниже:
clientcertificate — значения полей клиентского сертификата;
cookies — значения строки cookies;
Form — значения полей формы;
Querystring — строка запроса;
sgrverVaг 1 зЫesпеременные окружения.
Свойства
В объекте Request используется следующее свойство:
TotaiBytes — количество байтов в запросе.
Методы.
Метод BinaryRead получает данные, переданные серверу с запросом, с помощью метода post.
Все переменные доступны при обращении в форме Request (variable). Коллекцию указывать не нужно. Если коллекция не указана, сервер производит поиск по коллекциям в следующем порядке:
Querystring
Form•
Cookies
Clientcertificate
Servervariables
Если переменные с одинаковыми именами есть в нескольких коллекциях, то сервер возвращает первую встретившуюся. Рекомендуется указывать полное имя, т. е. задавать коллекцию, в которой производится поиск, вместо, например, Request(AUTH_USER). Лучше писать Request.Servervariables(AUTH_USER). При этом поиск будет осуществляться значительно быстрее.
Коллекция Form
Коллекция используется для получения элементов формы, переданных с помощью метода post:
Request.Form(element)[(index)I.Count]
где:
element — имя элемента формы, значение которого необходимо получить;
index — необязательный параметр, с помощью которого можно получить несколько значений с одним именем (если их более одного); параметр принимает значения от 1 ДО Request. Form (parameter) .Count.
При больших объемах данных (свыше 100 Кбайт) Request.Form не используется, следует использовать Request.BinaryRead. Приведем пример.
lllilflliliBiliilililliillllili^^
<%
For i = 1 То Request.Form ("FavoriteFlavor").Count
Response.Write Request.Form("FavoriteFlavor") (i) & "<BR>" Next %>
Еще пример.
<%
For i = 1 to Request.Form("FavoriteFlavor").count %>
Request.Form (FavoriteFlavor) = <%= Request.Form("FavoriteFlavor")(i)_ %> <BR>
<% Next %>
И еще пример.
; Код html-формы-
<FORM ACTION = "submit.asp" METHOD = "post">
<Р>Как ваше имя: <INPUT NAME = "firstname" SIZE = 48>
<Р>Какое ваше любимое мороженое: <SELECT NAME = "flavor"> <OPTION>Vanilla <OPTION>Strawberry <OPTION>Chocolate
<OPTION>Rocky Road</SELECT>
<PXINPUT TYPE = SUBMIT>
</FORM>'
Эта форма отправляет такую строку запроса:
firstname=James&flavor=Rocky+Road
Рассмотрим скрипт для обработки submit.asp.
Файл submitasp --' .
Здравствуйте, <%= Request.Form("firstname") %>.
Ваше любимое мороженое <%= Request.Form ("flavor") %>.
assassЗаполним форму ataspl (рис. П2.1).
ass
ass
^ http://localhost/atasp1.html - Microsoft Internet Explorer - (Working Offline}
j-v'EacK • -* ' ЦЭ <] dJ ! £(Seai:h jJFavotiles /^History -J^* J Й * 2J
i|A<tte*f J® http://localhost/atasp1 html
Введите ваше имя: |викгоРия|“
Какой сорт мороженого вы предпочитаете?: (vanilla 3
Р Submit Queiy |
Рис. П2.1. Заполняем форму
Результат работы скрипта показан на рис. П2.2.
•^http://localhost/submit.^^ - Microsoft Inte... Я!я1 ЕЗ
] File Edit View Favorites Took Help
Здравствуйте, Виктория. Ваш любимый сорт мороженого Vanilla.
Рис. П2.2. Результат работы скрипта
Коллекция QueryString
Коллекция Querystring используется для того, чтобы получать значения строки запроса, когда значения передаются серверу в составе URL. Строка запроса располагается после знака ?. Строку запроса можно сформировать внутри ярлыка <а>, например:
<А HREF= "example?string=this is a sarnple">string sample</A>
Запрос co строкой запроса, вставленной в адрес URL, отправляется формой при использовании метода get.
Request. QueryString (variable') [ (index) | .Count)
где:
variable — имя в строке запроса, значение которого нужно получить;
index — необязательный параметр, используется тогда, когда в строке запроса несколько переменных с одним именем.
Рассмотрим пример с файлом atasp3.asp.
; Файл atasp3.asp-'" *
<%
For item = 1 to Request.Querystring("Q").count
Response.Write Request.Querystring("Q")(item) & "<BR>"
Next
%>'
Обратимся к этому файлу, указав такой адрес:
http://localhost/atasp3.ASP?Q=Fred&Q=Sally
На экране будет показан результат:
Fred
Sally
Можно использовать конструкцию, представленную в файле atasp4.asp.
Файл atasp4.asp,|
<%=Request.Querystring %>
Она выведет непроанализированную строку запроса.
Если в адресную строку браузера ввести запрос http://localhost/ atasp4 .asp?Eto=stroka&Zaprosa&vse=taki, TO В ответ получим В окне браузера полную непроанализированную строку запроса:
Eto=stroka&Zaprosa4vse=taki
Коллекция ServerVariables
Эта коллекция содержит заранее определенные серверные переменные (табл. П2.1).
Request.ServerVariables (server environment variable)
Таблица П2.1. Серверные переменные (параметр server environment variable)
Переменная
Описание
ALL_http'
HTTP-заголовок, полученный от клиента
ALL_RAW
Все HTTP-заголовки в том виде, как они есть
APPL_MD_PATH
Путь metabase для приложений ISAPI DLL
APPL_PHYSICAL_PATH
Физический путь, соответствующий пути metabase для APPL_MD_PATH
AUTH_PASSWORD
Значение введенной клиентом в диалоговом окне аутентификации
AUTH_TYPE
Тип аутентификации на сервере
AUTH_USER
Имя пользователя
CERT_COOKIE
Уникальный клиентский идентификатор сертификата
CERT_FLAGS
Нулевой бит переменной устанавливается 1, если существует клиентский сертификат. Первый бит переменной устанавливается 1, если клиентский сертификат авторизован незарегистрированной на сервере службой сертификации
CERT_ISSUER
Кто выдал клиентский сертификат (O=MS, OU=IAS, CN=user name, C=USA)
CERT_KEYSIZE
Глубина шифрования Secure Sockets Layer, например 128
CERT_SECRETKEYSIZE
Количество бит в ключе private key на сервере, например, 1024
CERT_SERIALNUMBER
Серийный номер клиентского сертификата
CERT_SERVER_ISSUER
Кто выдал серверный сертификат
CERT_SERVER_SUBJECT
Поле subject серверного сертификата
CERT_SUBJECT
Поле subject клиентского сертификата
CONTENT_LENGTH
Длина содержимого в соответствии с той, которая указана клиентом
CONTENT_TYPE
Тип данных; используется при запросах, которые содержат дополнительные прикрепленные данные, при запросах HTTP get, post, put
GATEWAY_INTERFACE
Номер стандарта CGI в форме CGUrevision
HTTP_<HeaderName>
Значение HTTP_<HeadrName>
HTTP_ACCEPT
Значение заголовка Accept
HTTP_ACCEPT_LANGUAGE
Заголовок, описывающий язык
Таблица П2.1 (окончание)
Переменная
Описание
НТТР_USER_AGENT
Тип браузера
НТТР_COOKIE
Строка, содержащая информацию cookies
НТТР_REFERER
Адрес оригинала, с которого произошло перенаправление
HTTPS
Принимает значение ON (если используется SSL) или OFF (если SSL нет)
HTTPS_KEYSIZE
Количество бит в ключе шифрования SSL
HTTPS_SECRETKEYSIZE
Количество бит в секретном ключе шифрования сервера
HTTPS_SERVER_ISSUER
Кто выдал сертификат сервера
HTTPS_SERVER_SUBJECT
Поле sub ject
INSTANCE_ID
Идентификатор экземпляра IIS
INSTANCE—META—PATH
Метапуть metabase к IIS
LOCAL—ADDR
Адрес сервера, куда пришел запрос
LOGON_USER
Имя пользователя Windows
PATH_INFO'
Информация о пути
PATH-TRANSLATED
Путь, переведенный в физический путь
QUERY_STRING
Строка запроса (после символа ? в URL)
REMOTE_ADDR
Адрес IP хоста, пославшего запрос
REMOTE_HOST
Имя хоста, пославшего запрос
REMOTE_USER
Имя пользователя, пославшего запрос
REQUEST_METHOD
Метод, используемый в запросе, например для HTTP —ЭТО GET, HEAD, POST И др.
SCRIPT_NAME
Виртуальный путь к срипту
SERVER_NAME
Имя хоста сервера
SERVER_PORT
Порт сервера
SERVER_PORT_SECURE
Имеет значение 0 или 1.1 — при безопасном соединении
SERVER-PROTOCOL
Название и версия протокола в форме protocol/revision
SERVER-SOFTWARE
Версия программного обеспечения сервера в форме name/version
URL
Основной адрес URL
Пример с файлом atasp5.asp..
: Файл atasp5.aspj
<TABLE BORDER="1">
<TR><TD><B>Server Variable</Bx/TDXTDXB>Value</BX/TDX/TR>
<% For Each strKey In Request.Servervariables %>
<TRXTD> <%= strKey %> </TDXTD> <%= Request. Servervariables (strKey) %>
</TDX/TR>
<% Next %>
</TABLE>
Этот пример выводит значения всех серверных переменных.
' Файл atasp6.asp
А HREF = "http://<%= Request.Servervariables("SERVER_NAME") %> /scripts/MyPage.asp">Link to MyPage.asp</A>
Коллекция Cookies
Коллекция Cookies позволяет получать информацию, посылаемую в виде строк cookies в НТТР-запросах:
Request.Cookies(cookie)[(key)[.attribute]
где:
cookie — задает строки фрагментов информации cookie, значение которых надо получить;
key — дополнительный параметр;
attribute — информация о строках cookies.
<%
For Each strKey In Request.Cookies
Response.Write strKey & " = " & Request.Cookies(strKey) & "<BR>"
If Request.Cookies(strKey).HasKeys Then
For Each strSubKey In Request.Cookies(strKey)
Response.Write "->" & strKey & "(" & strSubKey &")="&_ Request.Cookies(strKey)(strSubKey) & "<BR>"
Next End If Next %>
Объект Response
Объект Response используется для того, чтобы посылать ответ клиенту:
Response.collection|property|method1
Коллекции
Стандартная коллекция, используемая при работе с объектом Response, представлена ниже:
Cookies — для задания cookies.
Свойства.
В объекте Response используются свойства:
Buffer — проверяет, буферизуется ли страница;
Cachecontrol — может ли прокси-сервер кэшировать страницу ASP;
Charset — вставка имени кодовой таблицы символов в заголовок HTTP content-type;
ContentType — задает тип ответа;
Expires — срок (продолжительность), по истечении которого страница "устареет" ("устареет" кэш страницы в браузере);
ExpiresAbsolute — абсолютное значение даты, когда "устареет" кэш браузера для данной страницы;
isCiientConnected — проверяет, соединен ли клиент с сервером;
Rics — значение рейтинга содержания картинки;
status — значение строки состояния, возвращаемой сервером.
Методы
Объект Response содержит следующие методы:
AddHeader — задает HTML-заголовок;
AppendToLog — записывает строку о текущем запросе в конец файла логов;
Binarywrite — выводит информацию напрямую без преобразования символов;
clear — очищает буфер;
End — завершает выполнение ASP-файла, возвращая текущий результат;
Flush — посылает клиенту кэшированное содержимое буфера;
Redirect — посылает информацию о перенаправлении браузеру; браузер должен попытаться обратиться к другому URL;
write — выводит переменную в текущий поток вывода HTTP в виде строки.
Метод Write
Метод write используется для вывода в текущий НТТР-поток:
Response.Write variant
где variant — данные для записи, любые данные, "понятные" VB, кроме комбинации символов %> (вместо нее используйте %\>).
Например:
I just want to say <% Response.Write "Hello World." %>
Your name is: <% Response .Write Request.Formfname") %>
■веижмия»^
: Пример с методом WriteQ.■
% Response.Write "<TABLE WIDTH = 100%\>" %>
produces the output
<TABLE WIDTH = 100%>
Объект Server
Большинство методов и свойств объекта Server — это утилиты:
Server.property|method
Свойства
Объект server содержит следующее свойство:
scriptTimeout — предел времени, отведенного для работы скрипта.
Методы
Объект Server содержит методы:
CreateObject — создает экземпляр серверного компонента;
Execute — выполняет ASP-файл;
GetLastError — возвращает объект ASPError;
HTMLEncode — для указанной строки задает HTML-кодировку;
MapPath — сопоставляет виртуальный путь с абсолютным путем;
Transfer — посылает всю текущую информацию другому ASP-файлу для обработки;
URLEncode — применяет метод кодирования URL к строке.
Объект Session
Объект Session содержит информацию о пользователе и его предпочтениях, причем эта информация не уничтожается тогда, когда пользователь переходит от одной страницы сервера к другой. Сервер создает объект Session, когда пользователь, у которого нет сессии, заходит на сервер. Объект сессии уничтожается сервером по истечении срока действия сессии. Одно из наиболее полезных свойств сессии — хранение пользовательских предпочтений:
Session.collection|property|method
Коллекции
Стандартные коллекции, используемые при работе с объектом Session, представлены ниже:
Contents — содержит элементы, добавленные к сессии при помощи команд скрипта;
staticobjects — содержит объекты, созданные при помощи ярлыка <object> в пределах видимости сессии.
Свойства
Объект Session содержит следующие свойства:
codePage — страница кодировки для отображения символов;
lcid — локальный идентификатор;
SessioniD — идентификатор сессии;
Timeout — временной период для сессии в минутах.
Методы
Объект Session содержит методы:
Abandon — уничтожает сессию и высвобождает ресурс, который был занят сессией;
Contents. Remove — удаляет элемент ИЗ коллекции Contents;
Contents.RemoveAii — удаляет все элементы из коллекции Contents.
События
В объекте Session предусмотрены события:
Session_OnEnd;
Session_OnStart.'
Метод Contents.Remove
Удаляет указанный объект из коллекции contents:
Session.Contents.Remove(Item,Index)
где:
item — имя удаляемого объекта;
index — индекс удаляемого объекта.
Пример С методом Remove()
<%'
Session("myName") = " "
Session.Collection.Remove("myName")
%>
Приложение 3
Функции в языке PHP. Краткая справка
Этот справочник не претендует на полноту. В нем отражены лишь некоторые группы функций, которые используются достаточно часто в практической работе.
Функции для работы с сервером Apache
Apache_iookup_uri — выполняет запрос по указанному URI и возвращает информацию.
Apache_note — получает и устанавливает значения в таблице примечаний запроса Apache.
Getaiiheaders — выбор всех заголовков НТТР-запросов.
Пример функция getaiiheaders о$
$headers = getaiiheaders() ;
while (list($header, $value) = each($headers)) ( echo "$header: $value<br>\n";
Функции для работы с массивами
Эти функции используются для манипуляций с массивами, в которых хранятся значения наборов переменных. Поддерживаются как простые одномерные массивы, так и многомерные массивы. Массивы могут быть созданы в явном виде или с помощью вызова тех или иных функций, которые возвращают массивы. Функции для работы с массивами приведены далее.
Array — создает массив.
Следующий пример демонстрирует, как можно создать двумерный массив.
Пример. Функция array()
$fruits = array(
"fruits" => array("a"=>"orange","b"=>"banana","c"=>"apple"), "numbers" => array(1, 2, 3, 4, 5, 6)
"holes" => array("first", 5 => "second", "third")
) ;.
Array_count_values — пересчитывает значения, содержащиеся в массиве.
Array_waik — применение функции к каждому члену массива.
Синтаксис:
int array_walk(array arr, string func)
Применяет функцию с именем func для каждого элемента массива arr.
Пример. Функция array_walk ().
$fruits = array("d"=>"lemon","a"=>"orange","b"=>"banana","c"=>"apple");
function test_alter($iteml) { $iteml = 'bogus';
}
function test_print($item2) { echo "$item2<br>\n";
array_walk($fruits, 'test_print');
array_walk($fruits, ’test_alter'); array_walk($fruits, 'test_print');
Ar sort — сортировка массива в обратном порядке.
Пример. Функция arsortO
$fruits = array("d"=>"lemon", "a"=>"orange","b"=>"banana","c"=>"apple"); arsort($fruits);
for(reset($fruits); $key = key($fruits); next($fruits)) { echo "fruits[$key] = ".$fruits[$key]."\n";
Результат работы примера:
fruits[а] = orange
fruits[d] = lemon fruits[b] = banana fruits[c] = apple Фрукты названы в обратном алфавитном порядке, и поддерживаются связанные с ними индексы.
Asort — сортирует массив и поддерживает связанные индексы.
Пример. Функция asort()
$fruits = array("d"=>"lemon","a"=>"orange","b"=>"banana","c"=>"apple"); asort($fruits);
for(reset($fruits); $key = key($fruits); next($fruits)) { echo "fruits[$key] = ".$fruits[$key]."\n";
}
Результат примера приведет к следующим значениям: fruits[с] = apple fruits[b] = banana fruits[d] = lemon'
fruits[a] = orange
Фрукты названы в алфавитном порядке, и поддерживаются индексы, связанные с каждым элементом массива.
Count — возвращает число элементов массива. Возвращает число элементов в переменной var, возвращает 0, если переменная не определена, возвращает 1, если переменная не является массивом.
Current — возвращает текущий элемент массива. Каждая переменная-массив имеет внутренний указатель, который указывает на один из своих элементов. Кроме того, все элементы в массиве связываются двунаправленным списком указателей для дополнительных целей.
Функция current о возвращает элемент массива, на который в данный момент указывает внутренний указатель. Она не перемещает указатель. Если внутренний указатель установлен на конец списка элементов, функция current () возвращает значение false (ложно).
Внимание
Если массив содержит пустые элементы (0 или "", пустую строку), то для каждого такого элемента функция возвратит значение "false".
Each — возвращает следующую пару ключ/значение из массива.
Пример. Функция each ()'..
$foo = arrayfbob", "fred", "jussi", "jouni");
$bar = each($foo);
Переменная $bar теперь содержит следующие пары ключ/значение:
о => о
1 => "bob"
key => О
value => "bob"■
$foo = array("Robert" => "Bob", "Seppo" => "Sepi");
$bar = each($foo);
Значения переменной $bar таковы:
0 => "Robert"
1 => "Bob"
key => "Robert"
value => "Bob"
Функция eacho, как правило, используется вместе с функцией list о, чтобы просмотреть массив, например, $http_post_vars.
i Пример. Просмотр $http_post_vars с помощью функции each О
echo "Values submitted via POST method:<br>";
while (list($key, $val) = each($HTTP_POST_VARS)) ( echo "$key => $val<br>";
}
End — устанавливает внутренний указатель массива на последнем элементе. Функция end () перемещает внутренний указатель на последний элемент массива.
□ Key — выбирает ключ из ассоциативного массива key о и возвращает индекс элемента в текущей позиции массива.
Ksort — сортирует массив по ключам.
Пример. Функция icsortO ’ ’’"r> ifc-'^-xr.t/*^ -*??.
$fruits =
array("d"=>"lemon","a"=>"orange","b"=>"banana","c"=>"apple");
ksort($fruits);
for(reset($fruits); $key = key($fruits); next($fruits)) { echo "fruits[$key] = ".$fruits[$key]."\n";
}
После выполнения примера получаем результат:
fruits[а] = orange
fruits[b] = banana■
fruits[c] = apple fruits[d] = lemon
□ List — связывает переменные, как если бы они были массивом.
<table>
<tr>
<th>Employee name</th>
<th>S alary</th>
</tr>
<?php
$result = mysql($conn, "SELECT id, name, salary FROM employees");
while (list($id, $name, $salary) = mysql_fetch_row($result)) { print(" <tr>\n".
" <tdxa href=\"info.php?id=$id\">$name</ax/td>\n".
" <td>$salary</td>\n”.
" </tr>\n");
}
?></table>
□ Next — передвигает внутренний указатель массива.
Возвращает следующий элемент массива, по сравнению с текущей позицией, на которую указывает внутренний указатель, или значение false, если в массиве больше нет элементов (false также будет возвращен для всех пустых элементов массива). Для просмотра массива, содержащего пустые элементы, рекомендуется использовать функцию each о.
Функция next о ведет себя подобно функции current о, с одной лишь разницей. Она передвигает внутренний указатель массива на один элемент вперед прежде, чем возвратить элемент. Это означает, что функция next () возвращает значение следующего элемента и передвигает на него
внутренний указатель массива. Если при обращении к следующему элементу обнаружен конец массива, то next о возвращает значение false.
роз — возвращает текущий элемент массива. Это псевдоним для current ().
Prev — перемещает внутренний указатель массива назад.
Возвращает предыдущий элемент массива или значение false, если перед текущим элементом нет больше элементов (и для пустых элементов массива).
Функция prev о ведет себя подобно функции nexto, за исключением того, что она переводит внутренний указатель массива на одну позицию назад, а не вперед.
Reset — устанавливает внутренний указатель массива на первом элементе. Синтаксис:
mixed reset(array array)
Функция reset () возвращает внутренний указатель массива на первый элемент.
Rsort — сортирует массив в обратном порядке.
Синтаксис:
void rsort(array array) Сортирует массив в обратном порядке (по убыванию).
| Пример. Функция rsort О
$fruits = array("lemon","orange","banana","apple");
rsort($fruits);
for(reset($fruits); ($key,$value) = each($fruits);) { echo "fruits[$key] = ".$value."\n"; }'
Этот пример выведет
fruits[0] = orange fruits[1] = lemon fruits[2] = banana fruits[3] = apple Фрукты отсортированы в обратном алфавитном порядке.
Sizeof — получает размер массива.
Синтаксис:
int sizeof(array array) Возвращает число элементов списка.
sort — сортирует массив.
Синтаксис:
void sort(array array)
Эта функция сортирует массив — все элементы по окончании ее работы будут расположены по возрастанию.
. Пример. Функция sort()■ \
$fruits = array("lemon”,"orange","banana","apple");
sort($fruits);
for(reset($fruits); $key = key($fruits); next($fruits)) { echo "fruits[$key] = ".$fruits[$key]."\n";
}'
Результат выглядит так:.
fruits[0] = apple
fruits[1] = banana
fruits[2] = lemon
fruits[3] = orange
Фрукты будут отсортированы, по возрастанию в алфавитном порядке.
uasort — сортирует массив с использованием функций сравнения, определенных пользователем, и поддержкой соответствия индексов элементов массива с исходным порядком элементов в массиве (важно для ассоциативных массивов).
Синтаксис:
void uasort(array array, function cmp_function)
Эта функция сортирует массив так, что индексы массива поддерживают исходные соответствия с элементами массива. Функции сравнения задает пользователь.
uksort — сортирует массив по ключам с использованием функций сравнения, определенных пользователем.
Синтаксис:
void uksort(array array, function cmp_function)
Эта функция отсортирует массив, используя функции сравнения, определенные пользователем. Если массив должен быть отсортирован в соответствии с некоторыми нетривиальными критериями, то можно использовать эту функцию.
function mycompare($a, $b) {
if ($a == $b) return 0;
return ($a > $b) ? -1 : 1;
}
$a = array(4 => "four", 3 => "three", 20 => "twenty", 10 => "ten"); uksort($a, mycompare);
while(list($key, $value) = each($a)) ( echo "$key: $value\n";
}
Результат работы:
twenty
ten
four
three
Usort — сортирует массив по значениям, используя функции сравнения, определенные пользователем.
Синтаксис:
void usort(array array, function cmp_function)
Эта функция отсортирует массив по значениям, используя функции сравнения, определенные пользователем. Если массив, который вы хотите отсортировать, должен сортироваться по некоторым нетривиальным критериям, то можно использовать эту функцию.
Пример. Функция usort(),.- ■ ■
function cmp($a,$b) (
if ($а == $b) return 0;
return ($a > $b) ? -1 : 1;
}
$a = array (3,2, 5, 6,1) ;
usort($a, cmp) ;
while (list($key,$value) = each($a)) ( echo "$key: $value\n";
}
Математические функции BCMath для работы с числами произвольной точности
Bcadd — сложение двух чисел произвольной точности.
Синтаксис:
string bcadd(string левый операнд, string правый операнд, int [масштаб])
Функция прибавляет левый операнд К правому операнду И ВОЗВрЗЩЗСТ сумму типа string. Параметр масштаб используется для того, чтобы установить количество разрядов после десятичной отметки.
Вссотр — сравнение двух чисел произвольной точности.
Синтаксис:
int bccomp(string левый операнд, string правый операнд, int [масштаб])
Сравнивает левый операнд с правым операндом и возвращает результат типа integer.
Bcdiv — операция деления для двух чисел произвольной точности.
Синтаксис:
string bcdiv(string левый операнд, string правый операнд, int [масштаб])
Делит левый операнд на правый операнд и возвращает результат типа string. Параметр масштаб устанавливает количество цифр после десятичной точки в результате.
Bcmod — получение модуля числа произвольной точности.
Синтаксис:
string bcmod(string левый операнд, string модуль)
Получение остатка от деления первого параметра на второй.
Bcmui — операция умножения для двух чисел произвольной точности.
Синтаксис:
string bcmui(string левый операнд, string правый операнд, int [масштаб])
Умножает левый операнд на правый операнд и возвращает результат типа string. Параметр масштаб устанавливает количество цифр после десятичной отметки в результате.
□ Bcpow — возведение одного числа произвольной точности в степень другого.
Синтаксис:
string bcpow(string х, string у, int [масштаб])
Возведение х в степень у. Параметр масштаб может использоваться для установки количества цифр после десятичной отметки в результате.
Bcscaie — устанавливает масштаб по умолчанию для всех математических функций.
Синтаксис:
string bcscaie(int [масштаб])
Эта функция устанавливает заданный по умолчанию параметр масштаб для всех последующих математических ВС-функций, которые явно не определяют параметр масштаба.
Bcsqrt — получение квадратного корня числа произвольной точности.
Синтаксис:
string bcsqrt(string операнд, int [масштаб])
Возвращает квадратный корень переменной операнд.
Bcsub — вычитает одно число произвольной точности из другого.
Синтаксис:
string bcsub(string левый операнд, string правый операнд, int
[масштаб])
Вычитает правый операнд из левого операнда и возвращает результат типа string.
Функции для работы с календарем
Календарное расширение в PHP представляет серию функций, которые упрощают преобразование между разными календарными форматами. Посредником для преобразования является дневной юлианский счет. Дневной юлианский счет отличается от юлианского календаря! Более подробно о календарной системе смотрите на сайте http://genealogy.org/~scottlee/ cal-overview.html.
□ JDToGregorian — преобразование дневного юлианского счета в григорианскую дату.
Синтаксис:
string jdtogregorian(int julianday)
Преобразование дневного юлианского счета в григорианскую дату в формате "месяц/день/год".
□ GregorianTojd — преобразовывает григорианскую дату в дневной юлианский счет.
Синтаксис:
int gregoriantojd(int month, int day, int year's
Пример. Календарные функции:
<?php
$jd = GregorianToJD(10,ll,1970);
echo("$jd\n");
$gregorian = JDToGregorian($jd) ;
echo("$gregorian\n");
□ JDToJulian — преобразовывает дату юлианского календаря на дневной юлианский счет.
Синтаксис:
string jdtojulian (int julianday")
Преобразование дневного юлианского счета в строку, содержащую дату юлианского календаря в формате "месяц/день/год". .
□ JulianToJD — преобразовывает дату юлианского календаря в дневной юлианский счет.
Синтаксис:
int juliantojd(int month, int day, int year’s
Правильно заданный диапазон для юлианского календаря 4713 г. до н. э. до 9999 г. н. э.
jDToJewish — преобразовывает дневной юлианский счет в еврейский календарь.’
Синтаксис:
string jdtojewish(int juliandayS
jewishToJD — преобразовывает дату в еврейском календаре на дневной юлианский счет.
Синтаксис:
int jewishtojd(int month, int day, int year)
JDToFrench — преобразовывает дневной юлианский счет во французский республиканский календарь.
Синтаксис:
string jdtofrench (int month, int day, int year's
FrenchToJD — преобразовывает дату французского республиканского календаря в дневной юлианский счет.
Синтаксис:
int frenchtojd(int month, int day, int year)
jDMonthName — возвращает название месяца.
Синтаксис:
string jdmonthname(int julianday, int mode)
JDDayOfWeek — возвращает день недели.
Синтаксис:
mixed jddayofweek(int julianday, int mode)
Возвращает день недели. Может возвратить строку (string) или int в зависимости от способа (mode):
0 — возвращает номер дня в неделе (О=воскресенье, 1=понедельник и т. п.);
1 — возвращает строку (string) — день недели.
Функции даты и времени
Checkdate — проверяет правильность даты/времени.
Синтаксис:
int checkdate(int month, int day, int year)
Возвращает значение true, если проверяемая дата правильна, иначе — false. Проверяет правильность даты, заданной аргументами. Дата считается правильной, если параметры находятся в пределах:
год между 1900 и 32767 включительно;
месяц между I и 12 включительно;
день находится в диапазоне разрешенных дней данного месяца.
Високосные года учитываются.
Date — форматирование локального времени/даты.
Синтаксис:
string date(string format, int timestamp)
Возвращает строку, отформатированную согласно данной строке format, . используя данную временную метку timestamp или текущее локальное время, если не задана временная метка.
В форматной строке format ИСПОЛЬЗуЮТСЯ СЛСДуЮЩИС СИМВОЛЫ.
а — "ат" или "рпГ;
. а - "АМ" или "РМ";'
d — день месяца, цифровой, 2 цифры (на первом месте ноль);
о — день недели, текстовый, 3 буквы; например, "Fri";
F — месяц, текстовый длинный; например, "January";
h — час, цифровой, 12-часовой формат;
н — час, цифровой, 24-часовой формат;
i — минуты, цифровой;
j — день месяца, цифровой, без начальных нулей;
1 (строчная 'L') — день недели, текстовый длинный; например, "Friday";
ш — месяц, цифровой;
м — месяц, текстовый, 3 буквы; например, "Jan";
s — секунды, цифровой;
s — английский порядковый суффикс, текстовый, 2 символа; например, "th", "nd";
и — секунды с начала века;
у — год, цифровой, 4 цифры;
w — день недели, цифровой, 0 означает воскресенье;
у — год, цифровой, 2 цифры;
z — день года, цифровой; например, "299".
Нераспознанные символы в форматной строке будут печататься как есть.
Функции date () и mktimeо (см. описание этой функции ниже) возможно использовать вместе для того, чтобы найти даты в будущем или прошлом.
Пример 1. Функции date () И mktime ();
print(date("1 dS of F Y h:i:s A"));
print("July 1, 2000 is on a ". date("l", mktime(0,0,0,7,1,2000)));
.Пример 2. Функции date () И mktime ()
$tomorrow = mktime(0,0,0,date("m"),date("d")+1,date("Y"));
$lastmonth = mktime(0,0,0,date("m")-1,date("d"),date("Y"));
$nextyear = mktime(0,0,0, date("m"), date("d", date("Y")+1);
strftime — форматирует локальное время.
Синтаксис:
string strftime(string format, int timestamp')
Возвращает строку, отформатированную согласно данной форматной строке format, используя данную временную метку timestamp или текущее локальное время, если метка не задана. Названия месяцев, недель и другие, зависящие от того, как должна быть представлена строка даты, зависят также и от локальных параметров, которые могут быть заданы С ПОМОЩЬЮ функции setlocale ().
В форматной строке forma t следует использовать следующие спецификаторы преобразований:
%а — сокращенное название дня недели согласно текущему locale;
%д — полное название дня недели согласно текущему locale;
%ь — сокращенное название месяца согласно текущему locale;
• %в — полное название месяца согласно текущему locale;
% с — предпочтительное представление даты и времени для текущего locale;
%d — день месяца как десятичное число (в диапазоне от 0 до 31);
%н — час как десятичное число в 24-часовом формате (в диапазоне от 00 до 23);
%i — час как десятичное число в 12-часовом формате (в диапазоне от 01 до 12);
% j — день года как десятичное число (в диапазоне от 001 до 366);
%т — месяц как десятичное число (в диапазоне от 1 до 12);
%м — минуты как десятичное число;
%р — 'ат' или 'рт' согласно текущему времени или соответствующие строки для текущего locale;
%s — секунды как десятичное число;
%и — номер недели текущего года как десятичное число, начиная с первого воскресенья в качестве первого дня первой недели;
%w — номер недели текущего года как десятичное число, начиная с первого понедельника в качестве первого дня первой недели;
%w — день недели как целое число, воскресенье — 0-й день;
%х — предпочитаемое представление даты для текущего locale, не включающее время;
%х — предпочитаемое представление времени для текущего locale, не включающее дату;
%у — год как десятичное число без столетия (в диапазоне от 00 до 99);
%y — год как десятичное число, включая столетие;
%z — временная зона или название, или сокращение;
% % — символ '%'.
) Пример. Функция strftime ();
setlocale("LC_TIME", "С");
print(strftime("%A in Finnish is "));
setlocale("LC_TIME", "fi");
print(strftime("%A, in French ") ) ;
setlocale("LC_TIME", "fr”);
print(strftime("%A and in German "));
setlocale("LC_TIME", "de");
print(strftime("%A.\n"));
Пример будет работать, если у вас установлены соответствующие locale.
Getdate — получает информацию о дате/времени.
Синтаксис:
array getdate(int timestamp)
Возвращает ассоциативный массив, содержащий информацию о дате со следующими элементами:
"seconds" — секунды;
"minutes" — МИНУТЫ;.
"hours" — часы;
"mday" — день месяца;
"wday" — день недели, цифровой;
"mon" — месяц, цифровой;
"year" — год, цифровой;
"yday" — день года, цифровой; т. е. "299";
"weekday" — день недели, текстовый, полный; т. е. "Friday";
"month" — месяц, текстовый, полный; т. е. "January".
Gmdate — форматирует GMT/CUT время/дату.
Синтаксис:
string gmdate(string format, int timestamp)
Эта функция аналогична функции date о за исключением того, что время возвращается в гринвичском формате Greenwich Mean Time (GMT).
Например, при запуске в Финляндии (GMT +0200), первая строка ниже напечатает "Jan 01 1998 00:00:00", в то время как вторая строка напечатает "Dec 31 1997 22:00:00".
i Пример. Функция gradate ();
echo date("M d Y H:i:s",mktime(0,0,0,1,1,1998));
echo gradate("M d Y H:i:s",mktime(0,0,0,1,1,1998));
Mktime — получает временную метку UNIX для даты.
Синтаксис:
int mktime(int hour, int minute, int second, int month, int day, int year)
. Предупреждение^
Обратите внимание на необычный порядок аргументов, который отличается от порядка аргументов в вызове функции mktime () в UNIX.
Возвращает временную метку UNIX. Эта временная метка является целым числом, равным количеству секунд между эпохой UNIX (1 января 1970) и указанным временем.
Аргументы могут быть опущены справа налево (т. е. нельзя опустить четвертый параметр функции, не пропустив 5-ый и 6-ой параметры); каждый опущенный таким образом аргумент будет установлен в текущую величину согласно локальной дате и времени.
Функция mktime о полезна при арифметических действиях с датой и ее проверкой, она будет автоматически вычислять корректную величину для вышедших за границы параметров. Например, каждая из. следующих строк возвращает строку "Jan-01-1998".
Пример. Функция mktime ()'
echo date("M-d-Y", mktime(0,0,0,12,32,1997));
echo date("M-d-Y", mktime(0,0,0,13,1,1997));
echo date("M-d-Y", mktime(0,0,0,1,1,1998));
Gmmktime — получает временную метку UNIX для даты в GMT.
Синтаксис:
int gmmktime(int hour, int minute, int second, int month, int day, int year)
Идентична функции mktimeo за исключением передаваемых параметров, представляющих дату в GMT.
Time — возвращает текущую временную метку UNIX.
Синтаксис:
int time(void)
Возвращает текущее время, измеренное в числе секунд с эпохи UNIX (1 января 1970 00:00:00 GMT).
Microtime — возвращает текущую временную метку UNIX в микросекундах.
Синтаксис:
string microtime(void)
Возвращает строку "msec sec , где sec текущее время ^ измеренное в числе секунд с эпохи UNIX (0:00:00 1 января, 1970 GMT), a msec — это часть строки в микросекундах.
Функции для работы с каталогами
chdir — смена каталога.
Синтаксис:
int chdir(string directory)
Изменяет текущий PHP-каталог на directory. Возвращает false, если не может изменить каталог, и true, если смена произошла.
Dir — класс каталога. .
Синтаксис:
new dir(string directory)
Псевдообъектно-ориентированный механизм для чтения каталога. Открывает каталог из directory. Если каталог открыт, то метка ресурса каталога может быть использована вместе с другими функциями работы с каталогом. Например, с функциями readdir о, rewinddir () и closedir().
Пример. Функция dir ()
$d = dir("/etc");
echo "Handle: ".$d->handle."<br>\n";
echo "Path: ".$d->path."<br>\n";
while($entry=$d->read()) { echo $entry."<br>\n";
}
$d->close() ;
closedir — закрыть дескриптор каталога.
Синтаксис:
void closedir (int dir_handle')
Закрывает поток каталога, обозначенный как dir_handie. Поток предварительно должен быть открыт функцией opendir ().
Opendir — открыть дескриптор каталога.
Синтаксис:
int opendir (string path1)
Возвращает ресурс (handle) каталога, который в последующем используется В функциях closedir() , readdir() И rewinddir() .
□ Readdir — чтение данных из каталога по метке ресурса handle. Синтаксис:
string readdir (int dir_handle'j
Возвращает имя следующего файла из каталога.
| Пример. Вывод всех файлов в текущем каталоге।
<?php
$handle=opendir('.');
echo "Directory handle: $handle\n";.
echo "Files:\n"; while ($file = readdir($handle)) { echo "$file\n";
closedir($handle); ?>
□ Rewinddir — возврат к началу данных каталога по метке ресурса handle. Синтаксис:
void rewinddir(int dir_handle^
Возвращает поток каталога, обозначенный как dir_handie, в начало.
Функции для работы с файловой системой
Basename — возвращает из полного пути имя файла.
Синтаксис:'
string basename(string path)
Получив строку, содержащую путь к файлу, данная функция возвратит базовое имя файла.
В Windows оба слеша — прямой (/) и обратный (\) — используются как разделители при задании пути. В других системах — это только прямой слеш (/).
Пример. Функция basename ():
$path = "/home/httpd/html/index.php3";
$file = basename($path); // $file устанавливается в "index.php3"
chgrp — изменяет файловую группу, к которой относится файл.
Синтаксис:
int chgrp(string filename, mixed group)
Пытается изменить группу файла filename на group. Возвращает true при успешном завершении; в противном случае — false.
В Windows ничего не происходит и возвращается значение true.
chmod — изменяет режим файла.
Синтаксис:
int chmod(string filename, int mode) .
Пытается изменить режим файла, указанный в filename, на mode.
Заметим, что mode не присваивает автоматически восьмеричное значение, необходим префикс (0):
chmod("/somedir/somefile", 755);// десятичный;
// возможно неправильный
chmod("/somedir/somefile", 0755);// восьмеричный;
// корректное значение режима
Возвращает значение true при успешном завершении; в противном случае — false.
Chown — изменяет владельца файла.
Синтаксис:
int chown(string filename, mixed user)
Пытается изменить владельца файла filename на пользователя user.
Возвращает значение true при успешном завершении; в противном случае — false.
В Windows ничего не выполняется и возвращается значение true.
Ciearstatcache — очищает кэш статистики файла.
Синтаксис:
void clearstatcache(void)
Вызовы системных функций stat () или Istat () в большинстве систем требуют заметных ресурсов. Поэтому результаты последнего вызова любой из функций (см. ниже) сохраняются для последующего использования при вызове этой же функции для этого же файла. Если вы желаете инициировать новый кеш, например, в случае, когда к файлу было много обращений по проверке статуса или файл был изменен, используйте эту функцию для очистки памяти результатов вызовов.
См. также функции stat о, Istat (), f ile_exists () , is_writeable(), is_readable(), is_executable(), is_file(), is_dir(), is_link(), fileatimeO, filemtime(), fileinodeO, filegroupO, fileowner (), filesize(), filetype() И fileperms().■
Copy — копирует файл.
Синтаксис:
int copy(string source, string dest)
Создает копию файла. Возвращает значение true при успешном завершении; в противном случае — false.
: Пример. Функция сору () '
; j
if (1 copy($file, $file.’.bak*)) {
print("failed to copy -$file...<br>\n");
}
Dirname — указывает путь к файлу.
Синтаксис:
string dirname (string path1)
Получив строку, содержащую путь к файлу, данная функция возвратит папку, содержащую файл.
[ Пример. Функция dirname ()
$path = "/etc/passwd";
$file = dirname($path); // $file is set to "/etc"
Fciose — закрывает указатель на файловый ресурс. *
Синтаксис:
int fciose(int fp)
Указатель на файл fp закрывается.
Возвращает значение true при удачной операции и false при ошибке.
Указатель должен быть действующим и указывать на файл, успешно открытый функцией f open О ИЛИ f sockopen о .
Feof — проверка на достижение указателем конца файла.
Синтаксис:
int feof(int fp)
Возвращает значение true, если указатель файла равен EOF; в противном случае возвращается false.
Указатель должен быть действующим и указывать на файл, успешно открытый функцией fopen (), рореп () или fsockopen ().
Fgetc — получает символ из файла.
Синтаксис:
string fgetc(int fp)
Возвращает строку, содержащую один символ, прочитанный по файловому указателю fp. При достижении EOF возвращается значение false.
Указатель должен быть действующим и указывать на файл, успешно открытый функцией fopen (), рореп () ИЛИ fsockopenf).
Fgets — получает строку по указателю на файл.
Синтаксис:
string fgets (int fp, int length1)
Возвращает строку — читается по одному байту из файла, указанному в fp. Чтение заканчивается, если прочитано length символов (1 байт прочитается в любом случае), или чтение идет до символов перевода строки или возврата караетки, или до EOF. При ошибке возвращается значение false. Указатель должен быть действующим и указывать на файл, успешно открытый функцией fopen о , рореп о или fsockopen о .
Fgetss — получает строку по указателю файла и вырезает ярлыки HTML.
Синтаксис:
string fgetss (int fp, int length1)
File — читает файл в массив.
Синтаксис:
array file(string filename)
Fiie_exists — проверяет существование искомого файла.
Синтаксис:
int file_exists(string filename)
Возвращает значение true, если файл, определенный в filename, существует; иначе — false.
Fileatime — время последнего обращения к файлу.
Синтаксис:
int fileatime (string filename')
Возвращает время последнего успешного обращения к файлу или false в случае ошибки.
Filectime — время последнего изменения файла.
Синтаксис:
int filectime(string filenames
Возвращает время последего изменения файла или false в случае ошибки.
Filegroup — группа файла.
Синтаксис:
int filegroup(string filenames
Возвращает id группы владельца файла или false в случае ошибки.
Fileinode — значение параметра inode для файла.
Синтаксис:
int fileinode (string filename')
Возвращает значение параметра inode для файла или false в случае ошибки.
Filemtime — время модификации файла.
Синтаксис:
int filemtime (string filename's
Возвращает время последего изменения файла или false в случае ошибки.
Fileowner — владелец файла.
Синтаксис:
int fileowner (string filename")
Возвращает id пользователя, владельца файла, или false в случае ошибки.
Fileperms — разрешения для файла.
Синтаксис:
int fileperms (string filename's
Возвращает разрешения, установленные для файла, или false в случае ошибки.
Filesize — размер файла.
Синтаксис:
int filesize(string filename^
Возвращает размер файла или false в случае ошибки.
Filetype — тип файла.
Синтаксис:
string filetype(string filename)
Возвращает тип файла. Возможные значения:
fifo;
char;
dir;
block;
link;
file;
unknown.
В случае ошибки возвращется значение false.
Fopen — открывает файл или URL.
Синтаксис:
int fopen(string filename, string mode)
Если строка filename начинается c "http://" (без учета регистра), то открывается соединение по протоколу HTTP с указанным сервером и возвращается указатель файла. Если filename начинается с "ftp://" (без учета регистра), открывается ftp-соединение с указанным сервером и возвращается указатель на искомый файл. Если сервер не поддерживает режим пассивного ftp, данная операция завершится ошибкой. Можно открывать файлы как для чтения, так и для записи через ftp (но не обе операции одновременно).
Если filename начинается как-нибудь иначе, открывается файл локальной файловой системы и возвращается указатель на открытый файл.
Если при открытии файла происходит ошибка, функция возвращает значение false.
Значение строки mode выбирается из следующего списка:
'г' — открыть только для чтения, помещает указатель на начало файла;
• г+' — открыть для чтения и для записи, помещает указатель на начало файла;'
'w' — открыть только для записи, помещает указатель на начало файла и очищает все содержимое файла. Если файл не существует, создается новый файл;
'w+' — открыть для чтения и для записи, помещает указатель на начало файла и очищает все содержимое файла. Если файл не существует, создается новый файл;
'а' — открыть только для записи, помещает указатель на конец файла. Если файл не существует, создается новый файл;
'а+' — открыть для чтения и для записи, помещает указатель на конец файла. Если файл не существует, создается новый файл.
; Пример. Функция fopen ()\
$fp = fopen("/home/rasmus/file.txt", "г");
$fp = fopen("http://www.php.net/", "r");
$fp = fopen("ftp://user:password@example.com/", "w");
Если вы испытываете проблемы с чтением и записью в файл, используя PHP как серверный модуль, помните, что ваши файлы и директории должны быть доступными для серверных процессов.
$fp = fopen( "с: WdataWinfo.txt", "г");
Fpassthru — выводит все данные из указателя файла.
Синтаксис:
int fpassthru(int fp)
Функция читает файл до EOF и записывает результат на стандартное устройство вывода. При возникновении ошибки функция fpassthru () возвращает false.
Файловый указатель должен быть действующим и указывать на файл, успешно открытый с помощью функций fopeno, popen(), fsockopenO. Файл, закрытый fpassthru(), не читается, оставляя fp неиспользованным.
Fputs — записывает в файл.
Синтаксис:
int fputs(int fp, string str, int [length])
Функция fputs () — это псевдоним для fwrite(). Обе функции полностью идентичны. Заметим, что параметр length необязателен и при его отсутствии записывается вся строка str.
Fread — бинарное чтение файла.
Синтаксис:
string fread(int fp, int length")
Функция fread о читает байты из файла, на который ссылается fp, до length. Чтение заканчивается, когда прочитано length байт или достигнут EOF.
// получить содержимое файла в строку
$filename = "/usr/local/something.txt";
$fd = fopen($filename, "г") ;
$contents = fread($fd, filesize($filename)); fclose($fd);
Fseek — организует поиск в файле.
Синтаксис:
int fseek(int fp, int offset)
Для файла fp устанавливает указатель в потоке файла на величину смещения offset в байтах. Эквивалентно вызову функции fseek(fp, offset, SEEK_SET) в языке С.
При удачном выполнении возвращает 0, в противном случае — значение —1. Не используется для файловых указателей, возвращенных fopen о при использовании форматов "http://" или "ftp://".
Fteii — текущая позиция указателя в файле.
Синтаксис:
int ftell(int fp)
Возвращает позицию указателя в файле, на который ссылается fp, т. е. смещение в потоке файла. При возникновении ошибки возвращается значение false. Файловый указатель должен быть действующим и указывать на файл, успешно открытый при помощи функций fopen о или рореп().
Fwrite — бинарная запись в файл.
Синтаксис:
int fwrite(int fp, string string, int [length])
Функция fwrite о записывает содержимое string в файловый поток, указанный fp. Если аргумент length присутствует, запись останавливается после записи байта length или после записи всей строки string.
is_dir — проверка, является ли имя, указанное в строке filename, каталогом.
Синтаксис:.
bool is_dir(string filename)
Возвращает значение true, если filename существует и это каталог.
is_executabie — файл относится к классу исполнимых.
Синтаксис:
bool is_executable(string filename)
Возвращает значение true, если filename существует и является исполнимым файлом.
is fiie — файл относится к классу обычных файлов.
Синтаксис:
bool is_file(string filename)
Возвращает значение true, если filename существует и является обычным файлом.
is link — файл относится к файлу символических ссылок.
Синтаксис:
bool is_link(string filename)
Возвращает значение true, если filename существует и является символической ссылкой.
is_readabie — файл относится к классу читаемых.
Синтаксис:
bool is_readable(string filename)
Возвращает значение true, если filename существует и является доступным для чтения.
is writeabie — файл относится к классу записываемых.
Синтаксис:
bool is_readable(string filename)
Возвращает значение true, если файл существует и доступен для записи.
Link — создает ссылку.
Синтаксис:
int link(string target, string link)
Linkinfo — информация о ссылке.
Синтаксис:
int linkinfo(string path)
Функция получает информацию о ссылке.
Mkdir — создает каталог.
Синтаксис:
int mkdir(string pathname, int mode)
Функция пытается создать каталог, указанный в pathname. Mode указывается в восьмеричной системе, число должно начинаться с 0.
mkdir("/path/to/my/dir", 0700);
Возвращает значение true при успешном выполнении и false при ошибке.
pciose — закрывает процесс файлового указателя.
Синтаксис:
int pciose(int fp)
Закрывает файловый указатель к файловому потоку-ресурсу, открытому с помощью функции рореп (). Файловый указатель должен быть действующим и возвращенным функцией рореп ().
рореп — открывает процесс файлового указателя.
Синтаксис:
int рореп(string command, string mode)
Открывает указатель ресурса, файловый указатель, идентичный возвращаемому функцией fopen (), но этот указатель мононаправленный (может использоваться только для чтения или только для записи) и должен быть закрыт функцией pciose о. Этот указатель можно использовать с fgetst), fgetss()H fputs(). При возникновении ошибки функция рореп о возвращет значение false.
| Пример. Функция рореп ()|
$fp = рореп("/bin/ls", "г")
Readfile — ВЫВОД файла.
Синтаксис:
int readfile(string filename)
Читает файл и записывает его на стандартное устройство вывода.
Возвращает количество прочитанных байтов. В случае возникновения ошибки возвращается значение false. Если filename начинается с "http://" (без учета регистра), открывается соединение HTTP к указанному серверу и текст ответа выводится на стандартное устройство вывода. Если filename начинается как-нибудь иначе, будет открыт файл локальной файловой системы и его содержимое выведется на стандартное устройство вывода.
Readlink — содержимое ресурса-ссылки.
Синтаксис:
string readlink(string path)
Функция readlink о работает аналогично функции readlink в языке С и возвращает содержимое символической ссылки pa th или 0 в случае ошибки.
Rename — переименовывает файл.
Синтаксис:
int rename(string oldname, string newname)
Функция пытается переименовать файл из oidname в newname. Возвращает значение true при успешном выполнениии и false при сбое.
Rewind — возвращает в начало внутреннего указателя ресурса.
Синтаксис:
int rewind(int fp)
Позиционирует файловый указатель для fp на начало потока файла.
При возникновении ошибки возвращается 0.
Rmdir — удаляет каталог.
Синтаксис:
int rmdir(string dirname)
Пытается удалить каталог. Каталог должен быть пустой. При возникновении ошибки возвращается 0.
stat — информация о файле.
Синтаксис:
array stat(string filename)
Собирает статистику о файле filename. Возвращает массив информации о файле со следующими элементами:
устройство;
параметр inode;
номер ссылки;
id пользователя или владельца;
id группы, к которой относится пользователь, создавший файл;
тип устройства;
размер в байтах;
время последнего доступа;
время последней модификации;
время последнего изменения;
размер блока для I/O файловой системы (только для систем, поддерживающих задание размера блока st_blksize; в других системах (Windows) возвращается — 1);
количество занятых блоков.
Lstat — информация о файле или символической ссылке.
Синтаксис:
array Istat(string filename)
Собирает информацию о файле filename. Эта функция идентична stat (), но если filename — это символическая ссылка, то возвращается статус символической ссылки, а не статус файла, на который указывает данная ссылка. Возвращает массив статистической информации со следующими элементами:
устройство;
параметр inode;
число ссылок;
id пользователя или владельца;
id группы владельца;
тип устройства;
размер в байтах;
время последнего доступа;
время последней модификации;
время последнего изменения;
размер блока для I/O файловой системы;
количество занятых блоков.
Symiink — создает ссылку.
Синтаксис:
int symiink(string target, string link)
Функция symiink о создает символическую ссылку на файл target с указанным именем link.
Tempnam — создает уникальное имя файла.
Синтаксис:
string tempnam(string dir, string prefix')
Создает уникальное имя файла в указанном каталоге. Если каталог не существует, tempnam о может сгенерировать имя файла во временном каталоге системы.
Возвращает новое временное имя файла или нулевую строку при ошибке.
Пример. Функция tempnam ()■i
$tmpfname = tempnam("/tmp", "FOO");
Touch — устанавливает время модификации файла.
Синтаксис:
int touch(string filename, int time)
Пытается установить время модификации файла filename в значение time. Если опция time отсутствует, используется текущее время. Если файл не существует, то он создается. Возвращает значение true при успешном выполнении и false в обратном случае.
Umas к — устанавливает текущую маску umask.
Синтаксис:
int umask (int mask's
Функция umask о устанавливает текущую маску umask.
unlink — удаляет файл.
Синтаксис:
int unlink (string filename')
Удаляет файл filename. Аналогична функции Unix С uniinkt). Возвращает 0 или false при ошибке.
Почтовые функции
Mail — пересылает почту.
Синтаксис:
bool mail(string to, string subject, string message, string
additional_headers)
Функция mailt) позволяет отсылать почту. Mail о автоматически посылает сообщение, содержащееся в message, адресату, указанному в to. Несколько получателей могут быть указаны в поле to в виде строки с адресами, разделенными пробелами.
I Пример 1. Посылка почтыj
mail("yes@on.ru", "Моя тема", "Строка 1\пСтрока 2\пСтрока 3") ;
Если задан четвертый строковый аргумент, он автоматически вставляется в конец заголовка. Обычно это используется при добавлении дополнительных полей в заголовок. Несколько дополнительных полей разделяются символом новой строки \п.
i Пример 2. Посылка почты с дополнительными полями заголовкаj
mail("ssb@guardian.ru", "the subject", $message, "From:
webmaster@$SERVER_NAME\nReply-To: webmaster@$SERVER_NAME\nX-Mailer: PHP/". phpversion());
Математические функции
Abs — абсолютная величина.
Синтаксис:
mixed abs (mixed number1)
Возвращает абсолютную величину числа.
Acos — арккосинус.
Синтаксис:
float acos (float arg")
Возвращает арккосинус аргумента в радианах.
Asin — арксинус.
Синтаксис:
float asin( float arg1)
Возвращает арксинус аргумента в радианах.
Atan — арктангенс.
Синтаксис:
float atan (float arg")
Возвращает арктангенс аргумента в радианах.
Atan2 — арктангенс от двух переменных.
Синтаксис:
float atan2(float у, float х)•
Эта функция вычисляет арктангенс от двух переменных х и у. Функция аналогична вычислению арктангенса значения у/х, за исключением того, что знаки обоих аргументов здесь существенны и используются для определения сектора результата. Функция возвращает результат в радианах, находящихся между —лил (включительно).
Base_convert — конвертирует число между произвольными основаниями систем счисления.
Синтаксис:
strin base_convert(string number, int frombase, int tobase)
Возвращает строку, содержащую число number, представленное по основанию tobase. Основание, в котором дается число number, указывается в системе счисления с основанием frombase. Основания frombase и tobase должны находиться в диапазоне от 2 до 36 включительно. Цифры в числах с основанием выше, чем 10, будут представлены буквами a—z, со значениями а — 10, b — 11, ..., z — 36.
. Пример. Функция base_convert ()
$binary = base_convert($hexadecimal, 16, 2);
Bindec — перевод числа из двоичного в десятичное.
Синтаксис:
int bindec(string binary_string)
Возвращает десятичный эквивалент двоичного числа, представленного аргументом binary_string. Функция bindec конвертирует двоичное число в десятичное. Наибольшее число, которое может быть сконвертировано, равно 31 биту или 2147483647 в десятичном виде.
Ceil — округляет число наверх.
Синтаксис:
int ceil (float number1)
Возвращает следующее наименьшее целое значение.
Cos — косинус.
Синтаксис:
float cos (float arg)
Возвращает косинус аргумента в радианах.
Decbin — перевод числа из десятичного в двоичное.
Синтаксис:
string decbin(int number)
Возвращает строку, содержащую двоичное представление аргумента number. Наибольшее число, которое может быть сконвертировано, равно 214748 3647 в десятичном виде или 31 биту.
Dechex — перевод числа из десятичного в шестнадцатеричное.
Синтаксис:
string dechex(int number)
Возвращает строку, содержащую шестнадцатеричное представление аргумента number. Наибольшее число, которое может быть сконвертировано, равно 214748 3647 в десятичном виде или "7ffIffiF' в шестнадцатеричном.
Decoct — перевод числа из десятичного в восьмеричное.
Синтаксис:
string decoct(int number)
Возвращает строку, содержащую восьмеричное представление аргумента number. Наибольшее число, которое может быть сконвертировано, равно 214748 3647 в десятичном виде или "17777777777" в восьмеричном.
Ехр — ев степени, экспонента.
Синтаксис:
float exp(float arg).
Возвращает число е, возведенное в степень агд.
Floor — округляет число вниз.
Синтаксис:
int floor(float number1)
Возвращает "нижележащее" целое значение после number.
Getrandmax — показывает наибольшую возможную случайную величину.
Синтаксис:
int getrandmax (void1)
Возвращает максимальную величину, которая может быть возвращена вызовом функции rand ().
Hexdec — перевод числа из шестнадцатеричного в десятичное.
Синтаксис:
int hexdec(string hex_string)
Возвращает десятичный эквивалент числа, представленного аргументом hex_string. Функция hexdec конвертирует шестнадцатеричную строку в десятичное число. Наибольшее число, которое может быть сконвертировано, равно 7ЙППГ в шестнадцатеричном виде или 2147483647 в десятичном.
Log — натуральный логарифм.
Синтаксис:
float log(float arg)
Возвращает натуральный логарифм от аргумента агд.
Logic — логарифм по основанию 10.
Синтаксис:
float logic(float arg)
Функция возвращает логарифм по основанию 10 от аргумента агд.
Мах — находит максимум.
Синтаксис:
mixed max(mixed argl, mixed arg2, mixed argn)
Функция max () возвращает наибольшее число из перечисленных в параметрах.
Если первый элемент является массивом, функция max () возвращает максимальную величину массива. Если первый параметр — целое, строка
или типа double, следует использовать как минимум два параметра и в этом случае функция max о возвращает наибольшую из этих величин. Можно сравнивать неограниченное количество аргументов. Если одна или более величин типа double, то все остальные величины будут обращены double и, соответственно, возвратится число типа double. Если ни одно из чисел не является double, то все числа будут обращены в целые и возвратится целое число.
м1п — находит минимум.
Синтаксис:
mixed min (mixed argl, mixed arg2, mixed argrT)
Функция min о возвращает наименьшее значение из указанных в аргументах.
Если первый параметр — массив, то функция mint) возвратит наименьшую величину массива. Если первый параметр — целое число, строка или типа double, следует указать как минимум два парметра и функция min о возвратит наименьшую из этих величин. Если одна или более величин типа double, все остальные величины будут обращены double и, соответственно, возвратится число типа double. Если ни одно из чисел не является double, то все числа будут обращены в целые и возвратится целое число.
Mt rand — генерирует случайное число.
Синтаксис:
int mt_rand([int min], [int max])
mt srand — инициализирует генератор случайных чисел.
Синтаксис:
void mt_srand(int seed)
Инициализирует генератор случайных чисел значением seed.
/ инициализируется- количеством микросекунд, истекших от последней // "целой" секунды
mt_srand((double)microtime()*1000000);
$randval = mt_rand();
Mt_getrandmax — показывает наибольшее возможное случайное число.
Синтаксис:
int mt_getrandmax(void)
Функция возвращает максимальную величину, которая может быть возвращена функцией mt_rand () .
Number_format — форматирует заданное число в число с группированными по три десятичными знаками.
Синтаксис:
string number_format(float number, int decimals, string decjpoint,
string thousands_sep)
Функция number_format о возвращает форматированную версию аргумента number. Эта функция принимает один, два или четыре параметра (но не три):
если дан только один параметр number, то он будет приведен к представлению без десятичных цифр, но с запятой (",") между каждой группой тысяч;
если дано два параметра, число number будет отформатировано с десятичными знаками, число которых равно decimals с точкой (".") впереди и запятой (",") между каждой группой тысяч;
если даны все четыре параметра, то число number будет отформатировано с десятичными знаками в количестве decimals, dec_point вместо точки (".") перед десятичным знаком и thousands sep вместо запятой (",") между каждой группой тысяч.
Octdec — перевод числа из восьмеричного в десятичное.
Синтаксис:
int octdec (string octal_string'i
Возвращает десятичный эквивалент восьмеричного числа, представленного аргументом octai_string. Функция octdec () конвертирует восьмеричное число в десятичное. Максимальное число, которое может быть сконвертировано, равно 17777777777 или 2147483647 в десятичном виде.
Pi — величина л.
Синтаксис:
double pi(void)
Возвращает аппроксимированное значение л.
Pow — степень числа.
Синтаксис:
float pow(float base, float exp)
Возвращает число base, возведенное в степень exp.
Rand — генерирует случайную величину.
Синтаксис:
int rand([int min], [int max])
Если функция вызывается без необязательных параметров min и max, то она возвращает псевдослучайную величину между 0 и rand_max. При желании получить случайное число между 5 и 15 (включительно), используйте
г and (5,15). Необходимо проинициализировать генератор случайных чисел перед использованием функции srand().
Round — округляет число с плавающей запятой.
Синтаксис:
double round (double val?)
Возвращает округленную величину val.
Пример Функция round О I..11<Г. I
$foo = round(3.4);// $foo ==3.0
$foo = round(3.5);// $foo ==4.0
$foo = round(3.6);// $foo == 4.0
О sin — синус.
Синтаксис:
float sin(float arg)
Возвращает синус аргумента.
Sqrt — квадратный корень.
Синтаксис:
float sqrt(float arg)
Возвращает квадратный корень аргумента.
Srand — инициализирует генератор случайных чисел.
Синтаксис:
void srand(int seed)
Инициализирует генератор случайных чисел значением seed.
// инициализируется числом микросекунд, прошедших
// с последней "целой" секунды
srand((double)microtime()*1000000);
$randval = rand();
Tan — тангенс.
Синтаксис:
float tan(float arg)
Возвращает тангенс аргумента.
Функции для работы с базами данных MySQL
Mysqi_affected_rows — возвращает количество столбцов, извлеченных предыдущими MySQL-операциями.
Синтаксис:
int mysql_affected_rows(int [link_identifier])
Функция mysqi_affected_rows о возвращает количество столбцов, извлеченных с применением запросов insert, update или delete.
Если последний запрос был delete без указания условия where, то все записи будут удалены из таблицы, а функция возвратит ноль.
Эта функция не работает с запросами select, она действует только при запросах, изменяющих записи. Чтобы получить количество рядов, возвращенных на запрос SELECT, ИСПОЛЬЗуеТСЯ фуНКЦИЯ mysql_num_rows о .
Mysqi_ciose — закрывает MySQL-соединение.
Синтаксис:
int mysql_close(int [link_identifier])
Возвращает значение true при успешном завершении, false при ошибке.
Функция mysqi_ciose() закрывает связь с базой данных MySQL, ассоциированной с определенным идентификатором ресурса. Если идентификатор ресурса не определен, используется последняя открытая связь.
Mysqi_connect — открывает соединение с MySQL-сервером.
Синтаксис:
int mysql_connect(string [hostname] [:port], string [username], string [password])
Функция возвращает идентификатор ресурса при успешном выполнении или false при ошибке.
Mysqi_create_db — создает базу данных MySQL.
Синтаксис:
int mysql_create_db(string database name, int [2ink_identifier])
Функция mysqi_create_db () пытается создавать новую базу данных на сервере, который связан с. определенным идентификатором ресурса.
Mysqi_data_seek — перемещает внутренний указатель результата.
Синтаксис:
int mysql_data_seek(int resu2t_identifier, int row_number)
Возвращает значение true при успешном выполнении, false при ошибке.
Функция mysql_data_seek () перемещает внутренний указатель столбца в MySQL-запросе, который связан с определенным идентификатором ресурса, чтобы указать на определенный номер столбца. Последующий вызов mysql_fetch_row () должен возвратить этот столбец.
Mysqi_db_query — посылает MySQL-запрос.
Синтаксис:
int mysql_db_query(string database, string query, int [link_identifieri)
Возвращает идентификатор ресурса MySQL по выполняемому запросу или значение false при ошибке.
Mysqi_drop_db — удаляет базу данных MySQL.
Синтаксис:
int mysql_drop_db(string database_name, int [link_identifierl)
Возвращает значение true при успешном выполнении, false при неудачном завершении.
Функция mysqi_drop_db () пытается удалить целую базу данных с сервера, который связан с определенным идентификатором ресурса.
□ Mysqi_errno — возвращает номер сообщения об ошибке предыдущей операции MySQL.
Синтаксис:
int mysql_errno(int [link_identifierl )
Ошибки, возвращающиеся из выходного буфера базы данных MySQL.
<?php
mysql_connect("marliesle");
echo mysql_errno().": ",mysql_error()."<BR>";
mysql_select_db("nonexistentdb") ;
echo mysql_errno().": ",mysql_error()."<BR>";
$conn = mysql_query("SELECT * FROM nonexistenttable");
echo mysql_errno().": ",mysql_error()."<BR>"; ?>
□ Mysqi_error — возвращает текст сообщения об ошибке предыдущей операции MySQL.
Синтаксис:
string mysql_error(int [link_identifieri 1
I Пример. Функция mysql_error().... j
<?php'
mysql_connect("marliesle");
echo mysql_errno().": ",mysql_error()."<BR>";
mysql_select_db("nonexistentdb");
echo mysql_errno().": ".mysql_error()."<BR>" ;
$conn = mysql_query("SELECT * FROM nonexistenttable");
echo mysql_errno().": ",mysql_error()."<BR>"; ?>
Mysql_fetch_array — подбирает результат в виде ассоциативного массива.
Синтаксис:
array mysql_fetch_array (int result")
Возвращает строку результата запроса в виде ассоциативного массива или значение false при отсутствии результата. ■
Функция mysql_fetch_array() является расширенной версией функции mysqi_fetch_row(). Она сохраняет информацию и в пронумерованном массиве.
Кроме того, что она сохраняет данные в пронумерованных элементах массива, являющегося результатом, она также сохраняет ассоциативную связь, используя имена полей как ключи. Если два или более столбца имеют одинаковые имена, то пару ключ/значение получает последний из них. Чтобы получить доступ к другому столбцу(столбцам) с таким же именем, необходимо использовать индексы или задать псевдонимы (alias) для этих столбцов.
select tl.fl as foo t2.fl as bar from tl, t2
: Пример. Функция mysql_fetch_array ()
<?php
mysql_connect(Shost,$user,$password);
$result = mysql_db_query("database","select * from table");
while($row = mysql_fetch_array($result)) {
echo $row["user_id"];
echo $row["fullname"];
)
mysql_free_result($result);
?>
Mysqi_fetch_fieid — получает информацию о столбце из результата и возвращает ее как объект.
Синтаксис:
object mysql_fetch_field(int result, int [field-Offset])
Функция mysqi_fetch_fieid о может быть использована для получения информации о поле в определенном результате запроса. Если параметры
поля не указаны, то будет запрошено поле, которое еще не было запрошено функцией mysql_fetch_f ield ().
Свойствами объекта являются:
name — имя столбца;
table — имя таблицы, содержащей столбец;
max_iength — максимальная длина столбца;
not_nuii — 1, если столбец не может принимать нулевые значения;
primary_key — 1, если столбец содержит первичные ключи;
unlque_key — 1, если столбец содержит уникальные ключи;
muitipie_key — 1, если столбец не содержит уникального ключа;
numeric — 1, если столбец числовой;
blob — 1, столбец содержит значения типа blob;
type — тип столбца;
unsigned — 1, если столбец не назван;
zerofill — 1, если столбец заполнен нулем.
Mysqi_fetch_iengths — получает максимальный размер данных для каждого выходного значения.
Синтаксис:
array mysql_fetch_lengths(int result)
Функция возвращает массив, который соответствует длинам каждого поля в последней строке, выбранной mysqi_fetch_row(), или значение false при ошибке.
Mysqi_fetch_object — получает строку результата как объект.
Синтаксис:
object mysql_fetch_object(int result)
Возвращает объект со свойствами, который соответствует полученной строке, или значение false, если нет результата. Функция mysqi_fetch_ object о подобна mysql_fetch_array() С ОДНИМ различием — ВМвСТО массива возвращается объект. Это означает, что можно осуществлять доступ к данным по именам полей, а не по их параметрам (индексные числа в данном случае являются неверным обращением).
: Пример. Функция mysql_fetch_object() ’ ‘'
<?php
mysql_connect($host,$user,$password);
$result = mysql_db_query("database","select * from table");
while($row = mysql_fetch_object($result)) (
echo $row->user_id;
echo $row—>fullname;
)
mysql_free_result($result);
?>
Mysqi_fetch_row — получает строку результата как пронумерованный (проиндексированный) массив.
Синтаксис:
array mysql_fetch_row(int result)
Возвращает массив, который соответствует выбранным колонкам, или значение false, если нет результата. Функция mysqi_fetch_row() выбирает столбец данных из результата и связывает его с определенным идентификатором ресурса. Запрос возвращается как массив. Каждый столбец результата хранится в элементах массива, пронумерованного с нуля.
Дальнейший вызов функции mysqi_fetch_row() должен возвратить следующую строку результата или значение false, если нет больше колонок.
Mysqi_fieid_name — получает имя определенного поля в результате запроса.
Синтаксис:
string mysql_field_name(int result, int field_index)
Функция mysqi_fieid_name о возвращает имя указанного поля. Аргументами функции являются идентификатор ресурса и индекс поля, т. е. mysqi_fieid_name($resuit,2) возвратит имя второго поля для ресурса $result.
Mysqi_fieid_seek — устанавливает указатель в определенное поле.
Синтаксис:
int mysql_field_seek(int result, int field_offset)
Mysqi_fieid_tabie — получает имя таблицы, в которой находится указанное поле.
Синтаксис:
string mysql_field_table(int result, int field_offset)
Mysqi_f ieid_type — получает тип указанного поля в результате.
Синтаксис:
string mysql_field_type(int result, int field_offset)
Функция mysql_field_type () подобна функции mysql_field_name(). Аргументы идентичны, но возвращается тип поля. Это могут быть "int", "real", "string", "blob" ИЛИ другие ТИПЫ.
| Пример. Функция mysql f ield_types ()
<?php.
mysql_connect("localhost:3306");
mysql_select_db("Wisconsin");
$result = mysql_query("SELECT * FROM onek");
$fields = mysql_num_fields($result);
$rows = mysql_num_rows($result);
$i = 0;
$table = mysql_field_table($result, $i);
echo "Your '".$table."' table has ".$fields." fields and ".$rows." records <BR>";
echo "The table has the following fields <BR>"
while ($i
$type
< $fields) {
= mysql_field_type
($result,
$i);
$name
= mysql_field_name
($result,
$i);
$len
= mysql_field_len
($result,
$i) ;
$flags
= mysql_field_flags
($result,
$i);
echo $type." ",$name." ".$len." ".$flags."<BR>"; $i++;
}■
mysql_close();
Mysqi_fieid_fiags — получает флаги, связанные с указанным полем в результате.
Синтаксис:.
string mysql_field_flags (int result, int field_offset)
Могут быть получены следующие флаги : : "not_nuii", "primary_key", unique_key , multiple_key , blob , unsigned , zerofill , binary , "enum", "autO—increment", "timestamp"..
Mysqi_fieid_ien — возвращает длину указанного поля.
z Синтаксис:
int mysql_field_len(int result, int field_offset)
Mysqi_f ree_resuit — освобождает память результата.
Синтаксис:
int mysql_free_result (int result1)
Функция mysqi_free_resuit () должна быть вызвана, только если существуют опасения по поводу чрезмерного использования памяти.
Вся используемая результатом память для определенного идентификатора ресурса автоматически будет освобождена.
Mysqi_insert_id — получает id, сгенерированный предыдущим выполнением SQL-запроса insert.
Синтаксис:
int mysql_insert_id(int [2ink_identifier])
Mysql_iist_fields — показывает список полей MySQL в результате запроса.
Синтаксис:
int mysql_list_fields(string database_name, string tab2e_name,
int [2ink_identifierl)
Функция mysqi_iist_f ields о извлекает информацию об указанной в качестве аргумента таблице. Аргументы — имя базы данных и имя таблицы. После выполнения возвращается указатель ресурса, который может ИСПОЛЬЗОВаТЬСЯ ФУНКЦИЯМИ mysql_field_flags о, mysql_field_len() , mysql_field_name() И mysql_field_type().
Идентификатор результата является положительным целым. Функция возвращает —1, если происходит ошибка. Строка описания ошибки будет помещена в переменную $phperrmsg, и если функция не была вызвана как @mysql (), то будет выведено описание ошибки.
Mysql_iist_dbs — показывает список доступных баз данных на сервере.
Синтаксис:
int mysql_list_dbs(int [2ink_identifier])
Функция mysqi_iist_dbs о возвратит указатель ресурса, содержащий базу данных, доступную текущему процессу. Для просмотра результата используется функция mysql_tablename () .
Mysqi_iist_tabies — показывает список таблиц в базе данных MySQL.
Синтаксис:-
int mysql_list_tables(string database, int [2ink_identifier])
Функция mysqi_iist_tabies о берет имя базы данных и указатель ресурса. Mysql_num_f ields получает количество полей в результате.
Синтаксис:
int mysql_num_fields(int result)
Функция mysqi_num_f ields () получает количество полей в установленном результате.
Mysql_num_rows — получает количество столбцов в результате.
Синтаксис:
int mysql_num_rows(int result)
Функция mysqi_num_rows о получает количество столбцов в установленном результате.
Mysqi_pconnect — открывает постоянное соединение с MySQL-сервером.
Синтаксис:
int mysql_pconnect(string [hostname] [:port], string [username], string [password])
Возвращает идентификатор связи при успешном выполнении или значение false при ошибке. Функция mysqi_pconnect о действует очень похоже С функцией mysql_connect () , но с двумя важными различиями. Во-первых, при соединении функция пытается найти связь, которая уже открыта тем же хостом, именем пользователя и паролем. Если связь обнаруживается, то возвращается ее идентификатор (вместо открытия нового соединения). Во-вторых, соединение с сервером SQL не закроется даже тогда, когда закончится выполнение сценария. Вместо этого, связь останется открытой для последующего ее использования (mysqi_ciose () не закроет связи, установленные функцией mysqi_pconnect о). Потому этот тип связей назван постоянными связями.
Mysqi_query — отправляет SQL-запрос MySQL-серверу.
Синтаксис:
int mysql_query(string query, int [link-identifier])
Функция mysqi_query () посылает запрос в базу данных с определенным идентификатором ресурса связи. Если параметр Hnk_identifier не указан, то используется последняя открытая связь. Если связь не открыта, то функция пытается установить связь, как если бы была вызвана функция mysql_connect().
Функция mysqi_query() возвращает значение true или false, чтобы показать успешность выполнения запросов update, insert и delete. При запросе select она возвращает новый идентификатор ресурса. Ресурсы, использованные запросом, затем могут быть освобождены вызовом функции mysql_free_result().
Mysqi_resuit — получает данные результата.
Синтаксис:
int mysql_result(int result, int row, mixed field)
Функция mysqi_resuit о возвращает содержимое одной ячейки из установленного результата MySQL. Аргументом поля может быть номер или имя поля, или параметр имя_таблицы-точка-имя_поля (fieldname.tablename). Если имя столбца заменено псевдонимом (например, 'select foo as bar from...'), то используется псевдоним вместо имени столбца.
Mysqi_seiect_db — выбирает базу данных MySQL.
Синтаксис:
int mysql_select_db(string database_name, int [link_identifieri)
Возвращает значение true при успешном выполнении, false при ошибке. Функция mysqi_seiect_db () устанавливает текущую активную базу данных на сервере, которая связывается с определенным идентификатором ресурса связи. Если не определен идентификатор связи, принимается последняя открытая связь. Если связь не открыта, функция попытается установить связь, как если бы была вызвана функция mysqi_connect(). Каждый последующий вызов mysqi_query () будет произведен в активной базе данных.
Mysqi_tabiename — получает имя таблицы, содержащей указанное поле.
Синтаксис:
string mysql_tablename(int result, int i)
Функция mysqi_tabiename () берет указатель ресурса, возвращенный функцией mysqi_iist_tabies (), а также целочисленный индекс и возвращает имя таблицы. Функция mysqi_num_rows () может использоваться для того, чтобы определить количество таблиц на данном указателе ресурса.
Пример. Функция mysql_tablename()
<?php
mysql_connect ("localhost:3306");
$result = mysql_listtables ("Wisconsin");
$i = 0;
while ($i < mysql_num_rows ($result)) (
$tb_names[$i] = mysql_tablename ($result, $i) ;
echo $tb_names[$i]. "<BR>"; $i++;
} .
?>
Функции для работы с сетью
Fsockopen — открывает соединение с узлом в Интернете или Unix-системой через сокет.
Синтаксис:
int fsockopen(string hostname, int port, int [errno], string
[errstr])
I Пример. Функция fsockopenO
$fp = fsockopen("www.php.net", 80, &$errno, &$errstr);
if(I$fp) { echo "$errstr ($errno)<br>\n";
} else {
fputs($fp,"GET / HTTP/1.0\n\n") ;
while(!feof($fp)) {
echo fgets($fp,128);
}'
fclose($fp);
}
Set_socket_blocking — устанавливает режимы blocking/non-blocking при работе сокета.
Синтаксис:
int set_socket_blocking(int socket descriptor, int mode)
Если параметр mode отсутствует, данный дескриптор сокета переключится на режим non-blocking, а если присутствует, то переключится на режим blocking. В режиме non-blocking обращение К функции fgets о всегда будет возвращаться немедленно, в то время как в blocking-режиме происходит ожидание данных.
Gethostbyaddr — получает имя хоста Интернета, соответствующее данному IP-адресу.
Синтаксис:
string gethostbyaddr(string ip_address)
Возвращает имя хоста Интернета, определенного аргументом ip_address. Если происходит ошибка, возвращается значение ip_address.
Gethostbyname — получает IP-адрес, соответствующий заданному имени хоста Интернета.
Синтаксис:
string gethostbyname(string hostname)
Возвращает IP-адрес хоста, указанного аргументом hostname.
Gethostbynamei — получает список IP-адресов, соответствующих заданному имени хоста Интернета.
Синтаксис:
array gethostbynamei(string hostname)
checkdnsrr — проверяет записи на сервере DNS, соответствующие заданному хосту или IP-адресу.
Синтаксис:
int checkdnsrr(string host, string [type])
Ищет в DNS записи типа type, соответствующие аргументу host. Возвращает значение true, если обнаруживаются какие-либо записи, и false, если не обнаружены никакие записи или если произошла ошибка. Параметр type может быть любым из значений: а, мх, ns, soa, ptr, cname или any. По умолчанию — мх. Параметр host может быть или адресом IP, или именем хоста.
Getmxrr — получает мх-записи, соответствующие заданному имени хоста.
Синтаксис:
int getmxrr(string hostname, array mxhosts, array [weight])
Ищет в DNS мх-записи, соответствующие hostname. Возвращает значение true, если записи найдены, и false, если записей не найдено или произошла ошибка. Список мх-записей может размещаться в массиве mxhosts.
Openlog — открывает соединение к системным логам.
Синтаксис:
int openlog(string ident, int option, int facility)
Sysiog — генерирует системное сообщение.
Синтаксис:
int sysiog(int priority, string message)
closelog — закрывает соединение с системными логами.
Синтаксис:
int closelog(void)
Debugger_on — активизирует внутренний отладчик.
Синтаксис:"
int debugger_on(string address')
Debugger_off — выключает внутренний отладчик.
Синтаксис:
int debugger_off(void)
Функции для работы с графическим форматом PDF
PDF_get_info — возвращает обычную информационную структуру для pdf-документа.
Синтаксис:
info pdf_get_info (string filename)
Функция PDF_get_info() возвращает обычную (принимаемую по умолчанию) информационную структуру для pdf-документа. Эта структура может быть заполнена различной информацией, такой как автор, название и т. д.
: Пример, функция PDF_get_info ()■
<?php $info = PDF_get_info();
PDF_set_info_creator($info, "Name of Author") ?>
PDF_set_info_creator — заполняет поле создателя информационной структуры.
Синтаксис:
void pdf_set_info_creator (info info, string creator)
Функция PDF_set_info_creator о устанавливает создателя pdf-документа. Она должна вызываться после PDF_get_info() и перед функцией PDF_open (). Вызов функции после PDF_open () не даст никакого эффекта.
PDF_set_info_title — заполняет поле заголовка информационной структуры.
Синтаксис:'
void pdf_set_info_title (info info, string title)
Функция PDF_set_info_titie () устанавливает заголовок pdf-документа. Она должна вызываться после PDF_get_info о и перед функцией PDF_open (). Вызов функции после PDF_open () не даст никакого эффекта.
PDF_set_info_subject — заполняет поле темы информационной структуры.
Синтаксис:
void pdf_set_info_subject (info info, string subject)
Функция PDF_set_info_subject () устанавливает тему pdf-документа. Она должна вызываться после PDF_get_info () и перед функцией PDF_open(). Вызов функции после PDF_open() не даст никакого эффекта. '
PDF_set_info_keywords — заполняет поле ключевых слов информационной структуры.
Синтаксис:
void pdf_set_info_keywords (info info, string keywords')
Функция PDF_set_info_keywords о устанавливает ключевые слова pdf- документа. Она должна вызываться после PDF_get_info() и перед функцией PDF_open(). Вызов функции после PDF_open() не даст никакого эффекта.,
PDF_set_info_author — заполняет поле автора.
Синтаксис:’
void pdf_set_info_author (info info, string author')
Функция PDF_set_info_author о устанавливает автора pdf-документа. Она должна вызываться после PDF_get_info () и перед функцией PDF_open (). Вызов функции после PDF_open () не даст никакого эффекта.
PDF_open — открывает новый pdf-документ.
Синтаксис:
int pdf_open (int descript erfHe, int info)
Функция PDF_set_info_author о открывает новый pdf-документ. Соответствующий файл должен быть открыт функцией fopen (), и дескриптор файла использоваться как аргумент file. Параметр info ИСПОЛЬЗуется для записи информации, которая должна быть создана функцией PDF_get_infо(). Возвращаемое значение необходимо указывать как первый параметр у всех функций записи в pdf-документ.
PDF_ciose — закрывает pdf-документ.
Синтаксис:
void pdf_close (int pdf_document)
Функция PDF_ciose () закрывает pdf-документ. Функция не закроет файл. Неоходимо вызвать отдельно функцию fcioseO после функции PDF_close().
PDF_begin_page — начинает страницу.
Синтаксис:
void pdf_begin_page (int pdf_document, double height, double width)
Функция PDF_begin_page() начинает новую страницу ВЫСОТОЙ height И шириной width.
PDF_end_page — завершает страницу.
Синтаксис:
void'pdf_end_page (int pdf —document)
PDF_show — выводит текст с текущей позиции.
Синтаксис:
void pdf_show (int pdf—document, string text)
Функция PDF_show () выводит строку text с текущей позиции.
PDF_show — выводит текст с определенной позиции.
Синтаксис:
void pdf_show_xy (int pdf—document, string text, double x-koor, double y-koor)
Функция PDF_show_xy() выводит строку text, начиная с позиции с координатами (х-koor, у-коогУ
PDF_set_font — устанавливает текущий шрифт и его размер.
Синтаксис:
void pdf_set_font (int pdfdocument, string font_name, double size, string encoding')
Функция PDF_set_font () устанавливает текущий шрифт, его размер и кодировку. Потребуется указать Adobe Font Metrics (afm-файлы) для шрифта в пути шрифта (по умолчанию ./fonts).
PDF_set_ieading — устанавливает промежуток между строками текста.
Синтаксис:■
void pdf_set leading (int pdf document, double distance)
Функция PDF_set_ieading () устанавливает промежуток между строками текста. Он будет использоваться при выводе текста функцией PDF_continue_text().
PDF_set_text_rendering — определяет, как будет прорисовываться текст.
Синтаксис:
void pdf_set_text_rendering (int pdf document, int mode)
Функция PDF_set_text_rendering () определяет то, как текст прорисовывается. Возможные значения для параметра mode:
0=заливка текста;
1=контурный текст;
2=контурный текст с заливкой;
3=невидимый текст;
4=заливка текста и добавление его в контур;
5=контурный текст с добавлением в контур;
6=контурный текст с заливкой и с добавлением контура;
7=добавление текста.
PDF_set_horiz_scaiing — задает горизонтальное масштабирование текста.
Синтаксис:
void pdf_set_horiz_scaling (int pdf—document, double scale1)
Функция PDF_set_horiz_scaiing() устанавливает горизонтальное масштабирование В scale процентов.
PDF_set_text_rise — устанавливает увеличение текста.
Синтаксис:
void pdf_set_text_rise (int pdfjdocument, double value)
Функция pdf set text rise () устанавливает увеличение текста на value единиц.
PDF_set_text_matrix — устанавливает текстовую матрицу.
Синтаксис:.
void pdf_set_text_matrix (int pdfjdocument, array matrix)
PDF_set_text_pos — устанавливает позицию текста.
Синтаксис:
void pdf_set_text_pos (int pdfjdocument, double x-koor, double
y-koor)
Функция PDF_set_text_pos о устанавливает позицию текста для следующего вызова функции PDF_show().■
PDF_set_char_spacing — устанавливает межсимвольные промежутки.
Синтаксис:
void pdf_set_char_spacing (int pdfjdocument, double space)
Функция PDF_set_char_spacing() устанавливает промежутки между символами.
PDF_set_word_spacing — устанавливает промежутки между словами.
Синтаксис:
void pdf_set_word_spacing (int pdfjdocument, double space)
PDF_continue_text — выводит текст на следующей строке.
Синтаксис:
void pdf_continue_text (int pdfjdocument, string text)
Функция PDF_continue_text () выводит строку текста в новой строке.
PDF_stringwidth — возвращает ширину текста при текущем шрифте.
Синтаксис:
double pdf_stringwidth (int pdfjdocument, string text)
Функция PDF_stringwidth() возвращает ширину строки.
PDF_save — сохраняет текущее окружение.
Синтаксис:
void pdf_save (int pdf —document)
PDF_restore — восстанавливает сохраненное ранее окружение.
Синтаксис:
void pdf_restore (int pdf_document)
Функция PDF_restore о восстанавливает окружение, сохраненное функцией PDF_save О .
Пример. Функция PDF_get infо ().. i
<?php PDF_save($pdf);
H здесь текст программы ...
PDF_restore($pdf) ?>
PDF_transiate — задает начало системы координат.
Синтаксис:
void pdf_translate (int pdf_document, double x-koor, double y-koor)
Функция PDF_transiate о устанавливает начало системы координат ВТОЧКе^х-коог, у-коог\
PDF_scaie — задает масштабирование.
Синтаксис:
void pdf_scale (int pdf_document, double x-scale, double y-scale)
Функция PDF_scaie о устанавливает масштабный коэффициент для обеих осей.
PDF_rotate — задает вращение.
Синтаксис:
void pdf_rotate (int pdf—document, double angle1)
Функция PDF_rotate () задает вращение на угол angle.
PDF_setfiat — устанавливает плоскость.
Синтаксис:
void pdf_setflat (int pdf_document, double value)
PDF_setiinejoin — устанавливает параметр слияния линий.
Синтаксис:
void pdf_setlinejoin (int pdf_document, long value)
PDF_setiinecap — устанавливает параметр формата строки.
Синтаксис:
void pdf_setlinecap (int pdf—document, int value1)
PDF_setmiteriimit — устанавливает минимальный предел.
Синтаксис:
void pdf_setmiterlimit (int pdf_document, double value1)
Функция PDF_setmiteriimit о устанавливает минимальный предел больше или равный 1.
PDF_setiinewidth — устанавливает ширину линии.
Синтаксис:
void pdf_setlinewidth (int pdf_document, double width1)
PDF_setdash — устанавливает вид тире в линиях.
Синтаксис:
void pdf_setdash (int pdf—document, double white, double black1)
Функция PDF_setdash () устанавливает вид пунктирной линии, где white — единицы белого и black — единицы черного. Если они оба равны 0, то устанавливается сплошная линия.
PDF_moveto — устанавливает текущую точку.
Синтаксис:
void pdf_moveto (int pdf_document, double x-koor, double y-koor1)
Функция PDF_moveto() устаналивает текущую точку в координатах x-koor И y-koor.
PDF_curveto — рисует кривую.
Синтаксис:
void pdf_curveto (int pdf —document, double xl, double yl, double x2, double y2, double x3, double y3)
Функция PDF_curveto () рисует кривую Безье от текущей точки до точки с координатами (хз, уз), используя (xi, yi) и (х2, у2) как управляющие точки.
PDF_lineto — рисует ЛИНИЮ.
Синтаксис:
void pdf_lineto (int pdf—document, double x-koor, double y-koor1)
Функция PDF_lineto() рисует линию, начиная от текущей точки до точки с координатами (x-koor, y-koor).
PDF_circle — рисует круг.
Синтаксис:
void pdf_circle (int pdfjdocument, double x-koor, double y-koor, double radius)
Функция PDF_circie() рисует круг с центром в точке (х-коог, у-коог) И радиусом radius.
PDF_arc — рисует дугу.'
Синтаксис:
void pdf_arc (int pdf_document, double x-koor, double y-koor, double radius, double start, double end)
Функция PDF arcO рисует дугу с центром в точке с координатами (х-коог, у-коог) и радиусом radius, начинает с угла start и заканчивает углом end.
PDF_rect — рисует прямоугольник.
Синтаксис:
void pdf_rect (int pdfjdocument, double x-koor, double y-koor, double width, double height)
Функция pDF_rect () рисует прямоугольник с нижним левым углом в точке (x-koor, у-коог). Ширина определяется параметром width, высота — параметром height.■
PDF_ciosepath — закрывает контур.
Синтаксис:
void pdf_closepath (int pdfjdocument)
Функция PDF_ciosepath() закрывает текущий контур.
PDF_stroke — рисует линию вдоль контура.
Синтаксис:
void pdf_stroke (int pdfjdocument)
Функция PDF_stroke о рисует линию вдоль текущего контура.
PDF_ciosepath_stroke — закрывает контур и рисует вдоль него линию.
Синтаксис:
void pdf_closepath_stroke (int pdfjdocument)
Функция PDF_ciosepath_stroke () является сочетанием функций PDF_closepath() И PDF_stroke()..
PDF_fiii — заполняет текущий контур.
Синтаксис:
void pdf_fill (int pdfjdocument)
Функция PDF_fiii () заполняет область текущего контура текущим цветом.
PDF_f iii_stroke — заполняет текущий контур.
Синтаксис:
void pdf_fill_stroke (int pdf_document)
Функция PDF_fiii_strokeо заполняет область текущего контура текущим цветом.
PDF_ciosepath_fiii_stroke — рисует и заполняет контур.
Синтаксис:
void pdf_closepath_fill_stroke (int pdf_document)
Функция PDF_ciosepath_fiii_stroke() заполняет область текущего контура текущим цветом и рисует контур.
PDF_endpath — заканчивает текущий контур.
Синтаксис:
void pdf_endpath (int pdf_document)
Функция PDF_endpath() заканчивает текущий контур, но не закрывает его.
PDF_ciip — заканчивает текущий контур.
Синтаксис:
void pdf_clip (int pdfjdocument)
Функция PDF_ciip() прекращает рисование текущего контура.
PDF_setgray_f ill — устанавливает серый цвет заполнения.
Синтаксис:
void pdf_setgray_fill (int pdf_document, double value)
Функция PDF_setgray_fiil () делает текущим серый цвет для заполнения контура.■
PDF_setgray_stroke — устанавливает серый цвет рисования.
Синтаксис:
void pdf_setgray_stroke (int pdf_document, double gray value)
Функция PDF_setgray_stroke () далает текущий цвет рисования серым.
PDF_setgray — устанавливает серый цвет рисования и заполнения.
Синтаксис:
void pdf_setgray (int pdf_document, double gray value)
Функция PDF_setgray_stroke О делает текущие цвета рисования и заполнения серыми.
PDF_setrgbcoior_fill — устанавливает RGB-значение цвета заполнения. Синтаксис:
' void pdf_setrgbcolor_fill (int pdf_document, double red value,
.double green value, double blue value)
Функция PDF_setrgbcoior_fill () делает текущим RGB-цвет для заполнения контура.
PDF_setrgbcoior_stroke — устанавливает RGB-значение цвета рисования.
Синтаксис:
void pdf_setrgbcolor_stroke (int pdf_document, double red value, double green value, double blue value)
Функция PDF_setrgbcoior_strokeо делает текущим RGB-цвет рисования.
PDF_setrgbcoior — устанавливает RGB-цвет рисования и заполнения.
Синтаксис:
void pdf_setrgbcolor (int pdf_document, double red value, double green value, double blue value)
Функция PDF_setrgbcoior_strokeо делает текущим RGB-цвет рисования и заполнения.
PDF_add_outiine — добавляет закладку для текущей страницы.
Синтаксис:
void pdf_add_outline (int pdf_document, string text)
Функция PDF_add_outiine () добавляет закладку с текстом text, которая указывает на текущую страницу.
PDF_set_transition — устанавливает переход между страницами.
Синтаксис:
void pdf_set_transition (int pdf_document, int transition)
Функция PDF_set_transition() устанавливает переход между указанными следующими страницами. Значения параметра transition могут быть:
0 — нет перехода;
1 — две линии;
2 — несколько линий;
3 — прямоугольник;
4 — одна линия;
5 — новая страница открывается, старая "растворяется";
6 — эффект "растворения", перемещающегося от одного края экрана к другому;
7 — простая смена старой страницы новой (по умолчанию).
PDF_set_duration — устанавливает паузу между страницами.
Синтаксис:
void pdf_set_duration (int pdf —document, double duration)
Функция PDF_set_duratlon () устанавливает паузу между страницами в секундах.
Функции вызова внешних программ
Escapesheiicmd — убирает мета-символы..
Синтаксис:
string escapesheiicmd(string command)
Функция Escapesheiicmd о убирает любые символы в строке, которые могут быть использованы в командном интерпретаторе как команды. Эту функцию нужно использовать, чтобы убедиться, что все команды введены правильно. Ее лучше всего вставлять в функции ехес о или system о. Стандартное использование этой функции выглядит так: system(EscapeShellCmd($cmd))
Exec — запуск внешней программы.
Синтаксис:
string exec(string command, string [ array ], int [ return_var ])
Функция exec о запускает программу из строки command, весь стандартный вывод отключен. Возвращает последнюю строку результата выполнения программы. Если вы хотите запустить команду и использовать все данные непосредственно без всякого вмешательства других программ, то ИСПОЛЬЗуЙте функцию PassThruf).
Если параметр array установлен, то указанный массив будет заполнен выводом из программы. Помните, если массив уже содержит данные, то функция ехес () добавляет свои данные. Если вы не хотите, чтобы функция добавляла данные, вызывайте unset () для массива перед использованием функции ехес ().
Если параметр return_var задан (наряду с параметром array), то в него записывается результат выполнения команды.
System — запуск внешней программы с выводом результата.
Синтаксис:
string system(string command, int [ return_var ])
Если используется второй параметр, то в него записывается результат выполнения команды.
Passthru — запускает внешнюю программу и выводит данные.
Синтаксис:
string passthru(string command, int [ return_var ])
Функция passthru () ПОХОЖа На функцию Exec () ДЛЯ запуска command. Если параметр return_var установлен, то результат Unix-команды помещается в него. Эта функция должна использоваться вместо Ехес () или System о тогда, когда вывод из Unix-команды является двоичными данными, которые должны быть переданы непосредственно обратно в окно просмотра. Это можно использовать, например, для запуска утилиты pbmpius для вывода непосредственно потока изображения.
Функции для работы со строками
Adds lashes — выделяет строку обратной чертой.
Синтаксис:
string addslashes(string str)
Возвращает строку с чертой (/) перед символами, которые должны быть выделены в запросах к базам данных и т. п. Это символы: ('), двойные кавычки ("), (\) и nul (нулевой байт).
chop — удаляет повторяющиеся пробелы.
Синтаксис:
string chop(string str)
Возвращает строку без повторяющихся пробелов.
Пример. Функция chop (),(
Strimmed = Chop($line);
chr — возвращает специальный символ.
Синтаксис:
string chr(int ascii)
Функция возвращает односимвольную строку, содержащую символ, определенный кодом ascii.
i Пример. Функция chr (),■
•;.-.;:.«я...-..».,......
$str.= chr(27); /* добавляет символ ESC в конец $str */
$str = sprintf("The string ends in escape: %c", 27);
chunk_spiit — разбивает строку на части.
Синтаксис:
string chunk_split(string string, int [chunkier], string [end])
Функция может быть использована для разбивки строки на меньшие части, например, при конвертировании результата функции base64_encode в формат RFC 2045. Функция возвращает новую строку, оставляя исходную без изменений.
' Пример. Функция chr^replaae ()
format $data using RFC 2045 semantics
$new_string = chunk_split(base64_encode($data));
Convert_cyr_string — переводит из одной русской кодовой таблицы в другую.-
Синтаксис:
string convert_cyr—string(string str, string from, string to)
Эта функция переводит указанную строку из одной русской кодовой таблицы в другую. Аргументы from и to являются одним символом, который определяет исходную и целевую кодовую таблицу. Поддерживаемые типы:
k — koi8-r;
w — windows-1251;
i — iso8859-5;
a — x-cp866;.
d — x-cp866;
m — x-mac-cyrillic.
Crypt — шифрует строку методом DES.
Синтаксис:
string crypt(string str, string [salt])
Функция crypt () шифрует строку, используя стандартный метод шифрования для UNIX — DES. Аргументами являются строка, которую нужно зашифровать, и дополнительная 2-символная строка salt, на которой будет основываться шифрование (см. документацию по UNIX для дополнительной информации). Если аргумент salt отсутствует, то он будет сгенерирован случайным образом.
Echo — ВЫВОДИТ СТРОКИ.
Синтаксис:
echo(string argl, string [argn]...)
Функция echo () в действительности не является функцией (это языковая конструкция), поэтому вовсе не обязательно использовать круглые скобки. Выводит аргумент в поток вывода.
‘ Пример. Функция echo О'
echo "Hello World";
Explode — разбивает строку на части.
Синтаксис:
array explode (string separator, string string")
Возвращает массив строк, содержащий элементы, разделенные строкой separa tor.
Пример. Функция explode О, \
$pizza = "piecel piece? piece3 piece4 pieces piece6";
$pieces = explode(" ", $pizza);
Flush — освобождает буферы вывода.
Синтаксис:
void flush(void)
Освобождает буферы вывода PHP и все остальные буферы, используемые PHP.
Get_meta_tags — извлекает все содержимое атрибутов ярлыка <meta> из файла и возвращает в массиве.
Синтаксис:
array get_meta_tags(string filename, int [use_include_joath])
Открывает файл filename и обрабатывает его строка за строкой, извлекая ярлыки <meta>.
Пример. Ярлыки Meta,‘
<meta name="author" content="name">
<meta name="tags" content="php3 documentation">
</head> <!- parsing stops here ->
Значение свойства name становится ключом, значение свойства content — значением возвращаемого массива, поэтому вы можете легко использовать стандартные функции для его обработки или доступа к отдельным элементам. Специальные символы в значении свойства заменяются символом "_", остальные переводятся в нижний регистр.
Htmispeciaichars — переводит специальные символы в коды HTML.
Синтаксис:
string htmispeciaichars(string string)
Определенные символы имеют особое значение в HTML и должны быть заменены кодами HTML, если они таковые имеют. Эта функция возвращает измененные строки. Например, символ:
'&' (амперсанд) становится '&атр;';
"" (двойные кавычки) становятся '"';
'<' (знак меньше) становится '<';
'>' (знак больше) становится '>'.
Htmientities — переводит все возможные символы в коды HTML.
Синтаксис:
string htmientities(string string)
Эта функция идентична htmispeciaichars о, кроме того, что заменяются все символы.
implode — объединяет массив элементов в строку.
Синтаксис:
string implode(array pieces, string glue)
Возвращает строку, содержащую совокупность всех элементов массива в том же порядке, со строкой glue между каждым элементом.
Пример. Функция implode ()■.
...• • ...•«...«.«.«....•,,..«•««• hi - #..»..и *•...•.*.•.•« не. ..*»«*•.. ».»>>....■..•.. .«.««.. «. .......I
$colon_separated = implode($array, ":”);
Join — присоединяет элементы массива к строке.
Синтаксис:
string join(array pieces, string glue)
Функция joint) является псевдонимом функции implode () и полностью ей идентична.
Ltrim — удаляет пробелы из начала строки.
Синтаксис:
string ltrim(string str)
Эта функция удаляет пробелы из начала строки и возвращает обрезанную строку.
Md5 — вычисляет значение md5 для строки.
Синтаксис:
string md5(string str)
Вычисляет значение MD5 для строки str, используя алгоритм Inc. MD5 — Message-Digest.
N12br — переводит символы новой строки в HTML-ярлык разрыва строки.
Синтаксис:
string nl2br (string string1)
Возвращает строку с ярлыком (тегом) <br>, вставляемым перед каждой новой строкой.
Ord — возвращает ASCII-значение символа.
Синтаксис:
int ord(string string)
Возвращает ASCII-значение первого символа строки string. Эта функция дополняет функцию chr ().
Пример. Функция ord ()''*:
if (ord($str) == 10) { echoC'The first character of \$str is a line feed.\n");
}
Parse_str — разбирает строку на переменные.
Синтаксис:
void parse_str(string str)
Разбирает строку str, как если бы она была URL-строкой запроса, и устанавливает переменные текущей среды.
i Пример, функция parse atr()’
$str = "first=value&second[]=this+works&second[]=another";
parse_str($str);
echo $first; /* prints "value" */
echo $second[0]; /* prints "this works" */
echo $second[l]; /* prints "another" */
Print — выводит строку.
Синтаксис:
print(string arg)
Выводит строку arg.
Printf — выводит форматированную строку.
Синтаксис:
int printf(string format, mixed [args]...)
Осуществляет вывод в соответствии с параметром format, который описан в ФУНКЦИИ sprintf().
Quoted_printable_decode — переводит строку в кавычках в 8-битную строку.
Синтаксис:
string quoted__printable_decode(string str)
Эта функция возвращает 8-битную строку, соответствующую декодированной строке в кавычках. Эта функция аналогична imap_qprint(), за исключением того, что она не требует IMAP-модуль для работы.
QuoteMeta — выделяет мета-символы.
Синтаксис:
int quotemeta(string str)
Возвращает обработанную строку str с символом (\) перед каждым из следующих символов:
. \\ + * ? [ А ] ($).
Rawurldecode — декодирует URL-кодированную строку.
Синтаксис:
string rawurldecode(string str)
Возвращает строку, в которой последовательность из символа процента (%) и последующих 2-х шестнадцатеричных цифр заменяется соответствующим буквенным символом. Например, строка:
yes%20no%40sure
будет заменена на yes no@sure
Rawuriencode — URL кодирует строку в соответствии с RFC 1738.
Синтаксис:.
string rawuriencode(string str)
Возвращает строку, в которой все не буквенно-цифровые символы заменяются на знак % с последующими двумя шестнадцатеричными цифрами. Это кодирование, описанное в RFC1738, применяется для защиты символов от интерпретации их как особых разделителей URL и для защиты URL от искажения системами передачи данных с переводом символов
(как некоторые e-mail системы). Например, если вы хотите включить пароль в ftp URL:
Пример 1. Функция rawurlencode (). ,
echo '<А HREF="ftp://user:', rawurlencode ('foo 0+%/'),
10ftp.my.com/x.txt">';
Или если передается информация в качестве части URL, то записываем так, как в примере 2:
Пример 2. Функция rawurlencode ()*.
I <i, .**......i.eiU * *W iM.eU...1 I. #.....!,.,..■, ..И«.• ■■■•■«•«Mie. •...■.•••.. «..м.а.М I...... uulUU*
echo '<A HREF="http://x.com/department_list_script/', rawurlencode ('sales и marketing/Miami'), '">';
Setlocale — устанавливает локальную информацию.
Синтаксис:
string setlocale(string category, string locale1)
Параметр category является строкой, определяющей категорию функций, изменяемую строкой locale:
lc_all для всех нижеследующих;
lc_collate для сравнения строк;
lc_ctype для классификации и перевода символов, например, с помощью функции strtoupper() ;
LC_MONETARY ДЛЯ функции localeconv () ;
lc_numeric для десятичного разделителя;
lc_time для даты и времени, форматируемых функцией strftime ().
Если locale является пустой строкой "", то локальные имена будут установлены из значений переменных окружения с теми же именами, как у вышеописанных категорий, или из "LANG". Если locale равна нулю, то местные установки не изменяются, возвращаются текущие установки. Функция setlocale возвращает новое текущее значение locale или значение false, если locale функционально не поддерживается текущей платформой, указанной locale не существует или указана неверная категория. Неверное имя категории также вызывает предупреждение.
Soundex — вычисляет soundex-ключ для строки.
Синтаксис:
string soundex(string str)
Вычисляет КЛЮЧ soundex ДЛЯ str.
Пример. Функция soundex ()
soundex("Euler") == soundex("Ellery") == 'E460';
soundex("Gauss") == soundex("Ghosh") == 'G200';
soundex("Knuth") == soundex("Kant") == 'H416';
soundex("Lloyd") == soundex("Ladd") == 'L300';
soundex("Lukasiewicz") == soundex("Lissajous") == 'L222';
sprintf — возвращает форматированную строку.
Синтаксис:
sprintf(string format, mixed [args]...)
Возвращает строку, обрабатываемую в соответствии с форматирующей строкой format.
Форматирующая строка, содержащая ноль или более директив. Каждое описание изменений состоит из следующих элементов:
дополнительный описатель заполнения, который указывает, какие символы будут использоваться для заполнения результата до правильного размера строки. Это могут быть пробелы или 0 (символ нуля). По умолчанию заполняется пробелами. Альтернативный символ заполнения может быть определен одинарными кавычками (•). См. примеры ниже;
дополнительный описатель выравнивания, который указывает, что результат должен быть выровнен по левому или по правому краю. По умолчанию выравнивание происходит по правому краю;
дополнительный описатель ширины, который указывает, с каким количеством символов (минимум) может производиться данная замена;
дополнительный описатель точности, который указывает, сколько десятичных знаков следует отображать для чисел с плавающей точкой. Этот описатель не действует на остальные типы, кроме double. (Другая полезная функция для форматирования чисел — это функция number_format ());
описатель типа, который говорит о том, как тип данных аргумента должен трактоваться. Возможные типы: % — символ процента. Аргумент не требуется:
ь — аргумент трактуется как integer и представляется как двоичное число;
с — аргумент трактуется как integer и представляется как символ с ASCII-значением;
d — аргумент трактуется как integer и представляется как десятичное число;.
f — аргумент трактуется как double и представляется как число с плавающей точкой;
о — аргумент трактуется как integer и представляется как восьмеричное число;
s — аргумент трактуется как строка и представляется как строка;
х — аргумент трактуется как integer и представляется как шестнадцатеричное число (с буквами в нижнем регистре);
° х — аргумент трактуется как integer и представляется как шестнадцатеричное число (с буквами в верхнем регистре).
Пример 1. Функция sprintf (): числа с нулями '
$isodate = sprintf("%04d-%02d-%02d", $year, $month, $day);
Пример 2. Функция sprintf (): форматирование денежной единицы j
$moneyl = 68.75;
$money2 = 54.35;
$money = $moneyl + $money2;
// echo $money выведет "123.1";
$formatted = sprintf ("%01.2f", $money);
// echo $formatted выведет "123.10"
strchr — находит первое появление символа.
Синтаксис:
string strchr(string haystack, string needled
Эта функция является псевдонимом для функции strstr о и полностью ей идентична.
strcmp — двоичное сравнение строк (безопасное).
Синтаксис:
int strcmp(string strl, string str2)
Возвращает значение < 0, если strl меньше, чем str2; значение > 0, если strl больше, чем str2; и 0, если строки равны. Следует отметить, что это сравнение чувствительно к регистру.
strcspn — находит длину начального сегмента, не совпадающего с маской.
Синтаксис:
int strcspn(string strl, string str2)
Возвращает длину начального сегмента strl, который не содержит символы из str2.
stripslashes — удаляет символы "\" из строки.
Синтаксис:
string stripslashes(string str)
Возвращает строку с вырезанными символами \. (V заменяется на ' и так далее). Двойные \\ заменяются на \.
strien — возвращает длину строки.
Синтаксис:
int strien(string str)
Возвращает длину строки str.
strrpos — находит позицию последего появления символа в строке.
Синтаксис:■
int strrpos(string haystack, char needle) Возвращает номер позиции последнего появления символа needle в строке haystack. Следует отметить, что needle в этом случае может быть только единственным символом. Если в качестве параметра needle указывается строка, то только первый символ будет использован. Если needle не найден, то возвращается значение false. Если параметр needle не является строкой, то он переводится в десятичное число и рассматривается как числовое значение символа.
strpos — находит позицию первого появления строки.
Синтаксис: int strpos(string haystack, string needle, int [offset]) . Возвращает номер позиции первого появления строки needle в строке haystack. В отличие от strrpos о , эта функция может рассматривать целую строку в качестве параметра needle. Если параметр needle не найден, то возвращается значение false. Если параметр needle не является строкой, то он переводится в целое число и рассматривается как числовое значение символа. Дополнительный параметр offset позволяет вам определять, с какого символа в строке haystack начинать поиск. Позиция возвращается все равно относительно начала строки haystack.
strrchr — находит последнее появление символа в строке.
Синтаксис:
string strrchr(string haystack, string needle)
Эта функция возвращает позицию haystack, с которой начинается последнее появление needle. Возвращает значение false, если needle не найдена. Если параметр needle содержит более чем один символ, то используется первый символ. Если параметр needle не является строкой, то он переводится в целое число и рассматривается как числовое значение символа.
Ия«жжЯ®»ЯивЯИиМ1Ж1Р®1!ВИЧЯЯВИЯН1в
Пример. Функция strrchrQ .' ’’" '"
// получение последнего каталога в $РАТН
$dir = substr(strrchr($РАТН, ":"), 1);
// получение текста после последней новой строки
$text = "Line lXnLine 2\nLine 3";
$last = substr(strrchr($text, 10), 1);
strrev — переворачивает строку.
Синтаксис:
string strrev(string string')
Возвращает перевернутую строку string.
strspn — находит длину начального сегмента, отвечающего маске.
Синтаксис:
int strspn(string strl, string str2)
Возвращает длину начального сегмента строки strl, который содержит все символы из str2.
strstr — находит первое появление строки.
Синтаксис:
string strstr(string haystack, string needle)
Возвращает все haystack с первого появления строки needle и до конца. Если параметр needle не найден, то возвращается значение false. Если параметр needle не является строкой, то он переводится в целое число и рассматривается как числовое значение символа.
strtok — разбивает строку.
Синтаксис:
string strtok (string argl, String arg2')
Функция strtoko используется для разбивки строки. Мы можем разбить строку на отдельные слова, используя, например, пробел в качестве разделителя.
К
имер. Функция strtok ()\
$string = "This is an example string";
$tok = strtok($string," ");
while($tok) {
echo "Word=$tok<br>";
$tok = strtok(" ");
}
strtoiower — переводит строку в нижний регистр.
Синтаксис:
string strtoiower(string str)
Возвращает сроку str со всеми буквенными символами, переведенными в нижний регистр.
strtoupper — переводит строку в верхний регистр.
Синтаксис:
string strtoupper(string string)
Возвращает строку string со всеми буквенными символами, переведенными в верхний регистр.
str_repiace — заменяет все вхождения строки на указанную строку. Синтаксис:..
string str_replace(string needle, string str, string haystack^ Эта функция заменяет все вхождения строки needle в строке haystack на указанную строку str. Если вам не требуются особые правила замены, то следует всегда использовать эту функцию вместо функции ereg_replace().
Пример. Функция str_replaoe() Ii.l" ».... • ее е(е е.е e.le.e ..е.ее..е е е.ее... »е.пеi eiee.e.ee e t.i i .Hiee е е. .. е ее ■ lee i.rl
$bodytag = str_replace("%body%", "black", "<body text=%body%>");
strtr — переводит определенные символы. Синтаксис:
string strtr(string str, string from, string to)
Эта функция обрабатывает строку str, заменяя все появления каждого символа из строки from на соответствующие символы в строке to, и возвращает результат. Если строки from и to имеют различную длину, то дополнительные символы более длинной из строк игнорируются.
Пример. Функция strtr ()
$addr = strtr($addr, "дец", "аао");
Substr — возвращает часть строки.
Синтаксис:
string substr(string string, int start, int [length])
Эта функция возвращает часть строки string, определяемую параметрами start (начало) и length (длина). Если параметр start положительный,
то возвращаемая строка будет начинаться с символа в позиции start строки string.
Пример 1. функция substr()’•”:
$rest = substr("abcdef", 1); // вернет "bcdef" $rest = substr("abcdef", 1, 3) ; // вернет "bed"
Если параметр start отрицательный, то возвращаемая строка будет начинаться с символа в позиции start от конца строки string. Примеры: $rest = substr("abcdef", -1) ; // вернет "f" $rest = substr("abcdef", -2); // вернет "ef" $rest = substr("abcdef", -3, 1) ; // вернет "d"
Если параметр length указан и он положительный, то возвращаемая строка закончится за length символов от начала start. Это приведет к строке с отрицательной длиной (потому что начало будет за концом строки), следовательно, возвращаемая строка будет содержать один символ от начала строки start.
Если length указан и он отрицательный, то возвращаемая строка закончится за length от конца строки string. Это приведет к строке с отрицательной длиной, поэтому возвращаемая строка будет содержать один символ от начала строки start.
•■■•- •• ••’. ■■ 1
Пример 2. Функция substrQ . ,.:
$rest = substr("abcdef", -1, -1) ; // вернет "bede"
Trim — обрезает пробелы с начала и с конца строки.
Синтаксис:
string trim(string str)
Эта функция обрезает пробелы с начала и с конца строки и возвращает обрезанную строку.
uefirst — переводит первый символ строки в верхний регистр.
Синтаксис:
string uefirst(string str)
Делает прописным первый символ строки str, если этот символ буквенный.
ucwords — переводит в верхний регистр первые символы каждого слова в строке.
Синтаксис:
string ucwords(string str)
Делает прописным первый символ каждого слова в строке str, если этот символ буквенный.
Функции для работы с URL
Parse_uri — обрабатывает URL и возвращает его компоненты.
Синтаксис:
array parse_url (string uri).
Эта функция возвращает ассоциативный массив, включающий множество различных существующих компонентов URL. В их число входят scheme , host , port , user , pass , path , query И fragment .
Uridecode — декодирует URL-закодированную строку.
Синтаксис:.
string uridecode (string str)
Декодирует любые специальные символы, закодированные в указанной строке. Возвращается декодированная строка.
■ Пример. Функция uridecode ().
$а = split ('&', $querystring);
$i = 0;
while ($i < count ($a)) (
$b = split ('=', $a [$i]);
echo ’Value for parameter ', htmlspecialchars (uridecode ($b [0])),
’ is ', htmlspecialchars (uridecode ($b [1])), "<BR>";
$i++;
}
Uriencode — кодирует URL-строку.
Синтаксис:
string uriencode (string str)
Возвращает строку, в которой нет буквенно-цифровых символов (лишь _, тире). Они заменены на символ (%) со следующими за ним двумя шестнадцатеричными цифрами и пробелами, закодированными как символ (+). Это кодирование то же самое, что и кодирование данных, полученных методом post из HTML-формы; тип тот же, что и тип данных application/x-www-form-urlencoded.
Пример. Функция uriencode О , ,,.”
echo '<А HREF="mycgi?foo=’, uriencode ($userinput), "’>';
Base64_encode — кодирует данные в кодировке MIME base64.
Синтаксис:
string base64_encode (string data)
Функция base64_encodeо возвращает строку data, закодированную в кодировке base64. Эта кодировка разработана для того, чтобы передавать двоичные данные по транспортным уровням, которые не содержат восьмой бит, такие, например, как почта. Данные в кодировке base64 занимают примерно на 33% больше места, чем оригинал.
Base64_decode — декодирует данные, закодированные в кодировке MIME base64.
Синтаксис:
string base64_decode (string encoded_data)
Функция base64_decodeо декодирует encoded_data и возвращает оригинал данных. Возвращаемые данные могут быть двоичными.
Функции для работы с переменными
Gettype — получает тип переменной.
Синтаксис:
string gettype (mixed var)
Возвращает тип переменной var.
Возможные значения для возвращаемой строки:
integer ,
"double";
"string";
"array";
"object";
"unknown type".
intvai — возвращает целочисленное значение переменной.
Синтаксис:
int intvai (mixed var, int [base])
Возвращает целочисленное значение переменной var, используя указанное основание для перевода (по умолчанию 10). Переменная var может быть скалярного типа. Вы не можете использовать функцию intvai о для массивов или объектов.
Doubievai — получает значение переменной в формате double.
Синтаксис: double doubievai (mixed var) Возвращает значение double (с плавающей точкой) переменной var. Переменная var может быть скалярного типа. Вы не можете использовать функцию doubievai () для массивов и объектов.
Empty — определяет, присвоено ли переменной какое-либо значение. Синтаксис:
int empty (mixed var)
Возвращает значение false, если var существует и имеет не пустое или не нулевое значение, true в обратном случае.
is_array — определяет, входит ли переменная в массив.
Синтаксис:
int is_array (mixed var)
Возвращает значение true, если var есть в массиве, false в обратном случае.
is_doubie — определяет, имеет ли переменная тип double.
Синтаксис:
int is_double (mixed var)
Возвращает значение true, если var является типа double, false в обратном случае.
is_fioat — определяет, имеет ли переменная тип float.
Синтаксис:
int is_float (mixed var)
Эта функция является псевдонимом для функции is_doubie ().
is_int — определяет, имеет ли переменная тип integer.
Синтаксис:
int is_int (mixed var)
Эта функция является псевдонимом для функции is_iong ().
is_integer — определяет, имеет ли переменная тип integer.
Синтаксис:
int is_integer (mixed var)
Эта функция является псевдонимом для функции is_iong о .
is_iong — определяет, имеет ли переменная тип integer.
Синтаксис:
int is_long (mixed var)
Возвращает значение true, если var является типа integer (long), false в обратном случае.
is_object — определяет, имеет ли переменная тип object.
Синтаксис:
int is_object (mixed var)
Возвращает значение true, если var имеет тип object, false в обратном случае.
is_reai — определяет, имеет ли переменная тип real.
Синтаксис:
int is_real (mixed var)
Эта функция является псевдонимом для функции is_doubie ().
is_string — определяет, имеет ли переменная тип string.
Синтаксис:
int is_string (mixed var)
Возвращает значение true, если var является строкой, false в обратном случае.
isset — определяет, существует ли переменная.
Синтаксис:
int isset (mixed var)
Возвращает значение true, если var существует, false в обратном случае.
Если переменная была удалена функцией unseto, она больше не будет определяться функцией isset ().
а а в • а аава 1 «в • ■• вавв в■ вввв в е • • в ев в в в вв а в а в в е в, ~
. Пример.. Функция isset ()'■
$а = "test";
echo isset ($а) ; // true
unset ($a);
echo isset ($a) ; // false
settype — устанавливает тип переменной.
Синтаксис:
int settype (string var, string type)
Устанавливает тип переменной var как type.
Возможные значения типа type :
"integer";
"double";
"string";
"array";
"object".
Возвращает значение true при удачной установке типа, false в обратном случае.
strvai — получает строковое значение переменной.
Синтаксис:
string strvai (mixed var)
Получает строковое значение var. Переменная var может быть любого скалярного типа. Вы не можете использовать strvai () для массивов или объектов.
unset — удаляет указанную переменную.
Синтаксис:
int unset (mixed var) '
■ . Функция unseto уничтожает указанную переменную и возвращает значение true.
Пример. Функция unsett) ' .1
unset($foo);
unset($bar['quux']);
Приложение 4
Основные объекты JavaScript
JavaScript располагает средствами, позволяющими работать с различными типами объектов. Набор объектов JavaScript условно можно разделить на три части. Первая часть — это объекты, описанные как стандартные объекты в спецификации языка, именно эти объекты здесь рассматриваются. Вторая часть — объекты клиентского браузера, т. е. объекты, которые встроены в браузер и которые доступны для JavaScript. Третья часть — объекты клиентского документа, создаваемые браузером в соответствии с описанием объектной модели документа. Далее рассматриваются основные объекты JavaScript, описанные как стандарт языка JavaScript.
Объект Anchor
Объект Anchor - это якорь или ссылка, место в документе, с которым связана ссылка на другой документ или ссылка на фрагмент текущего документа (якорь). Объект клиентской части JavaScript.
Для задания якоря используется ярлык <а> или метод string.anchor. Объекты хранятся в коллекции document.anchors:
String.anchor(nameAttribute)
Объект Anchor является членом коллекций anchors и links.
Свойства
Свойства объекта Anchor приведены в табл. П4.1.
Таблица П4.1. Свойства объекта Anchor
Свойство Описание
NameИмя ссылки
TextТекст ссылки
Таблица П4.1 (окончание)
Свойство Описание.
XГоризонтальное положение левого края ссылки по отношению к лево
му краю документа, в пикселах
уВертикальное положение верхнего края ссылки по отношению к верх
нему краю документа, в пикселах
Методы
Объект Anchor наследует методы watch и unwatch из объекта object.
Объект Applet
Осуществляет вставку Java-апплета в HTML-страницу. Объект клиентской части JavaScript. Создается с использованием ярлыка <applet>. Объект является Элементом КОЛЛеКЦИИ document, applets.
Свойства■
Объект Applet наследует все открытые свойства Java-апплета.
Методы
Объект Applet наследует все открытые методы Java-апплета.
Объект Area
Задает область рисунка на карте ссылок.
Объект Array
Используется для работы с массивами. Объект ядра JavaScript.
Может быть создан с использованием функции-конструктора:
new Array(arrayLength);
new Array(elementO, elementl, ..., elementN).
Параметры
Параметры объекта Array приведены в табл. П4.2.
Таблица П4.2. Параметры объекта Array
Параметр
Описание
ArrayLength
ElementN
Начальная длина массива (количество элементов массива)
Элементы массива
Свойства
Свойства объекта Array приведены в табл. П4.3.
Таблица П4.3. Свойства объекта Array
Свойство
Описание
Constructor
Содержит функцию, которая создает прототип объекта
Index
—
Input
Для массива, образованного при поиске с использованием регулярного выражения. Содержит строку, по которой осуществлялся поиск
Length
Количество элементов массива
Prototype
Позволяет вставлять новые свойства в объект. Эти свойства будут унаследованы другими объектами по цепи наследования
Методы
Методы объекта Array приведены в табл. П4.4.
Таблица П4.4. Методы объекта Array
МетодОписание
Concat Объединяет два массива и возвращает новый массив
JoinОбъединяет все элементы массива в одну строку
Р°рУдаляет из массива последний элемент и возвращает этот элемент
PushВставляет один или несколько элементов в конецмассива и возвращает
длину нового массива
Reverse Обращает массив: первый элемент массива становится последним, а последний занимает место первого, остальные элементы также меняют свои места
Shift Удаляет первый элемент из массива и возвращает этот элемент
Slice Вырезает фрагмент массива и возвращает новый массив
Таблица П4.4 (окончание)
Метод
Описание
Splice
Sort
Добавляет или удаляет элементы из массива
Упорядочивает элементы массива
ToSource
Возвращает литерал массива
ToString
Unshift
Возвращает строку элементов массива
ValueOf
Возвращает значение элемента массива
Этот объект наследует методы watch и unwatch из объекта object.
Пример 1. Массив
msgArray = new Array()
msgArray[0] = "Hello"
msgArray[99] = "world"
// Длина массива — 100 элементов
if (msgArray.length = 100) myVar="The length is 100."
; Пример 2. Двумерный массив 1.-,':.
туУаг="Пример с многомерным массивом; " а = new Array(4) for (i=0; i < 4; i++) {
a[i] = new Array(4) for (j=0; j < 4; j++) { a[i][j] = "["+i+","+j+"]" } } for (i=0; i < 4; i++) { str = "Ряд "+i+":" for (j=0; j < 4; j++) { str += a[i][j] }'
myVar += str +"; " }
После выполнения строка myVar примет значение:
Пример с многомерным массивом;-■
Ряд 0:[0,0] [0,1] [0,2] [0,3];
Ряд 1:[1,0][1,1][1,2][1,3];
Ряд 2:[2,0] [2,1] [2,2] [2,3];
Ряд 3:[3,0][3,1][3,2][3,3];
Объект Boolean
Объект используется для работы с логическими значениями. Это объект ядра JavaScript. Объект может быть создан при помощи функции- конструктора:
new Boolean(value).
Параметры
Параметры объекта Boolean приведены в табл. П4.5.
Таблица П4.5. Параметры объекта Boolean
Параметр Описание
Value Начальное значение объекта. При необходимости значение может быть преобразовано к логическому типу. Если в качестве начального значения указаны 0, -0, null, false, NaN, undefined, пустая строка ("") или значение не указано, то значение будет преобразовано к логическому значению false. Все прочие значения, в том числе значения типов объектов или строковое значение "false", будут преобразованы к логическому значению true
Описание
Не следует путать примитивные логические значения true и false со значениями, которые возвращает логический объект. Это особенно важно при работе с условными выражениями. В условных выражениях любое значение, при проверке его на истинность, преобразуется к логическому типу. И если проверяется истинность выражения типа объекта, то любой объект, если только он не имеет значение null или underfined, будет сведен к логическому значению true даже тогда, когда этот объект является логическим объектом и имеет логическое значение false.
х = new Boolean(false);
if(x) //Условие выполняется, значение true.
Однако для примитивных логических значений подобного поведения не будет:
х = false;
if(х) // Значение false
Отсюда совет: для преобразования типа в логический тип не следует пользоваться логическим объектом. Вместо объекта целесообразнее использовать функцию Boolean:
х = Boolean(expression) //желательно
х = new Boolean(expression) //не желательно
Еще несколько примеров задания объектов:
myFalse=new Boolean(false) g=new Boolean(myFalse) myString=new String("Hello") s=new Boolean(myString)myFalse=new Boolean(false) g=new Boolean(myFalse) myString=new String("Hello") s=new Boolean(myString)//начальное значение false//начальное значение false//начальное значение true//строковый объект//начальное значение true//начальное значение true//строковый объект//начальное значение true
myFalse=new Boolean(false) g=new Boolean(myFalse) myString=new String("Hello") s=new Boolean(myString)
myFalse=new Boolean(false) g=new Boolean(myFalse) myString=new String("Hello") s=new Boolean(myString)
//начальное значение false
//начальное значение false
//начальное значение true
//строковый объект
//начальное значение true
//начальное значение true
//строковый объект
//начальное значение true
Свойства
Свойства объекта Boolean приведены в табл. П4.6.
Таблица П4.6. Свойства объекта Boolean
Свойство
Описание
Constructor
Функция, создающая прототип объекта
Prototype
Задает свойство, доступное всем объектам Boolean
Методы
Методы объекта Boolean приведены в табл. П4.7.
Таблица П4.7. Методы объекта Boolean
Метод
Описание
ToSource
Возвращает литерал объекта.
ToString
Возвращает строку, представляющую данный объект
ValueOf
Возвращает примитивное значение объекта
Объект наследует методы watch и unwatch из объекта object.
. Примеры объектов с начальным значением false
bNoParam = new Boolean()
bZero = new Boolean(0) bNull = new Boolean(null) bEmptyString = new Boolean("") bfalse = new Boolean(false)
. Примеры объектов с начальным значением true■'■.:" л- =
btrue = new Boolean(true)
btrueString = new Boolean("true")
bfalseString = new Boolean("false") bSuLin = new Boolean("Su Lin")■
Объект Button
Это клиентский объект JavaScript, используется для создания кнопки в форме HTML.
Может быть создан с использованием ярлыка HTML cinput type= "button">. Во время работы будет создан объект Button и помещен в массив elements для соответствующей формы. Каждый объект кнопки Button может быть доступен как с помощью указания индекса элемента в массиве elements, так и по имени, если имя задано в виде значения атрибута name.
Функции обработки событий, используемые в объекте Button:
OnBiur;
О onClick;
О onFocus;
О onMouseDown;
О onMouseUp.
Описание
Объект Button является элементом формы и может быть определен только в пределах HTML-кода, соответствующего элементу Form, описанному при помощи ярлыка <form>.
Свойства
Свойства объекта Button приведены в табл. П4.8.
ТаблицаП4.8. Свойства объекта Button
Свойство
Описание
Form
Указывает форму, в которой содержится объект Button
Name
Имя объекта
Type
Тип
Value
Значение
Методы
Методы объекта Button приведены в табл. П4.9.
' .Таблица П4.9. Методы объекта Button
МетодОписание
BlurУдаляет фокус с кнопки
ClickИмитирует щелчок мыши на кнопке
FocusПеремещает фокус на кнопку
HandleEventВызывает функцию обработки указанного события
Объект наследует методы watch и unwatch из объекта object.
Пример с кнопкой-’-
<INPUT TYPE="button" VALUE="Calculate" NAME="calcButton" onClick="calcFunction(this.form)">
Синтаксис использования метода handleEvent:
handleEvent(event)
где event — вызываемое событие.
Объект Checkbox
Объект представляет собой поле для отметки в HTML-форме. Оно может иметь два значения (стоит отметка или отметка отсутствует), значения меняются при щелчке мышкой над полем. Объект клиентской части JavaScript.
Объект может быть создан при помощи ярлыка <input type= "checkbox">. Объект помещается в коллекцию (массив) elements данной формы.
Функции обработки событий
Приведем функции обработки событий:
onBlur;.
onClick;
onFocus.1
Описание
Объект Checkbox является элементом формы. Он может быть определен во фрагменте HTML-кода, который соответствует элементу, описываемому при помощи ярлыка <form>.
Свойства
Свойства объекта Checkbox приведены в табл. П4.10.
Таблица П4.10. Свойства объекта Checkbox
Свойство
Описание
Checked
Свойство принимает логическое значение, соответствующее текущему состоянию поля для отметки (отмечено/не отмечено)
DefaultChecked
Логическое свойство, устанавливающее начальное значение атрибута CHECKED
Form
Указывает форму, содержащую данный объект Checkbox
Name
Имя объекта name
Type
Значение атрибута type
Value
Значение переменной Value
Методы
Методы объекта Checkbox приведены в табл. П4.11.
'Таблица П4.11. Методы объекта Checkbox
Метод
Описание
Blur
Снимает фокус с объекта
Click
Имитирует щелчок мыши на объекте
Focus
Устанавливает фокус на объекте
HandleEvent
Вызывает функцию обработки указанного события
Наследует методы watch и unwatch из объекта object.
Объект Date
Используется для работы с датами, числами, временем. Объект ядра JavaScript.
Объект может быть создан с использованием функции-конструктора:
new Date()
new Date(milliseconds)
new Date(datestring)
new Date(yr_num, mo_num, day_num
[, hr_num, min_num, sec_num, ms_num])
Параметры
Параметры, используемые в объекте Date, приведены в табл. П4.12.
Таблица П4.12. Параметры объекта Da te
Параметр
Описание
Milliseconds
Целое число— количество миллисекунд, истекших с 1 января 1970 года с 0 часов 0 минут 0 секунд
■Datestring
Строка, содержащая дату
Yr_num, mo_num, day_num
Целочисленные значения, соответствующие году, месяцу (с 0 до 11), дню месяца
Hr_num, min_num,
Целочисленные значения, соответствующие часу дня, минутам, секундам, миллисекундам
sec_num, ms_num
Описание
Если в качестве аргументов объекта Date будут указаны не все значения, то опущенные значения принимаются равными 0. Можно опустить значения часов, минут, секунд и миллисекунд, но нужно указать по крайней мере год, месяц и дату. Полезно иметь в виду, что в сутках содержится 86 400 000 миллисекунд. Для удобства работы с числом лет существуют методы getFullYear, setFullYear, getFullUTCYear, setFullUTCYear.
Свойства
Свойства объекта Date приведены в табл. П4.13.
Таблица П4.13. Свойства объекта Date
Свойство
■ Описание
Constructor
Функция для создания прототипа объекта
Prototype
Используется для создания свойств объекта Date
Методы
Методы объекта Date приведены в табл. П4.14.
Таблица П4.14. Методы объекта Date
Метод
Описание
GetDate
Возвращает день месяца (дату)
GetDay
Возвращает день недели
GetFullYear
Возвращает год
GetHours
Возвращает часы
GetMilliseconds
Возвращает миллисекунды
GetMinutes
Возвращает минуты
GetMonth
Возвращает месяц
GetSeconds
Возвращает секунды
GetTime
Возвращает время
GetTimezoneOffset
Возвращает временную поправку для зоны местного времени
GetUTCDate
Возвращает дату (по универсальному времени)
GetUTCDay
Возвращает день недели (по универсальному времени)
GetUTCFullYear
Возвращает год по универсальному времени
GetUTCHours
Возвращает часы по универсальному времени
GetUTCMilliseconds
Возвращает миллисекунды по универсальному времени
GetUTCMinutes
Возвращает минуты по универсальному времени
GetUTCMonth
Возвращает месяц по универсальному времени
GetUTCSeconds
Возвращает секунды по универсальному времени
GetYear
Возвращает год
Parse'
Возвращает дату в виде строки, аргумент — количество миллисекунд, истекших с 1 января 1970
SetDate
Устанавливает месяц и дату местного времени
SetFullYear
Устанавливает год (полное число) по местному времени
SetHours
Устанавливает часы по местному времени
SetMilliseconds
Устанавливает миллисекунды по местном времени
SetMinutes
Устанавливает минуты по местному времени
SetMonth
Устанавливает месяц по местному времени
SetSeconds
Устанавливает секунды по местному времени
SetTime
Устанавливает время (местное)
SetUTCDate
Устанавливает дату по универсальному времени
Таблица П4.14 (окончание)
Метод
Описание
SetUTCFullYear
Устанавливает год (полное число) по универсальному времени
SetUTCHours
Устанавливает часы по универсальному времени
SetUTCMilliseconds
Устанавливает миллисекунды по универсальному времени
SetUTCMinutes
Устанавливает минуты по универсальному времени
SetUTCMonth
Устанавливает месяц по универсальному времени
SetUTCSeconds
Устанавливает секунды по универсальному времени
SetYear
Устанавливает год по местному времени
ToGMTString
Переводит дату в строку
ToLocaleString
Переводит дату в строку по местному времени
ToSource
Возвращает литерал объекта даты
ToString
Возвращает строку, соответствующую объекту Date
ToUTCString
Преобразует дату к строке по универсальному времени
UTC
Возвращает количество миллисекунд, истекших с 1 января 1970 года до текущего момента
ValueOf
Возвращает примитивное значение объекта Date
Объект наследует методы watch и unwatch из объекта object.
. Примеры с объектом Date■
today = new Date()
birthday = new Date("January 19, 1991 05:24:00")
birthday = new Date(91,0,19)
birthday = new Date(91,0,19,5,24,0)
Объект Document
Объект содержит информацию, касающуюся текущего документа. Он имеет методы, с помощью которых можно задать способ того, как будет показан текущий документ пользователю в окне браузера. Объект клиентской части JavaScript.
Он может быть создан при помощи ярлыка <body>. Для каждого документа, для каждой странички создается свой объект Document. Каждый объект window обладает свойством document, значением этого свойства является объект Document.
В объекте Document используются функции обработки таких событий, как:
onClick;
onDblClick;
onKeyDownJ
onKeyPress;
onKeyUp;
onMouseDown;
onMouseUp.
Свойства
Свойства объекта Document приведены в табл. П4.15.
Таблица П4.15. Свойства объекта Document
Свойство
Описание
AlinkColor
Цвет ссылки
Anchors
Массив всех ссылок документа
Applets
Массив всех апплетов документа
BgColor
Цвет фона
Classes
Задает объект типа style для задания стилей HTML с указанием атрибута класса class
Cookie
Задает строку cookie
Domain
Имя сервера, предоставившего документ
Embeds
Массив всех внешних вставок в документ (или плагинов)
FgColor
Цвет текста документа
FormName
Имя для именованной формы в документе
Forms
Массив всех форм документа
Height
Высота документа в пикселах
Ids
Создает объект типа style с идентификатором
Images
Массив всех картинок документа
LastModified
Строка, указывающая дату последнего изменения документа
Layers
Массив всех слоев документа (для Netscape)
LinkColor
Цвет ссылки
Links
Массив всех ссылок документа
Таблица П4.15 (окончание)
Свойство
Описание
Plugins
Массив всех возможностей документа
Referrer
Строка, указывающая адрес URL вызывающего документа
Tags
Ярлыки документа
Title
Строка с содержимым элемента <title>
URL
Полный адрес URL документа
VlinkColor
Цвет ссылки
Width
Ширина документа в пикселах
Методы
Методы объекта Document приведены в табл. П4.16.
Таблица П4.16. Методы объекта Document
Метод
Описание
CaptureEvents
Документ будет перехватывать все события указанного типа
Close
Закрывает поток вывода и показывает данные
Contextual
GetSelection
Возвращает строку текущего выбора
HandleEvent
Вызывает функцию обработки указанного события
Open
Открывает поток для получения данных с использованием методов write и writein
ReleaseEvents
Заставляет документ или окно "освободить" перехваченное событие указанного типа и посылает это событие далее по иерархии
RouteEvent
Передает перехваченное событие далее по нормальной цепи иерархии
Write
Записывает одну или несколько HTML-инструкций в документ в заданном окне
Writein
То же, что write, но с добавлением знака конца строки
Наследует методы watch и unwatch из объекта object.
/Пример с объектом документа. Файл doc0.html
<HTML>
<HEAD>
<TITLE>Document object example</TITLE>
</HEAD>
<FRAMESET COLS="30%, 70%">'
<FRAME SRC="docl.html" NAME="framel">
<FRAME SRC="doc2.html" NAME="frame2">
</FRAMESET>
</HTML>
' Пример с объектом документа. Файл doc1.html
<HTML>
<SCRIPT>
</SCRIPT>
<BODY
BGCOLOR="antiquewhite"
TEXT="darkviolet"
LINK="fuchsia"
ALINK="forestgreen"
VLINK="navy">
<PXB>Some links</B>
<LIXA HREF="doc2.html#numbers" TARGET="frame2">Numbers</A>
<LIXA HREF="doc2.html#colors" TARGET="frame2">Colors</A>
<LIXA HREF="doc2.html#musicTypes" TARGET="frame2">Music types</A>
<LIXA HREF="doc2.html#countries" TARGET="frame2">Countries</A>
</BODY>
</HTML>
: Пример с объектом документа. Файл doc2.html
<HTML>
<SCRIPT>
</SCRIPT>
<BODY
BGCOLOR="oldlace" onLoad="alert(1 Привет всем!')"
TEXT="navy">
<РХА NAME="numbers"><B>HeMHOro чисел</В></А>
<UL><LI>OflHH
<Ы>два
<Ы>три
<Ы>четыре</иь>
<РХА НАМЕ="со1огз"хВ>Немного цветов</Вх/А>
<иЬХЫ>красный
<Ы>оранжевый
<Ы>желтый
<Ы>зеленый</иь>
<РХА NAME="musicTypes"XB>HeMHoro музыки</Вх/А>
<ULXLI>Pok
<Ы>Джаз
<Ы>Лабуда
<Ы>Тишина</иь>
<РХА NAME="countries"XB>HeMHoro стран</Вх/А>
<ULXLI>Cobok
<Ы>Советский союз
<Ы>Союз нерушимый
<Ы>Польша</иЬ>
</BODY>
</HTML>
Объект Event
Объект Event содержит свойства, которые описывают события JavaScript. Это объект клиентской части JavaScript.
Объект Event содержит информацию, которая указывает на то, какой тип события соответствует данному объекту Event. Например, в случае с событием MouseDown объект Event будет содержать информацию о том, что произошло именно событие MouseDown. Кроме ЭТОГО, В объекте Event будет содержаться информация о горизонтальном и вертикальном положении указателя мыши на экране в момент наступления события (х и у), номер нажатой кнопки мыши, а также информация об удерживаемой в момент нажатия кнопки мыши дополнительной клавиши-модификатора (<Control>, <Alt>, <Shift>). Конкретный набор свойств объекта Event зависит от того, какой ТИП события связан С данным объектом Event.
Объект события Event возникает в клиентском приложении в момент наступления того или иного события. Мы не имеем возможности вызвать событие по своему желанию в общем случае с использованием программных средств.
Свойства
Не все из приведенных свойств доступны для каждого из возможных типов событий и соответствующих им объектов Event. Конкретный набор свойств объекта события зависит от того, какой тип события соответствует данному объекту Event.
Свойства объекта приведены в табл. П4.17.
Таблица П4.17. Свойства объекта Event
Свойство
Описание
Data
Содержит массив строк адресов URL "перетащенных" объектов
Height
Высота окна или фрейма
Modifiers
Строка, содержащая клавишу-модификатор: alt_mask, control_mask, SHIFT_MASK, META_MASK
PageX
Число — горизонтальное положение курсора в пикселах по отношению к странице
PageY
Число — вертикальное положение курсора в пикселах по отношению к странице
ScreenX
Число — горизонтальное положение курсора в пикселах по отношению к экрану
ScreenY
Число — вертикальное положение курсора в пикселах по отношению к экрану
Target
Строка, содержащая информацию об объекте, которому было первоначально направлено событие (используется для всех событий)
Type
Строка, содержащая тип события type (используется во всех событиях)
Which
Число, соответствующее номеру нажатой кнопки мыши (1 — левая, 2 — средняя, 3 — правая), или ASCII значение нажатой клавиши
Width
Ширина окна или фрейма
Объект наследует методы watch и unwatch из объекта object.
В приведенном ниже примере выводится окно-предупреждение, в котором содержится тип события:
<А HREF="http://home.netscape.com" onClick='alert("Ссылка вызвала событие: "
+ event.type)'>Щелкните ссылку</А>
В следующем примере использован объект события Event для получения координат курсора мыши:
<SCRIPT>
function funl(evnt) {
alert ("Возникло событие: " + evnt.type);
alert ("Координата х равна " + evnt.layerX);
alert ("Координата у равна " + evnt.layerY);
if (evnt.modifiers & Event.ALT_MASK)
alert ("При наступлении события была нажата клавиша Alt."); return true;
}
document.onmousedown = funl;
</SCRIPT>
Объект Filellpload
Этот объект соответствует элементу <input type= "fiie"> в HTML- разметке, с помощью которого пользователь имеет возможность осуществить отсылку файла серверу. Это объект клиентской части.
Объект создается при помощи ярлыка <input type= "fiie">. Для формы, в которой используется указанный ярлык, создается объект Fileupload и помещается в коллекцию elements соответствующего объекта Form. Объект Fileupload может быть доступен с указанием индекса соответствующего элемента массива elements или с использованием атрибута name.
События
События объекта Fileupload приведены ниже:
О onBlurJ
onChange;
onFocus.
Свойства
Свойства объекта Fileupload приведены в табл. П4.18.
Таблица П4.18. Свойства объекта Fileupload
Свойство
Описание
Form
Форма, содержащая объект Fileupload
Name
Имя объекта
Type
Тип
Value
Текущее значение — имя посылаемого файла
Методы
Методы объекта Fileupload приведены в табл. П4.19.
Таблица П4.19. Методы объекта Fileupload
Метод
Описание
Blur
Удаляет фокус с объекта
Focus
Устанавливает фокус на объекте
HandleEvent
Вызывает функцию обработки для указанного события
Select
Выбор объекта
Объект Form
Этот объект используется тогда, когда необходимо предоставить пользователю право осуществления выбора одной из возможностей (поля для отметки, радиокнопки, списки выбора) и ввода текста. Затем введенная информация (осуществленный выбор, введенный текст) может быть отправлена для обработки на сервер. Это объект клиентской части JavaScript.
Объект может быть создан с применением HTML-ярлыка <from>. К объекту можно обратиться, указав соответствующий индекс элемента массива document.forms, в котором хранятся все формы текущего документа. Доступ к нему можно также осуществить по имени, если атрибут имени был задан в ярлыке <form>.
К элементам формы можно обращаться с указанием индекса (порядкового номера) элемента в массиве всех элементов данной формы Form.elements. Если несколько элементов одной формы имеют одно и то же значение атрибута name, то автоматически создается массив элементов с данным именем.
События
События объекта Form:
onReset;
onSubmit.
Свойства
Свойства объекта Form приведены в табл. П4.20.
Таблица П4.20. Свойства объекта Form
Свойство
Описание
Action
Соответствует атрибуту ACTION
Elements
Массив всех элементов формы
Encoding
Значение атрибута ENCTYPE
Length
Количество элементов формы
Method
Соответствует атрибуту method
Name
Соответствует атрибуту name
Target
Соответствует атрибуту target
Методы
Методы объекта Form приведены в табл. П4.21.
Таблица П4.21. Методы объекта Form
Метод
Описание
HandleEvent
Вызывает функцию обработки указанного события
Reset
Имитирует щелчок мыши на кнопке обновления формы Reset
Submit
Отсылает форму
Объект наследует методы watch и unwatch из объекта object.
Объект Frame
В одном окне можно показать несколько независимых друг от друга фреймов, причем каждый фрейм может содержать документ со своим собственным адресом URL. Фреймы создаются при помощи ярлыков <frame>, причем эти ярлыки должны быть помещены внутри элемента, описанного при помощи ярлыка <frameset>. Каждый фрейм может ссылаться на любые URL-адреса, в свою очередь, любой фрейм может быть указан в качестве значения атрибута target, т. е. любой фрейм может стать "контейнером" для загрузки страницы с произвольным URL.
Каждый объект фрейма frame является объектом окна window. Объект окна фрейма немного отличается от окна высшего уровня. Это объект клиентской части JavaScript.
Объект Function
Этот объект содержит строку кода JavaScript, которая компилируется, как функция. Объект ядра JavaScript.
Объект может быть создан при помощи функции-конструктора:
new Function ([argl[, arg2[, . .. argN] ], ] functionBody)
Функция описывается с использованием слова function:
function name([param[, param[, ... param]]]) {
statements
}
Параметры
Параметры объекта Function приведены в табл. П4.22.
Таблица П4.22. Параметры объекта Function
Параметр
Описание
Argl, arg2, ... argN
Формальные аргументы функции, каждый параметр должен быть допустимым в JavaScript идентификатором
Function
Body
Строка, содержащая инструкции JavaScript
Name
Имя функции
Param
Имена аргументов, передаваемых функции; функция может иметь до 255 аргументов
Statements
Выражения, составляющие тело функции
Создание функции, присвоение функции переменной с использованием конструктора Function во многом подобно созданию функции с использованием слова function. Однако здесь есть некоторые отличия:
когда функция присваивается переменной с использованием конструктора, например, var peremennaya = new Function ("..."), TO переменная peremennaya содержит ссылку на вновь созданную с помощью конструктора функцию;
когда мы создаем функцию с помощью слова function, например, function peremennaya () {...}, ТО сейчас peremennaya— ЭТО не переменная, а имя функции.
Функции могут быть вложенными одна в другую. Вложенная функция доступна только в пределах содержащей ее функции. Она может оперировать
с переменными и аргументами содержащей ее функции. Содержащая функция не может работать с переменными и аргументами вложенной функции.
Пример описания функций и создания объектов функций ••
function addSquares (a,b) { function square(x) { return x*x
}
return square(a) + square(b) }
a=addSquares(2,3) // возвращает 13
b=addSquares(3,4) // возвращает 25
c=addSquares(4,5) // возвращает 41
function outside(x) { function inside(y) { return x+y
} return inside }
result=outside(3)(5) // возвращает 8
С помощью конструктора объекта функции можно задать функцию обработки того или иного события следующим образом:
window.onfocus = new Function("document.bgColor='antiquewhite'")
Если функция присвоена переменной, то средству обработки того или иного события можно присвоить эту переменную:
var setBGColor = new Function("document.bgColor='antiquewhite'")
document.formi.colorButton.onclick=setBGColor
CINPUT NAME="colorButton" TYPE="button"
УАШЕ="Меняем цвет фона"
onClick="setBGColor()">
Свойства
Свойства объекта Function приведены в табл. П4.23.
Таблица П4.23. Свойства объекта Function
Свойство
Описание
Arguments
Массив аргументов, передаваемых функции
Arguments.callee
Тело выполняемой в данный момент функции
Arguments.caller
Имя функции, которая вызвала выполняемую в данный момент функцию
Arguments.length
Количество аргументов, переданных функции
Arity
Количество аргументов, ожидаемых функцией
Constructor
Функция, создающая прототип объекта
Length
Количество аргументов, описанных в функции
Prototype
Свойство позволяет осуществлять вставку новых свойств в объект функции Function
Методы
Методы объекта Function приведены в табл. П4.24.
Таблица П4.24. Методы объекта Function
Метод
Описание
Apply
Этот метод позволяет применить метод из другого объекта
Call
Вызов и выполнение метода другого объекта
ToSource
Возвращает строку, содержащую код функции
ToString
Возвращает строку, содержащую код функции
ValueOf
Возвращает строку, содержащую код функции
Объект Hidden
Этот текстовый объект содержит текст, который не будет показан на экране в окне браузера. Скрытый объект Hidden может быть использован для передачи пар name-value при отправке форм. Объект клиентской части JavaScript.
Объект создается при помощи ярлыка <input type= "hidden">. Скрытые объекты помещаются в коллекцию elements. Доступ к ним можно осуществить с указанием индекса объекта в массиве elements или с указанием имени (если имя было задано).
Объект Hidden является элементом формы и должен быть определен внутри элемента <form>. Этот объект не может быть видимым и не может быть
изменен пользователем, однако его содержание может быть изменено программными средствами, например, путем изменения свойства value. Объект Hidden может быть использован для обмена данными при организации связи между клиентом и сервером.
Свойства
Свойства объекта Hidden приведены в табл. П4.25.
Таблица П4.25. Свойства объекта Hidden
Свойство
Описание
Form
Форма, содержащая объект Hidden
Name
Атрибут имени name
Type
Атрибут типа type
Value
Текущее значение объекта Hidden.
Объект наследует методы watch и unwatch из объекта object.
, Пример с объектом hidden'...
<HTML>
<HEAD>
<Т1ТЬЕ>Скрытый объект Hidden</TITLE>
</HEAD>
<BODY>
<В>Щелкните один из объектов, а затем нажмите кнопку "Показать значение"
<BR> — вы увидите содержимое объекта, по которому щелкнули предваритель- но.</В>
<FORM NAME="myForm">
<INPUT TYPE="hidden" NAME="hiddenObject" VALUE="None">
<P>
<INPUT TYPE="button" VALUE="Click me" NAME="buttonl"
onClick="document.myForm.hiddenObject.value=this.value">
<P>
<INPUT TYPE="radio" NAME="musicChoice" VALUE="soul-and-r&b"
onClick="document.myForm.hiddenObject.value=this.value"> Soul and R&B
<INPUT TYPE="radio" NAME="musicChoice" VALUE="jazz"
onClick="document.myForm.hiddenObject.value=this.value"> Jazz
<INPUT TYPE="radio" NAME="musicChoice" VALUE="classical"
onClick="document.myForm.hiddenObject.value=this.value"> Classical
<P>
<SELECT NAME="music_type_single"
onFocus="document.myForm.hiddenObject.value= this.options[this.selectedlndex].text">
<OPTION SELECTED> Red <OPTION> Orange <OPTION> Yellow
</SELECT>
<PXINPUT TYPE="button" VALUE="Display hidden value" NAME="button2"
onClick="alert('Last object clicked: ' +
document.myForm.hiddenObject.value)">
</FORM>
</BODY>
</HTML>
Объект History
Объект содержит массив адресов URL тех ссылок, которые "посещались" клиентом с использованием данного окна. Объект клиентской части JavaScript.
Это заранее определенный объект, к которому можно обратиться с помощью свойства history в объекте window.
Свойства
Свойства объекта History приведены в табл. П4.26.
Таблица П4.26. Свойства объекта History
Свойство
Описание
Current
■ Адрес URL текущей страницы
Length
Количество элементов массива history
Next
Следующий элемент в коллекции history
Previous
Предыдущий элемент в коллекции history
Методы
Методы объекта History приведены в табл. П4.27.
Метод
Описание
Back
Загружает предыдущую ссылку
Forward
Загружает последующую в коллекции history ссылку
Go
Загружает указанную ссылку из коллекции history
Объект наследует методы watch и unwatch из объекта object.
i Примеры с объектом history.
history.go(-3)
window2.history.back()
parent.frames[1].history.back()
parent.framel.history.back()
window2.frame2.history.back()
document.writein("<B>history is</B> " + history)
Объект Image
Объект представляет собой рисунок в HTML-форме. Объект клиентской части JavaScript.
Объект рисунка создается при помощи ярлыка <img>. Все объекты рисунков помещаются в коллекцию document.images. К рисункам можно обращаться при помощи указания индекса элемента в этом массиве. Объект рисунка можно создать и с помощью функции конструктора:
new Image([width,] [height])
Параметры
Параметры объекта image приведены в табл. П4.28.
Таблица П4.28. Параметры объекта image
Параметр
Назначение
Width
Ширина рисунка в пикселах
Height
Высота рисунка в пикселах
События
Ниже представлены события объекта image:
OnAbort;
OnError;
OnKeyDown;
OnKeyPress;
OnKeyUp;
OnLoad.
Если объект рисунка создан при помощи конструктора объекта рисунка image, то для того, чтобы задать функцию обработки события для такого объекта, можно использовать соответствующие свойства этого объекта: imageName.onabort = handlerFunction imageName.onerror = handlerFunction imageName.onkeydown = handlerFunction imageName.onkeypress = handlerFunction imageName.onkeyup = handlerFunction imageName.onload = handlerFunction
Объект рисунка Image не содержит событий onClick, onMouseOut, onMouse- Over. Этот "недостаток" можно компенсировать, если для данного рисунка задать объект Area или поместить рисунок внутри объекта Link, при этом будет возможность воспользоваться функциями обработки событий для объектов ССЫЛОК Area и/или Link.
Свойства
Свойства объекта image приведены в табл. П4.29.
Таблица П4.29. Свойства объекта image
Свойство
Описание
Border
Атрибут BORDER
Complete
Содержит логическое значение, определяющее, закончена ли загрузка рисунка в браузер
Height
Высота рисунка, атрибут height
Hspace
Атрибут HSPACE
Lowsrc
Атрибут LOWSRC
Name
Имя объекта рисунка, атрибут NAME
Таблица П4.29 (окончание)
Свойство
Описание
Src
Источник рисунка, атрибут SRC
Vspace
Атрибут VSPACE
Width
Ширина рисунка, атрибут width
Методы
Методы объекта image приведены в табл. П4.30.
Таблица П4.30. Методы объекта image
Метод
Описание
HandleEvent
Вызывает функцию обработки указанного события
Объект наследует методы watch и unwatch из объекта object.
Объект Java
Это объект верхнего уровня в JavaScript. Он используется для того, чтобы иметь возможность осуществить доступ к классам Java в пакете java.*. Объект ядра JavaScript.
Это заранее определенный объект, доступ к которому может быть осуществлен непосредственно, причем этот объект не требуется создавать ни с помощью конструктора, ни с помощью каких-либо иных методов. Объект Java является СИНОНИМОМ свойства Packages, java.
Объект JavaArray
Объект представляет Java-массив, доступный из JavaScript-кода. Объект ядра JavaScript.
Объект может быть создан любым методом Java, который возвращает массив. Объект JavaArray, содержащий любой тип данных, с использованием метода newinstance в классе Array, приведен ниже:
public static Object newinstance(Class componentType, int length)
throws NegativeArraySizeException
Свойства
Свойства объекта JavaArray приведены в табл. П4.31.
Таблица П4.31. Свойства объекта JavaArray
Свойство
Описание
Length
Количество элементов в массиве
Объект JavaClass
Это ссылка из JavaScript на класс Java. Объект ядра JavaScript.
Объект может быть создан с использованием объекта Packages:
Packages.JavaClass
причем JavaClass — полное ИМЯ класса Java.
Пример с объектом JavaClass-' *
х = java.awt.Font
myFont = x("helv",x.BOLD,10)
Объект JavaObject
Это объект языка Java, используемый в JavaScript. Объект ядра JavaScript.
Любой метод языка Java, который возвращает объект, может быть использован для того, чтобы создать объект JavaObject. Кроме того, можно воспользоваться функцией-конструктором с указанием ключевого слова Packages:
new Packages.JavaClass(parameterList)
здесь Javaciass — имя объекта.
Параметры
Параметры объекта JavaObject приведены в табл. П4.32.
Таблица П4.32. Параметры объекта JavaObject
ПараметрОписание
ParameterListСписок параметров (необязательный)
; Примеры с объектом JavaObjectI
Создание объекта Java в JavaScript:
class java. lang.String:
var theString = new Packages.java.lang.String("Hello, world");
ИЛИ
var theString = new java.lang.String("Hello, world");
Обращение к методам в объекте java:
var theString = new java.lang.String("Hello, world") theString.startsWith("Hello") // возвращает true
Объект Layer
Соответствует слою на HTML-странице. Создается при помощи ярлыков
<LAYER> ИЛИ <ILAYER>.
События
События Объекта Layer:
onMouseOverJ
onMouseOut;
onLoadJ
onFocus;
onBlur.
Свойства
Свойства объекта Layer приведены в табл. П4.33.
Таблица П4.33. Свойства объекта Layer
Свойство
Описание
Above
Объект Layer, расположенный выше данного по нумерации z- индексов, либо окно, содержащее слой, если нет вышерасположенного слоя
Background
Рисунок, используемый в качестве фона слоя
BgColor
Цвет фона слоя
Below
Объект Layer, расположенный ниже по порядку z-индексов, или null, если нет нижерасположенного слоя
Таблица П4.33 (окончание)
Свойство
Описание
Clip.bottom
Нижний край видимой части слоя
Clip.height
Высота видимой части слоя
Clip.left
Левый край видимой части слоя
Clip.right
Правый край видимой части слоя
Clip.top
Верхний край видимой части слоя
Clip.width
Ширина видимой части слоя
Document
Документ, связанный со слоем
Left
Горизонтальное положение левого края слоя по отношению к родительскому слою
Name
Имя слоя
PageX
Горизонтальное положение слоя в пикселах по отношению к странице
PageY
Вертикальное положение слоя в пикселах по отношению к странице
ParentLayer
Объект Layer, являющийся родительским для данного слоя, если нет родительского слоя — то объект Window, содержащий данный слой
SiblingAbove
Вышерасположенный слой, имеющий такой же родительский слой. Если слоя нет, то null
SiblingBelow
Нижерасположенный слой, имеющий такой же родительский слой. Если слоя нет, то null
Src
Адрес URL содержимого слоя (строка)
Top
Вертикальное положение верхнего края слоя в пикселах по отношению к родительскому слою
Visibility
Видим или не видим данный слой
Window
Объект Window или объект Frame, содержащий данный слой независимо от того, является ли слой вложенным в другой слой
X
Синоним для Layer.left
Y
Синоним для Layer. top
Zindex
Относительное значение z-индекса по отношению к соседним слоям
Методы
Методы объекта Layer приведены в табл. П4.34.
Таблица П4.34. Методы объекта Layer
Метод
Описание
CaptureEvents
HandleEvent
Задает режим перехвата всех событий указанного типа
Вызывает функцию обработки события для указанного события
Load
Заменяет содержимое слоя на указанное
MoveAbove
Помещает слой поверх слоя, указанного в качестве аргумента без изменения вертикального и горизонтального положения слоя
MoveBelow
Помещает слой ниже слоя, указанного в аргументе, без изменения горизонтального и вертикального положения слоя
MoveBy
Изменяет положение слоя на указанное, в качестве аргументов — количество пикселов
MoveTo
Перемещает верхний левый угол к указанным координатам экрана
MoveToAbsolute
Перемещает слой к указанным координатам страницы
ReleaseEvents
Задает режим высвобождения перехваченных событий указанного типа, события пересылаются далее по иерархии объектов
ResizeBy
Изменяет размер слоя в соответствии с указанными аргументами в пикселах
ResizeTo
Изменяет размер слоя, задавая высоту и ширину, равными указанному количеству пикселов
RouteEvent
Передает перехваченное событие по обычному пути иерархии объектов
Объект Link
Объект представляет собой фрагмент текста, или рисунок, или фрагмент рисунка, описанный как гипертекстовая ссылка. Клиентский объект. Объект Area — это разновидность объекта Link. Создается при помощи ярлыков <а> или <агеа> или методом st ring.link. Объект является элементом массива document.link.
События
Объект Area реагирует на следующие события:
onDblClick;'
onMouseOut;
onMouseOver.
Объект Link имеет такие события:
onClick;
onDblClickJ
onKeyDown;
onKeyPress",
onKeyUp;
onMouseDown;
onMouseOut;
onMouseUp;
onMouseOver.
Свойства
Свойства объекта Link приведены в табл. П4.35.
Таблица П4.35. Свойства объекта Link
Свойство
Описание
Hash
Ссылка на URL
Host
Имя хоста, домен, или IP
Hostname
Часть URL host:port
Href
URL целиком
Pathname
Часть, относящаяся к URL в адресе
Port
Номер порта
Protocol
Протокол, часть URL до двоеточия, включая двоеточие
Search
Строка запроса (после символа знака вопроса)
Target
Атрибут TARGET
Text
Строка контекста ярлыка <А>
X
Горизонтальное положение в пикселах по отношению к левому краю документа
Y
Вертикальное положение в пикселах по отношению к верхнему краю документа
Методы
Методы объекта Link приведены в табл. П4.36.
Таблица П4.36. Методы объекта Link
МетодОписание
HandleEventВызывает функцию обработки указанного события
Объект Location
Объект содержит информацию о текущем URL. Это заранее определенный объект, который является свойством объекта window. Он создается автоматически. Общая форма URL выглядит так:
protocol//host:port/pathname#hash?search
Например:
http://home.netscape.com/assist/extensions.html#topicl?x=7&y=2.
Название составных частей URL:
protocol — протокол, включает в себя двоеточие;
host — хост, имя сетевого хоста, интернет-домен или IP;
port — порт;
pathname — путь;
hash — внутренняя ссылка (только для HTTP);
search — строка запроса или запрос (только для HTTP).
Еще два свойства:
href — полный URL;
hostname — ИМЯ ХОСТа В форме host:port.
Типы используемых URL перечислены в табл. 04.37.
Таблица П4.37. Типы URL
Тип URL
Протокол
Пример
Ссылка на код JavaScript
Javascript:
Javascript:history.go(-1)
Ресурс навигатора
View-source :
View-source:Wysiwyg://0/ file:/с|/temp/genhtml.html
Информация навигатора
About:
About:cache
WWW
Http:
Http://home.netscape.com/
Файл
File: /
File:///javascript/methods.html
FTP
Ftp:
Ftp://ftp.mine.com/home/mine
Таблица П4.37 (окончание)
Тип URL
Протокол
Пример
Почта
Mailto:
mailto:info@netscape.com
Новости
News :
news://news.scruznet.com/ comp.lang.javascript
Гофер
Gopher:
Gopher.myhost.com
Свойства
Свойства объекта Location приведены в табл. П4.38.
Таблица П4.38. Свойства объекта Location
Свойство
Описание
Hash
Внутренняя ссылка URL
Host
Домен, IP, или сетевой хост
Hostname
Хост host:port
Href
Полный URL
Pathname
Путь (каталог)
Port
Порт
Protocol
Протокол
Search
Строка запроса
Методы
Методы объекта Location приведены в табл. П4.39.
Таблица П4.39. Методы объекта Location
Метод
Описание
Reload
Перезагрузка текущего документа
Replace
Загрузка нового документа
Объект Math ■
Это встроенный объект для работы с математическими константами и функциями. Это заранее определенный объект верхнего уровня, к его свойствам можно обращаться всегда, явное создание этого объекта не требуется. Все свойства и методы объекта являются статическими.
Свойства
Свойства объекта Math приведены в табл. П4.40.
Таблица П4.40. Свойства объекта Ma th
Свойство
Описание
Е
LN10
LN2
LOG10E
LOG2E
Число е, примерно 2.718
Натуральный логарифм 10, примерно 2.302
Натуральный логарифм 2, примерно 0.693
Десятичный логарифм от е, примерно 0.434
Двоичный логарифм от е, примерно 1.442
PI
SQRT1_2
SQRT2
Число "пи", примерно 3.14159
Обратная величина от квадратного корня из 2, примерно 0.707
Корень квадратный из 2, примерно 1,414
Методы
Методы объекта Math приведены в табл. П4.41.
Таблица П4.41. Методы объекта Ma th
Метод
Описание
Abs
Модуль
Acos
Asin
Функция Arccos ()
Функция Arcs in ()
Atan
Atan2
Ceil
Функция Arctan ()
Функция Arctan ()
Наименьшее большее целое
Cos
Функция Cos ()
Exp
Floor
Экспонента
Наибольшее меньшее целое
Log
Max
Min
Row
Random
Round
Sin
Натуральный логарифм
Большее из двух чисел
Меньшее из двух чисел
База экспоненты
Псевдослучайное число в промежутке от 0 до 1
Округление до целого
Функция sin().
Sqrt
Tan
Квадратный корень
Функция Tan ()
Предметный указатель
Active Object Map 431
Adapter activator 431
C
CGI-приложения 135
CORBA 395
E
Enterprise Java Bean 361
Etherealize 431
H
HTML-формы 60
HTML-фреймы 59
1
IDL Interface Definition Language (язык описания интерфейса, используемый в CORBA) 398
Incarnate 431
А
Активаторы Servant 444
Активные серверные страницы (ASP — Active Server Pages) 111
JavaScript:
наследование 91
управление временем 83
Р
РОА 420
РОА manager 432
Policy 432
Persistent object 432
R
RootPOA 432
S
SQL-запрос 157
Servant manager 432
T
Transient object 432
Апплет 193
взаимодействие 207
графические элементы 199
звук 216
потоки 221
сеть 224
ББазовый РОА 423ВВложенные таблицы 35дДокументы, создаваемые "на лету" 79Дочерний РОА 423ККомпоненты ASP 125ЛЛокатор Servant 447ООбъектная модель в языкеJavaScript 90Объекты JavaScript 85ББазовый РОА 423ВВложенные таблицы 35дДокументы, создаваемые "на лету" 79Дочерний РОА 423ККомпоненты ASP 125ЛЛокатор Servant 447ООбъектная модель в языкеJavaScript 90Объекты JavaScript 85П
Б
Базовый РОА 423
В
Вложенные таблицы 35
д
Документы, создаваемые "на лету" 79
Дочерний РОА 423
К
Компоненты ASP 125
Л
Локатор Servant 447
О
Объектная модель в языке
JavaScript 90
Объекты JavaScript 85
Б
Базовый РОА 423
В
Вложенные таблицы 35
д
Документы, создаваемые "на лету" 79
Дочерний РОА 423
К
Компоненты ASP 125
Л
Локатор Servant 447
О
Объектная модель в языке
JavaScript 90
Объекты JavaScript 85
Передача файла серверу 186
Протокол:
HTTP 13
TCP/IP 13
с
Сервлет 273
События JavaScript 69
Сокет 349
Структура апплета 196
Ф
Функции JavaScript 72
Функция cgiMain() 306
Я
Язык:
HTML 15, 24, 25, 27, 28, 30, 65
JavaScript 67
Ярлык HTML 22