Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Стрельников О.И. Основы web-технологий.doc
Скачиваний:
100
Добавлен:
02.05.2014
Размер:
648.7 Кб
Скачать

2. 3. Технология Dynamic html

Для создания интерактивных документов в язык HTML были введены события. С точки зрения пользователя, события – это действия, совершаемые над активными элементами документа HTML при помощи устройств ввода. С точки зрения языка HTML, события – это специальные атрибуты элементов, в которых указываются действия, выполняемые при попытке пользователя воздействовать на данный элемент. Такая технология получила название Dynamic HTML. В качестве действия, выполняемого в случае наступления события, можно указывать программы (последовательности операторов) JavaScript. В табл. 8 перечислены основные события Dynamic HTML.

Таблица 8

События Dynamic HTML

Атрибут

Элемент

Событие

onfocus

A, AREA, BUTTON, INPUT, LABEL, SELECT, TEXTAREA

Попадание в фокус

onblur

Потеря фокуса

onchange

INPUT, SELECT, TEXTAREA

Изменение

onselect

INPUT, TEXTAREA

Выбор элемента списка

Окончание табл. 8

Атрибут

Элемент

Событие

onclick

Кроме APPLET, BASE, BASEFONT, BDO, BR, FONT, FRAME, FRAMESET, HEAD, HTML, IFRAME, ISINDEX, META, PARAM, SCRIPT, STYLE, TITLE

Щелчок

ondblclick

Двойной щелчок

onkeydown

Клавиша нажата

onkeypress

Клавиша нажата и отпущена

onkeyup

Клавиша отпущена

onmousedown

Кнопка мыши нажата

onmousemove

Мышь перемещена

onmouseout

Курсор мыши покинул область элемента

onmouseover

Курсор мыши перемещен в область элемента

onmouseup

Кнопка мыши отпущена

onload

BODY, FRAMESET

Документ загружен

onunload

Документ выгружен

onreset

FORM

Форма сброшена

onsubmit

Форма отправляется

3. Технологии стороны сервера

3. 1. Общий интерфейс шлюзов cgi

Серверы Web обеспечивают просмотр пользователем документов и переход с одного документа на другой. Часто такого взаимодействия пользователя с сервером Web бывает недостаточно. Во многих случаях пользователь должен получать для просмотра не статические документы, хранящиеся на сервере Web, а динамические, содержимое которых изменяется в соответствии с работающей на сервере Web программой. Для реализации подобной возможности необходимо выполнение, по крайней мере, двух условий. Во-первых, сервер Web должен уметь инициировать запуск на выполнение программ в соответствии с запросом пользователя. Во-вторых, необходима возможность передачи данных от пользователя удаленной программе, а также результатов работы программы – пользовательскому агенту. Для выполнения этих условий необходим программный интерфейс между сервером Web и запускаемым приложением. При создании Web был разработан такой интерфейс, получивший название общего интерфейса шлюзов (Common Gateway Interface, CGI).

Технология CGI относится к технологиям стороны сервера. Это означает, что программа CGI запускается на сервере Web и работает в его локальной операционной системе. Взаимодействие пользовательского агента с удаленной программой осуществляется по следующей общей схеме (рис. 2):

  1. Пользовательский агент соединяется с сервером Web, на котором расположена программа, и передает ему запрос, содержащий идентификатор программы и данные для обработки. Идентификатор передается в стартовой строке запроса. Место расположения данных для обработки в запросе зависит от метода, применяемого к запрашиваемой программе.

  2. Сервер Web получает запрос пользователя, запускает программу, идентификатор которой содержится в стартовой строке полученного запроса, передает ей по интерфейсу CGI данные для обработки и обеспечивает возможность получения результатов работы программыCGI.

  3. Программа обрабатывает полученные от сервера Web данные, формирует документ, содержимое которого является результатом обработки полученных данных, и отправляет сформированный документ серверу Web.

  4. Сервер Web формирует сообщение ответа HTTP с результатом работы программы в качестве объекта, и передает его пользовательскому агенту.

Данные для обработки могут быть содержимым формы, заполненной пользователем. Форма – это часть документа HTML, содержащая органы управления, информация о состоянии которых может быть передана пользователем серверу Web. Для размещения формы внутри документа HTML используется элемент FORM:

<FORM action=uri method=m enctype=mime>...</FORM>

Обязательны как начальный, так и конечный тэги. Атрибут action задает идентификатор программы, которой будут отправлены данные формы для обработки. Чаще всего это программа CGI, однако, можно указать идентификатор обычного пассивного документа. В последнем случае обработки формы не произойдет, но будет осуществлен переход к новому документу.

