Посещая в Internet различные Web-серверы, вы, наверно, заметили, что одни из них просто предоставляют некоторую информацию, а другие пытаются вступить с вами в диалог. Конечно, и статическая информация может быть очень интересна и полезна сама по себе. Однако ваш сервер будет намного привлекательнее для пользователей, если вы сделаете его активным. Активные серверы могут содержать счетчик посещений, книгу записей для гостей, в которой каждый желающий может оставить свои координаты, формы для обращения к базам данных, динамически изменяющиеся изображения, кнопки, списки и т. д.
Для централизованной обработки информации, которая поступает от клиентов, просматривающих содержимое страниц сервера с помощью Netscape Navigator и Microsoft Internet Explorer, можно воспользоваться расширениями серверов Web.
Мы предполагаем, что вы умеете создавать документы HTML. Неплохо, если в вашем распоряжении имеется Web-сервер, на котором вы можете экспериментировать.
Расширения CGI и ISAPI
Чаще всего активные серверы Web создаются с помощью программ CGI, использующих так называемый стандартный шлюзовой интерфейс, - Common Gateway Interface (CGI).
Что же представляет собой программа CGI? Вообще-то это обычное консольное приложение. Такая программа не ведет никакого диалога с пользователем, а работает со стандартными потоками ввода и вывода, а также с переменными среды (environment variables). Если вы когда-либо создавали консольные программы для операционных систем MS-DOS, OS/2 или Windows NT, то составление программ CGI вам вполне по плечу. Как правило, программа CGI анализирует содержимое некоторых переменных среды, получает данные от удаленного пользователя через стандартный поток ввода, а результат обработки этих данных записывает в стандартный поток вывода. Вот и все! Ну хорошо, почти все...
Каждый раз, когда удаленный пользователь обращается к расширению CGI, на сервере Web запускается программа, которая выполняется как отдельный процесс, причем в собственном адресном пространстве. На запуск процесса требуется время, и если ваш сервер пользуется популярностью, то программы CGI могут полностью его загрузить. В результате увеличится время реакции сервера, что может оттолкнуть от него пользователей.
Для повышения производительности в некоторых Web-серверах (в частности, Microsoft Internet Information Server) используется другой способ создания расширений. Расширение создается как библиотека динамической загрузки DLL с использованием программного интерфейса ISAPI (Internet Server API). Когда такое расширение активизируется в первый раз, оно загружается в адресное пространство процесса Web-сервера и начинает свою работу. В памяти всегда находится только одна копия соответствующей библиотеки DLL, поэтому при одновременном обращении к расширению ISAPI нескольких пользователей системные ресурсы расходуются более экономно, а кроме того, не тратится время на дополнительные загрузки расширения.
Программирование приложений ISAPI представляет собой более сложную задачу, нежели создание программ CGI. Поскольку такие приложения всегда работают в мультизадачном режиме, необходимо обеспечить синхронизацию доступа к критичным ресурсам. Ошибки в приложениях ISAPI могут привести к аварийной остановке сервера Web, а вот при использовании программ CGI это маловероятно. Поэтому, несмотря на то что расширения ISAPI в целом более эффективны по сравнению с программами CGI, первые эксперименты по созданию активных серверов следует начинать именно с программ CGI.
Пишем первую программу CGI
Наша первая программа CGI не принимает данные от пользователя. Она запускается, если пользователь щелкает левой кнопкой мыши по соответствующей ссылке в документе HTML, и возвращает ему новый документ HTML, созданный динамически.
Для ссылки на программу CGI мы использовали оператор , как это показано в листинге 1.
Что произойдет, если щелкнуть на ссылке, расположенной в этом документе?
Сервер с адресом http://frolov начнет поиск программы cgi1.exe и в случае успеха запустит ее. Перед запуском будет сформирован набор переменных среды, с помощью которых программа CGI может получить различную информацию, включающую, в том числе, строку параметров, указанную в операторе .
Сделаем небольшое замечание относительно каталога Scripts. Администратор Web- сервера таким образом настраивает права доступа к каталогам, содержащим документы HTML и другие файлы данных, чтобы удаленные пользователи могли только читать эти файлы. Запись в каталоги и запуск из них программ запрещены из соображений безопасности. Для расширений CGI и ISAPI администратор создает отдельный каталог, разрешая в нем только запуск программ без чтения и записи. Кроме того, каталогу с программными расширениями присваивается так называемое имя виртуального каталога (псевдоним), не имеющее никакой связи с именем физического каталога. Имя виртуального каталога вы можете узнать у администратора сервера. Если же вы сами выполняете функции администратора, то можете создать виртуальный каталог с любым именем, отобразив его на любой физический каталог. О том, как это сделать, вы можете узнать из документации к тому Web-серверу, с которым вы работаете.
Вернемся к нашей программе cgi1.c. Исходный текст этой программы вы найдете в листинге 2.
По своей сложности cgi1.c совсем недалеко ушла от знаменитой программы "Hello, World!". Ее задачей является динамическое формирование документа HTML и отправка его в стандартный поток вывода с помощью функции printf.
При первом вызове функции printf в стандартный поток вывода записывается заголовок протокола HTTP, из которого видно, что далее последует текстовый документ HTML:
printf ("Content-type: text/html ");
Заголовок протокола HTTP всегда отделяется от данных пустой строкой, поэтому в конце приведенной выше строки находятся два символа " ".
Вслед за заголовком программа cgi1 выводит строки документа HTML.
Необязательный оператор определяет тип документа и версию языка HTML. Далее в стандартный поток выводятся операторы ,
и. Для тех, кто когда-либо создавал документы HTML, здесь нет ничего необычного.
На динамически формируемой странице программа cgi1 отображает содержимое четырех переменных среды с именами REQUEST_METHOD, QUERY_STRING, CONTENT_LENGTH и CONTENT_ TYPE. Указатели на соответствующие текстовые строки записываются с помощью функции getenv.
Перед завершением своей работы программа cgi1 записывает в стандартный поток вывода операторы и , закрывающие документ HTML.
Переменные среды для программ CGI
Запуская программу CGI, сервер Web формирует для нее набор переменных среды, которые передают информацию, полученную от пользователя, строку параметров запуска программы CGI из документа HTML, а также некоторые параметры самого сервера Web.
Перечислим основные переменные среды программы CGI и приведем их краткое описание. Учтите, что набор доступных программе CGI переменных среды зависит от конкретной реализации сервера Web, однако самые важные переменные, такие как REQUEST_ METHOD, QUERY_ STRING, CONTENT_LENGTH и CONTENT_ TYPE, доступны всегда.
REQUEST_METHOD - информация о методе доступа при передаче данных от браузера Web-серверу. Чаще всего используются два метода: GET и POST. В нашем примере применен метод GET, хотя мы нигде это специально не указывали.
Метод GET обеспечивает получение данных от браузера с помощью переменной среды с именем QUERY_STRING. Значение этой переменной равно param1. Это значение соответствует строке параметров, передаваемой программе cgi1.exe в документе HTML, исходный текст которого приведен в листинге 1.
Метод передачи данных GET прост в использовании, однако он подходит только для передачи относительно коротких текстовых строк. Причина этого лежит в ограничении, которое накладывается операционной системой на размер строки переменной среды. Если необходимо передать текстовые данные большого объема (например, содержимое полей диалоговых панелей), более предпочтителен метод POST: тогда программа GCI получает данные от браузера, выполняя чтение из стандартного потока ввода. Для ввода можно вызывать обычные функции стандартной библиотеки Си, например fread.
Если данные передаются методом POST (о чем программа CGI может узнать, анализируя переменную среды REQUEST_METHOD), то объем передаваемых данных записывается в переменную среды с именем CONTENT_LENGTH. Заметим, при использовании метода GET содержимое переменной среды CONTENT_LENGTH анализировать не нужно.
QUERY_STRING - данные, которые передаются программе CGI в случае применения метода GET. Если в документе HTML после символа "?" указана строка параметров, то именно она записывается в эту переменную среды.
CONTENT_LENGTH - эта переменная среды используется в случае применения метода передачи данных POST и содержит количество байт данных, которые программа CGI должна получить от браузера.
CONTENT_TYPE - при использовании метода передачи POST в этой переменной хранится строка с названием типа данных, присланных браузером. Если браузер присылает текстовые данные (как это бывает в большинстве случаев), тип данных может быть application/x-www-form-urlencoded. Однако возможно применение и других типов данных, например multipart/form-data. В этом случае от браузера могут быть приняты как текстовые, так и двоичные файлы*.
AUTH_TYPE - технология WWW допускает защиту страниц HTML, когда доступ к отдельным страницам предоставляется только при предъявлении пароля. Переменная среды AUTH_TYPE содержит тип идентификации, который применяется сервером. Например, для сервера WWW на базе Microsoft Information Server при включении аутентификации в этой переменной будет храниться строка NTLM.
GATEWAY_INTERFACE - в этой переменной находится версия интерфейса CGI, с которой работает Web-сервер.
HTTP_ACCEPT - в этой переменной перечислены типы данных MIME, которые могут быть приняты браузером от Web-сервера.
HTTP_REFER - в переменную HTTP_REFER записывается адрес URL документа HTML, который инициировал работу программы CGI.
HTTP_ACCEPT_LANGUAGE - переменная HTTP_ACCEPT_LANGUAGE содержит идентификатор предпочтительного национального языка для получения ответа от Web-сервера. Сервер Web, однако, может прислать ответ на другом национальном языке.
HTTP_UA_PIXELS - разрешение видеоадаптера, установленное в компьютере пользователя. Анализируя содержимое этой переменной, а также содержимое переменной HTTP_UA_COLOR, описанной ниже, программа CGI может динамически создать документ HTML такого формата, который будет наилучшим образом отображаться на экране компьютера удаленного пользователя.
HTTP_UA_COLOR - допустимое количество цветов в системе пользователя.
HTTP_UA_OS - операционная система, под управлением которой работает браузер.
HTTP_UA_CPU - тип центрального процессора в компьютере удаленного пользователя.
HTTP_USER_AGENT - имя браузера, с помощью которого пользователь работает с сервером Web. Анализируя это имя, программа CGI может принимать решение об использовании тех или иных расширений стандарта языка HTML, допустимых для конкретного браузера.
HTTP_HOST - имя узла, на котором работает Web-сервер.
PATH_INFO - путь к виртуальному каталогу, в котором находится программа CGI.
PATH_TRANSLATED - физический путь к программе CGI.
REMOTE_ADDR - адрес узла IP, на котором работает браузер удаленного пользователя.
REMOTE_HOST - доменное имя узла, на котором работает браузер удаленного пользователя. Если эта информация недоступна (например, для узла не определен доменный адрес), вместо доменного имени указывается адрес IP, как в переменной REMOTE_ADDR.
REMOTE_USER - имя пользователя, которое используется браузером для аутентификации.
SCRIPT_NAME - в эту переменную записывается путь к виртуальному каталогу и имя программы CGI. Анализируя эту переменную, программа CGI может определить путь к своему загрузочному файлу.
SERVER_NAME - доменное имя Web-сервера или адрес IP сервера, если доменное имя недоступно или не определено.
SERVER_PROTOCOL - имя и версия протокола, который применяется для выполнения запроса к программе CGI.
SERVER_PORT - номер порта, на котором браузер посылает запросы Web-серверу.
SERVER_SOFTWARE - название и версия программного обеспечения Web-сервера. Версия следует после названия и отделяется символом "/".
Книга гостей
Следующая наша CGI-программа несколько сложнее и к тому же может быть использована на практике. Она выполняет функции электронной книги гостей, собирая отзывы посетителей и записывая их в файл на сервере Web. Отзывы доступны для всеобщего обозрения.
Для записи отзыва пользователь должен заполнить форму.
Форма содержит четыре поля редактирования текста, три из которых однострочные, а одно - многострочное. Однострочные поля предназначены для записи электронного адреса E-mail, имени и места проживания пользователя, пожелавшего оставить запись в книге гостей. Многострочное поле служит для записи отзыва. В нижней части страницы есть две кнопки с названиями Store и Clear Form. С помощью первой из них вы можете отправить свой отзыв на сервер, а с помощью второй - очистить содержимое полей формы.
Исходный текст документа HTML, содержащего только что описанную форму, приведен в листинге 3.
Форма описана между операторами
. Рассмотрим самые основные операторы языка HTML, с помощью которых определяются формы. Прежде всего обратите внимание на параметры оператора