Атрибут method задает метод, применяемый к ресурсу. Может принимать значения GET и POST. Атрибут enctype задает способ кодирования содержимого формы (значений в строках ввода, состояний переключателей). Если данные из формы будут переданы серверу Web в теле сообщения запроса, то способ кодирования означает тип содержимого и передается в заголовке объекта Content-Type. По умолчанию применяется единственный возможный для метода GET способ кодирования application/x-www-form-urlencoded. Для метода POST применим также способ text/plain.

Внутри формы, помимо других элементов, могут находиться элементы органов управления. Элементы органов управления могут располагаться и вне элементов FORM. В этом случае данные из органов управления для обработки передаются отображаемому в настоящий момент документу.

Отправка формы может осуществляться при нажатии кнопки класса submit, при нажатии клавиши ENTER в строке ввода, при нажатии мышью внутри органа управления класса image. При отправке формы клиент производит следующие действия:

  1. Кодирование содержимого элементов. У каждого органа управления (элемента) формы имеются атрибуты name и value, обозначающие соответственно имя элемента и значение. Имя задается в документе HTML. Значение зависит от типа элемента. Например, для строки ввода – это введенная строка, для включенного одиночного переключателя – on, для группы переключателей – имя включенного. Кодирование заключается в замене некоторых недопустимых символов последовательностями допустимых. Пробелы в значениях кодируются символом '+'. Символы с кодом больше или равным 127, а также некоторые символы с кодом меньше 127, например, '+', '%' и '&', кодируются тройкой символов '%hh', где hh – две шестнадцатеричные цифры кода символа. Код символа зависит от кодировки, в которой создан содержащий форму документ. Таким образом, для каждого элемента получается строка вида name=value, где name – имя элемента органа управления, value – строка с закодированным значением элемента органа управления.

  2. Кодирование содержимого формы в соответствии с атрибутом enctype элемента FORM. В случае способа кодирования application/x-www-form-urlencoded полученные строки для каждого элемента соединяются друг с другом символом '&':

name1=value1&name2=value2&...&nameN=valueN

В случае способа кодирования text/plain строки разделяются символами перевода строки и возврата каретки:

name1=value1

name2=value2

...

nameN=valueN

  1. Формирование HTTP-сообщения запроса. В случае метода GET кодированное содержимое формы присоединяется к идентификатору запрашиваемого ресурса (программы CGI) в начальной строке запроса при помощи символа '?':

URI?name1=value1&name2=value2&...&nameN=valueN

В случае метода POST кодированное содержимое формы помещается в тело сообщения. В сообщение запроса включается заголовок Content-Type, в котором содержится способ кодирования содержимого, и заголовок Content-Length, указывающий на длину кодированного содержимого.

  1. Отправка сообщения серверу.

При получении сообщения запроса от клиента сервер выполняет следующие действия:

  1. По идентификатору определяет, что запрашиваемый ресурс является программой.

  2. Выделяет блок памяти для переменных окружения создаваемого процесса. В выделенный блок копируются переменные окружения процесса сервера Web.

  3. Создает переменные окружения с информацией о протоколе HTTP, сервере Web и интерфейсе CGI и добавляет в выделенный блок переменных окружения. В табл. 9 приведены основные переменные окружения CGI.

  4. Запрашиваемый метод из полученного сообщения присоединяется в виде значения к переменной окружения REQUEST_METHOD, после чего созданная переменная добавляется в выделенный блок переменных окружения.

  5. Часть заголовков из полученного сообщения запроса преобразуется в соответствующие переменные окружения и добавляется в созданный блок переменных окружения.

Таблица 9

Основные переменные окружения CGI

Переменная

Значение

SERVER_SOFTWARE

Значение заголовка Server

SERVER_NAME

Имя хоста, на котором работает сервер Web

CONTENT_LENGTH

Значение заголовка Content-Length

CONTENT_TYPE

Значение заголовка Content-Type

SERVER_PROTOCOL

Версия протокола HTTP сервера

SERVER_PORT

Номер порта, на котором работает сервер

REQUEST_METHOD

Метод из стартовой строки сообщения запроса

PATH_TRANSLATED

Путь к корневому каталогу сервера Web в локальной файловой системе сервера

SCRIPT_NAME

URI программы CGI относительно сервера Web

QUERY_STRING

Кодированное содержимое формы из стартовой строки сообщения запроса

REMOTE_HOST

Имя хоста клиента

REMOTE_ADDR

Адрес хоста клиента

HTTP_ACCEPT

Значение заголовка Accept

HTTP_USER_AGENT

Значение заголовка User-Agent

  1. Если метод в стартовой строке сообщения запроса является методом GET, то от идентификатора запрашиваемого ресурса отделяется строка с кодированным содержимым формы (после символа '?'), которая рассматривается как значение переменной окружения QUERY_STRING, после чего сформированная переменная добавляется в созданный блок переменных окружения.

  2. Создает дочерний процесс из загрузочного модуля программы CGI, идентификатор которой передан в стартовой строке сообщения запроса, причем блоком окружения созданного процесса становится созданный сервером блок.

  3. Если метод в стартовой строке сообщения запроса является методом POST, то в стандартный поток ввода (дескриптор 0) созданного процесса передается тело сообщения запроса.

  4. При помощи операции замены дескриптора дескриптор стандартного потока вывода (дескриптор 1) созданного процесса заменяется дескриптором канала (или другого коммуникационного объекта), связанного с процессом сервера Web.

  5. Читает передаваемые программой CGI данные, формирует из них сообщение HTTP ответа и отправляет его пользовательскому агенту.

Если какие-либо из действий выполнить не удалось, то пользовательскому агенту отправляется строка с ошибочным кодом состояния и созданный процесс уничтожается.

Все современные операционные системы содержат в своем API средства для запуска дочернего процесса с данной средой окружения. В DOS – функция 4B00h прерывания 21h, в UNIX – системный вызов execve, в WIN32 – функция API CreateProcess. В любом случае, прикладная программа может получить доступ к среде окружения. Языки высокого уровня унифицируют интерфейс доступа к среде окружения для различных ОС. Например, в языках C и C++ имеются следующие переменные и функции:

#include <stdlib.h>

extern char **environ;

#include <stdlib.h>

char *getenv(char *varname);

Указатель на массив строк environ может быть использован для доступа ко всей среде окружения процесса. В массиве содержатся переменные окружения в формате "name=value", где name – имя переменной окружения, value – ее значение. Последний элемент массива содержит пустую строку в качестве признака окончания среды процесса.

Функция getenv позволяет получить значение переменной окружения, имя которой передано в качестве параметра varname. Если переменная с данным именем отсутствует, функция возвращает 0.

Если программой CGI обрабатывается запрос, содержащий метод POST, то тело сообщения запроса, в котором находится кодированное содержимое отправленной клиентом формы, можно получить из стандартного потока ввода. С каждым процессом связан стандартный поток ввода. Чтение из этого потока стандартно означает чтение с клавиатуры. При помощи операций с дескрипторами можно поместить блок данных в стандартный поток ввода. Читать из стандартного потока ввода в языке C удобнее всего при помощи функции чтения потока:

#include <stdio.h>

int fread(void *buffer, size_t size, size_t count, FILE *stream);

В параметре buffer передается адрес буфера, куда будут помещены прочитанные данные. В параметрах size и count указывается длина читаемого блока. Поскольку пользовательский агент передает длину тела сообщения в байтах, то в параметре size указывается 1, а в параметре count – длина тела сообщения запроса. В качестве параметра stream следует передать константу stdin для указания, что считывание производится из стандартного потока ввода. Функция fread возвращает количество фактически прочитанных символов.

Чтение из стандартного потока ввода является блокирующим, поэтому следует заранее определить число читаемых символов. Клиент вместе с другими заголовками передает заголовок Content-Length, в котором сообщается длина тела сообщения. Сервер при формировании среды окружения создает переменную CONTENT_LENGTH, значение которой совпадает со значением соответствующего заголовка. Поэтому чтением данной переменной можно определить число символов в стандартном потоке ввода.

Помимо стандартного потока ввода, с каждым процессом связан стандартный поток вывода. Для обычных процессов стандартный поток вывода, как правило, связан с экраном. При помощи операций замены дескриптора можно переключить стандартный поток вывода на любой открытый дескриптор. Сервер Web осуществляет переключение стандартного потока вывода на дескриптор канала или другого коммуникационного объекта. В результате такого перенаправления вся выводимая программой CGI в стандартный поток вывода информация будет передаваться серверу Web.

Формат данных, передаваемых от приложения CGI серверу Web, совместим с форматом сообщений протокола HTTP. Эти данные должны содержать заголовки, пустую строку и тело сообщения. Заголовки делятся на заголовки CGI и заголовки HTTP. Существует 3 заголовка CGI:

  1. Content-Type – тип содержимого передаваемого тела сообщения. Значение соответствует заголовку Content-Type протокола HTTP.

  2. Location – идентификатор, в котором содержится запрашиваемый ресурс. Значение соответствует заголовку Location протокола HTTP. При получении данного заголовка сервер Web передает пользовательскому агенту ответ с кодом перенаправления.

  3. Status – строка состояния. Значением данного заголовка является трехзначный код состояния и поясняющая фраза, которые сервер Web должен передать пользовательскому агенту.

Все остальные заголовки считаются сервером Web заголовками HTTP и передаются пользовательскому агенту без изменения, также как и тело сообщения. Можно считать, что данные передаются от программы CGI непосредственно клиенту Web.

Выводить в стандартный поток вывода можно при помощи функции printf():

#include <stdio.h>

int printf(char *format, ...);

При обмене двоичными данными между приложением CGI и сервером Web, например, при отправке графического изображения, сформированного приложением CGI в процессе своей работы, следует учитывать некоторые особенности. Потоки могут находиться в двух режимах: двоичном и текстовом. В двоичном режиме данные передаются в том виде, в котором они представляются при хранении этих данных в памяти. В текстовом режиме некоторые символы могут приводить к определенным эффектам. Например, при записи символа конца файла происходит закрытие текстового потока, а при записи символа перевода строки в текстовый поток записываются два символа: перевода строки и возврата каретки. Аналогично, при чтении двух символов из потока, содержащего подряд символы перевода строки и возврата каретки, будет считан только один символ перевода строки. Поскольку стандартные потоки, как правило, открываются в текстовом режиме, перед передачей двоичных данных следует перевести эти потоки в двоичный режим. Для перевода потока в двоичный режим следует сначала получить его дескриптор. Это можно сделать, вызвав функцию fileno() стандартной библиотеки:

#include <stdio.h>

int fileno(FILE *stream);

Единственным параметром данной функции является указатель на поток. При получении дескриптора стандартного потока вывода в качестве значения параметра следует указать константу stdout, а при получении дескриптора стандартного потока ввода – stdin. Полученное значение дескриптора теперь можно использовать при вызове функции setmode() для перевода потока в двоичный режим:

#include <io.h>

#include <fcntl.h>

int setmode(int handle, int mode);

Первым параметром данной функции является дескриптор открытого потока. Вторым параметром является режим, в который будет переведен поток, задаваемый одной из констант: O_TEXT при переводе потока в текстовый режим или O_BINARY при переводе потока в двоичный режим. Функция возвращает ранее установленный режим для данного потока или –1 в случае ошибки.

Для записи в поток, находящийся в двоичном режиме, удобно использовать функцию fwrite():

#include <stdio.h>

int fwrite(void *buffer, size_t size, size_t count, FILE *stream);

В параметре buffer передается адрес буфера, откуда будут взяты записываемые в поток данные. В параметрах size и count указывается длина читаемого блока. Поскольку приложение CGI передает длину тела сообщения в байтах, то в параметре size указывается 1, а в параметре count – длина передаваемого блока данных. В качестве параметра stream следует передать константу stdout, для указания того, что запись производится в стандартный поток вывода. Функция fwrite() возвращает количество фактически записанных символов.

Функцию printf() неудобно использовать при передаче двоичных данных, поскольку в передаваемом блоке могут оказаться нули.

Стандартный поток ввода практически всегда нужно переводить в двоичный режим, поскольку, если передаваемые от пользовательского агента данные являются многострочными, то есть содержат символы перевода строки и возврата каретки, то значение переменной окружения CONTENT_LENGTH не будет соответствовать фактическому числу символов, прочитанному из стандартного потока ввода в текстовом режиме.

Программа CGI должна выполнить следующие действия:

  1. Прочитать значение заголовка REQUEST_METHOD для определения запрашиваемого метода.

  2. Если запрашиваемый метод – GET, то прочитать переменную окружения QUERY_STRING и считать полученное значение кодированным содержимым формы. Способ кодирования считать равным application/x-www-url-encoded.

  3. Если запрашиваемый метод – POST, то прочитать длину тела сообщения запроса из переменной окружения CONTENT_LENGTH. Из стандартного потока ввода прочитать тело сообщения запроса и считать его кодированным содержимым формы. Способ кодирования прочитать из переменной окружения CONTENT_TYPE.

  4. Разобрать кодированное содержимое формы в зависимости от способа кодирования.

  5. Прочитать необходимые программе CGI переменные окружения.

  6. Выполнить все необходимые в программе действия и сформировать документ с результатом работы программы.

  7. Отправить в стандартный поток вывода все необходимые заголовки CGI и HTTP и пустую строку.

  8. Отправить в стандартный поток вывода сформированный документ.