Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Хомоненко А.Д., Цыганков В.М., Мальцев М.Г. - Базы данных. Учебник для высших учебных заведений (6-е изд.) - 2009

.pdf
Скачиваний:
4972
Добавлен:
14.05.2016
Размер:
14.64 Mб
Скачать

16. Интерфейсы программирования Web-приложения

623

C:\WebShare\wwwroot\ — каталог где находится CGI-модуль; my_cgi.exe —

имя файла, содержащего модуль.

Пример 2. Для Web-сервера Apache/1.3.14 (содержащего модуль CGI в папке cgi-bin сервера igin) следующие переменные окружения могут иметь значения, отличные от приведенных ранее:

SERVfER_SOFTWARE = Apache/1.3.14 (Win32)

REMOTEHOST = (null)

HTTP_HOST = igin

PATH_TRANSLATED = d:\program\apache\htdocs\

SCRIPT_NAME = /cgi-bin/my_cgi.exe

Пример 3. Для Web-сервера Microsoft-IIS/5.0 в среде Windows 2000 Server (содержащего модуль CGI в папке scripts) следующие переменные окружения могут иметь значения, отличные от приведенных выше:

SERVER_SOFTWARE = Microsoft-IIS/5.0

SERVERNAME = igin

GATEWAYJNTERFACE = CGI/1.1

SERVERPROTOCOL = HTTP/1.1

PATH_TRANSLATED = c:\inetpub\wwwroot

SCRIPT_NAME = /Scripts/my_cgi.exe

REMOTE_HOST= 127.0.0.1

REMOTE_ADDR= 127.0.0.1

Для вывода значения этих переменных может использоваться следующий код на языке С++:

#include <stdio.h> #include <stdlib.h> #define N 31

main(int argc, char *argv[])

{

char *par[]={"SERVER_SOFTWARE", "S ERVER_NAM E",

"HTTP_AUTHORIZATION" };

for(x=0;x<N;x++)

printf("%s = %s<Br>",par[x],getenv(par[x]));

}

В приведенном коде вместо "..." нужно подставить названия требуемых переменных окружения.

624

Часть 4. Публикация баз данных в Интернете

Стандартный

вывод

После перекодировки входных данных в CGI-модуле необходимо сформировать HTML-документ в стандартном устройстве вывода. Причем, HTML-документы могут создаваться динамически с использованием информации из БД. При этом HTML-страница формируется на основании информации, хранимой в БД, которая может обновляться в реальном масштабе времени.

Например, следующий фрагмент кода на С++ позволяет выводить в стандартный поток вывода stdout простейший HTML-доку мент:

prlntf("Content-type: text/html<BR>");

printf( <HTML><HEAD> <TITLE> Простейший HTML-документ </TITLEX/HEAD>");

printf("<BODY ");

printf("<H1 >Результаты обработки входных данных формы</Н1 >");

При этом первая строка "Content-type: text/html" есть директива CGI-ин- терфейса, которая определяет MIME-тип возвращаемого документа (в нашем случае — документ в формате HTML). В следующем разделе рассмотрен пример, демонстрирующий возможности интерфейса CGI по динамическому формированию НТМ L-документа.

Пример CGI-модуля на Visual С++

Рассмотрим пример CGI-модуля, позволяющий перекодировать передаваемые данные при использовании метода GET и POST.

Для получения данных, относящихся к требуемому значению параметра из текстовой строки, содержащейся в переменной окружения QUERY_STRING или в стандартном потоке ввода, может использоваться следующий код на С++:

#include <stdio.h> #include <stdlib.h> #include <string.h> #pragma hdrstop

//

//

#define MAX_ARRAY 40

#define MAX_LENGTH_BUFFER 10000

//Структура, используемая для хранения передаваемых параметров typedef struct {

char name[50]; char value[ 100]; } param;

16. Интерфейсы программирования Web-приложения

625

main(int argc, char *argv[])

{

param arr[MAX_ARRAY]; char *def;

int m=0; intx,y=0;

printf("Content-type: text/html%c%c",10,10); //Следующий код используется для определения метода //передачи данных и для считывания данных в буфер if(strcmp(getenv(" REQU EST_M ETHOD")," POST"))

//функция getenv возвращает значение переменной окружения,

//название которой задано в качестве аргумента

{

if(strcmp(getenv("REQUEST_METHOD"),"GET"))

{

printf("Внутренняя ошибка с кодом 1"); exit( 1);}

printf("Используется метод GET<BR>");

//Считываем передаваемые данные в буфер def из

//переменной окружения QUERY_STRING def=getenv( "QU ERY_STRI NG");

}

else{

printf("Используется метод POST<BR>"); int leng = atoi(getenv("CONTENT_LENGTH"));

// Считаем передаваемые данные в буфер def из

//стандартного потока ввода STDIN

def = (char *) malloc(MAX_LENGTH_BUFFER);

fread(def, leng, 1, stdin);

}

int len=strlen(def);

if (len==0)

{

printf(„Внутренняя ошибка с кодом 4");

exit(1);

}

//Промежуточный буфер word используется при декодировании данных char *word = (char *) malloc(MAX_LENGTH_BUFFER);

//Цикл для декодирования данных

for(x=0;x<len;x++,y++)

{

if(def[x] == '%') {

626

Часть 4. Публикация баз данных в Интернете

register char d;

//Код для декодирования шестнадцатеричного кода символов d=(def[x+1] >= 'А' ? ((def[x+1] & Oxdf) - 'А')+10 : (def[x+1] - 'О')); d*=16;

d+=(def[x+2] >= 'А' ? ((def[x+2] & Oxdf) - 'A')+10 : (def[x+2]- '0')); x+=2;

word[y]=d;

continue;} else

//Замена символа '+' на пробел if(def[x] == '+•) {word[у] = ' ' continue;} else

if(def[x] == '=') { word[y]='\0*;

У = - 1 ;

//формирование структуры для хранения передаваемых параметров strcpy(arr[m]. name,word);

continue;} else

if(def[x] =='&'){ word[y]='\0';

//формирование структуры для хранения передаваемых параметров strcpy(arr[m].value,word);

m++;

У = - 1 ; continue;} else

word[y]=def[x];

}

word[y]='\0';

//формирование структуры для хранения передаваемых параметров strcpy(arr[m].value,word);

m++;

printf("Значения передаваемых параметров:");

for(x=0; х < m; х++)

{

//вывод передаваемых параметров

}printf("<li>%s = %s</li>",arr[x].name, arr[x].value);

return 0;

}

16. Интерфейсы программирования Web-приложения

627

Вприведенном примере используется функция getenv(), которая возвращает значения соответствующей переменной окружения.

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

def=getenv("QUERY_STRING");

В случае использования метода PUT в коде применяется функция fread():

def = (char *) malloc(MAX_LENGTH_BUFFER); int leng = atoi(getenv("CONTENT_LENGTH")); fread(def, leng, 1, stdin);

Отметим, что при использовании метода POST CGI-модуль получает данные из формы через стандартный поток ввода stdin, в котором данные находятся в том же формате, что и в случае метода GET.

Использование метода POST предпочтительно по сравнению с методом GET для передачи больших по размерам данных. Учитывая, что операционные системы, как правило, накладывают ограничения на размер данных, передаваемых через переменную окружения QUERY_STRING, метод GET обычно применяют для обработки данных, передаваемых через URL, или данных форм, имеющих небольшое число интерфейсных элементов.

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

int leng = atoi(getenv("CONTENT_LENGTH"));

Здесь переменная окружения с именем CONTENT_LENGTH содержит длину буфера данных, находящихся в потоке stdin.

Строка

def = (char *) malloc(MAX_LENGTH_BUFFER);

динамически выделяет MAX_LENGTH_BUFFER байтов под буфер для хранения передаваемых данных.

Для вызова приведенного CGI-модуля нужно откомпилировать код модуля в системе программирования VisualC++6.0 или C++BUILDER5.0 под именем my_cgi.exe и поместить его в каталог C:\WebShare\Scripts\ в случае за-

пуска в среде Windows9X под управлением Personal Web Server. В случае запуска в среде Windows2000 под управлением Microsoft Internet Information Server в код модуля нужно поместить в каталог c:\inetpub\scripts\ и в случае запуска в любой среде под управлением сервера Apache — поместить в каталог d:\program\apache\cgi-bin\ (каталог d:\program\apache\ — это каталог, в который установлен сервер Apache).

628

Часть 4. Публикация баз данных в Интернете

При запуске CGI-модуля из HTML-документа в случае серверов PSW и MIIS может использоваться следующий URL — http://localhost/scripts/my_cgi.exe, а в случае сервера APACHE — http://localhost/cgi-bin/my_cgi.exe.

Кроме того, для вызова CGI-модуля необходим НТМ L-документ. Например, если загрузить приведенную выше форму в окне обозревателя и выбрать следующую ссылку

Загрузить CGI-модуль по запросу http://localhost/Scripts/my_cgi.exe?TEST=modul

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

Используется метод GET

Значения передаваемых параметров:

TEST = modul

При нажатии на кнопку Send будет выведена следующая информация:

Используется метод POST

Значения передаваемых параметров:

NAME = Myjogin

TYPE = Registry

Submit = Send

Перейдем к рассмотрению технологий публикации БД из CGI-модуля на НТМ L-документ.

Публикация БД с использованием ODBC

Для публикации БД из CGI-модуля на HTML-документ могут применяться различные интерфейсы доступа к БД — ODBC, ADO и др. В этом разделе рассмотрим основные особенности использования в CGI-модуле традиционного интерфейса ODBC и в следующем разделе — перспективного интерфейса ADO.

Интерфейс ODBC может использоваться при создании Web-приложений для связи модулей расширений Web-cepeepa (CGI, WinCGI и ISAPI) с базами данных и при применении стандартных средств, входящих в состав Webсерверов, таких как ASP и IDC/HTX-страницы. На стороне обозревателя могут также организовываться обращения к интерфейсу ODBC из объектов ActiveX и Java-апплетов.

ODBC' представляет собой программный интерфейс, разработанный фирмой Microsoft для доступа к реляционным БД. Он организован в виде библиотеки функций, используемых для доступа к базам данных на языке SQL.

Этот интерфейс не является объектным и поэтому, например в серверных

страницах ASP, получить доступ к источникам данных с использованием ODBC можно только через интерфейс ADO. В связи с этим интерфейс OD BC

16. Интерфейсы программирования Web-приложения

629

недоступен из серверных сценариев JScript и VB Script, расположенных в страницах ASP. Но в традиционной технологии IDC/HTX-страниц возможно использование интерфейса ODBC с помощью объектов IDC/HTX.

Использование этого интерфейса предполагает установку драйвера ODBC для конкретного тина СУБД. Например, драйвер ODBC стандартно входит в

состав СУБД, созданных фирмой Microsoft. Драйверы ODBC входят в состав многих СУБД, рассчитанных на работу в среде операционных систем Microsoft Windows, Macintosh и некоторых версий Unix.

Кроме того, дополнительно в состав операционной системы включается администратор ODBC, позволяющий устанавливать параметры соединения с источником данных.

Для обеспечения доступа к конкретному источнику данных используются системные имена источника данных DSN (Data System Name). Например, в операционных системах Microsoft Windows администратор ODBC входит в состав утилит панели управления и имеет название «Администратор источников данных ODBC» (рис. 16.2).

С 1 Администратор источников данных ODBC

 

 

 

Драйверы |

Трассировка I Группировка подключений

j

0 программе

Пользовательский DSN

{

Системный DSN

|

Файловый DSN

Источники данных пользователя: -

 

 

 

 

J H m r ^

1

Драйвер

,

1

 

Добавить... |

Е Д И Н

 

 

Microsoft Access Driver (".mdb)

 

.'

'

MS Access 7.0 Database

Microsoft Access Driver (x.mdb)

 

 

Удалить

Застройка...

Источив данных ODBC пользователя сохраняет сведения об установке связи с источником: Он доступен только этому пользователю и может применяться лишь на данном компьютере.

ОК

Отмена J ~ Применить

Справка

Рис. 16.2. Окно Администратора источника данных ODBC

630 Часть 4. Публикация баз данных в Интернете

Администратор ODBC позволяет вводить новые пользовательские DSN и перенастраивать существующие имена. При настройке имен DSN имеется возможность связывать каждое имя DSN с конкретной БД.

При использовании интерфейса ODBC для доступа к БД применяются функции^ входящие в состав библиотеки ODBC, а запросы для извлечения требуемых данных составляются на языке SQL.

Пример 1. Создание CGI-модуля — приложения "OD.EXE", раскрывающего основные возможности интерфейса ODBC для создания простейших Webприложений, связанные с доступом к информации в БД с помощью языка SQL.

//Стандартные заголовочные файлы #include <"windows.h>

#include <stdio.h> #include <sql.h> #include <sqlext.h> #include <sqltypes.h> #include <odbcss.h> #include <string> using namespace std;

//Заголовочный файл, генерируемый средой Visual С++ #include "stdafx.h"

int main(int argc, char* argv[])

{

//Определение системных переменных SQLHENV sql_henv = SQL_NULL_HENV; SQLHDBC sql_hdbc = SQL_NULL_HDBC; SQLHSTMT sql_hstmt = SQL_NULL_HSTMT;

RETCODE err;

UCHAR sys_DSN[SQL_MAX_DSN_LENGTH + 1] = "Authors"; UCHAR user_Name[MAXNAME] = "";

UCHAR user_Password[MAXNAME] = ""; //Инициализация среды выполнения приложения

err = SQLAIIocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &sql_henv);

//Анализ кода ошибки

if(err != SQL_SUCCESS && err != SQL_SUCCESS_WITH_INFO) return 1; //установка параметров среды выполнения приложения

err = SQLSetEnvAttr(sql_henv , SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER); //Анализ кода ошибки

if(err != SQL_SUCCESS && err != SQL_SUCCESS_WITH_INFO) return 1;

16. Интерфейсы программирования Web-приложения

631

//инициализация среды соединения

err = SQLAIIocHandle(SQL_HANDLE_DBC, sql_henv , &sql_hdbc ); if(err != SQL_SUCCESS && err != SQL_SUCCESS_WITH_INFO) return 1;

//установка соединения err = SQLConnect(sql_hdbc,

sys_DSN, (SWORD)strlen((const char*)sys_DSN), user_Name, (SWORD)strlen((const char*)user_Name),

user_Password, (SWORD)strlen((const char*)user_Password));

if(err != SQL_SUCCESS && err != SQL_SUCCESS_WITH_INFO)

{

printf("SQLConnect error\n");

return 1;

}

// получение идентификатора команд

err = SQLAIIocHandle(SQL_HANDLE_STMT, sql_hdbc, &sql_hstmt);

if(err != SQL_SUCCESS && err != SQL_SUCCESS_WITH_INFO)

{

printf("SQLAIIocHandle Error\n");

return 1;

}

//выполнение команды

err = SQLExecDirect(sql_hstmt, (unsigned char*) "select * from Authors",

SQLNTS);

if(err != SQL_SUCCESS && err != SQL_SUCCESS_WITH_INFO)

{

printf("SQLExecDirect Error\n");

return 1;

}

SQLCHAR id[30]; SQLINTEGER lid; SQLCHAR name[30]; SQLINTEGER Iname; SQLCHAR year[30]; SQLINTEGER lyear;

//Связывание указателей со значениями полей текущей записи err = SQLBindCol(sql_hstmt, 1, SQL_C_CHAR, id, 30, &lid);

err = SQLBindCol(sql_hstmt, 2, SQL_C_CHAR, name, 30, &lname); err = SQLBindCol(sql_hstmt, 3, SQL_C_CHAR, year, 30, &lyear); //Вывод заголовка HTML-доку мента

printf("Content-type: text/html%c%c" ,10,10);

632 Часть 4. Публикация баз данных в Интернете

p r i n t f ( " < H T M L X H E A D X T I T L E > M Y T E S T < / T I T L E > < / H E A D X B 0 D Y > " ) ;

c h a r * d = " % " ;

//Вывод заголовка таблицы

p r i n t f ( " < T a b l e W i d t h = ' 1 0 0 % s ' C e l l S p a c i n g = 1 0 C e l l P a d d i n g = 1 0 B o r d e r = 3 > " , d ) ;

p r i n t f ( " < C a p t i o n a l i g n = C e n t e r > l n f o r m a t i o n f r o m D a t a B a s e < / C a p t i o n > " ) ; p r i n t f ( " < T R > < T H > Id < Д Н х Т Н W i d t h = 1 0 0 % s > N a m e < Д Н Х Т Н > Year

//Вывод строчек таблицы

w h i l e ( ( e r r = S Q L F e t c h ( s q l _ h s t m t ) ) != S Q L N O DATA)

{

p r i n t f ( " < T R > < T D > % 15s < 7 T D X T D > % 2 5 s < Д О Х Т О > % 1 0 s < / T D > < Д Я > " ,

id, n a m e , y e a r ) ;

}

р г М ( " < Д а Ы е > " ) ;

p r i n t f ( " < / B O D Y X / H T M L > " ) ;

//Удаление служебных переменных

S Q L F r e e H a n d l e ( S Q L _ H A N D L E _ S T M T , s q l _ h s t m t ) ; S Q L D i s c o n n e c t ( s q l h d b c ) ;

S Q L F r e e H a n d l e ( S Q L _ H A N D L E _ D B C , s q l _ h d b c ) ; S Q L F r e e H a n d l e ( S Q L _ H A N D L E _ E N V , s q l _ h e n v ) ;

r e t u r n 0;

}

В функции m a i n ( ) последовательно выполняются следующие операции, установленные интерфейсом ODBC для получения доступа к БД:

инициализация среды выполнения приложения ODBC;

подключение к источнику данных;

выполнение команд SQL для получения требуемых данных;

освобождение памяти, выделенной под служебные переменные для работы с интерфейсом ODBC.

Для инициализации среды

выполнения приложения ODBC

используется

функция S Q L A I I o c H a n d l e ( ) .

Следующий код устанавливает

переменной

s q l _ h e n v значение идентификатора среды исполнения:

 

err -- SQLAIIocHandle(SQL _ HANDLE _ ENV, S Q L NULL HANDLE, &sql _ henv);

Параметры функции задают следующее:

•тип идентификатора ( S Q L _ H A N D L E _ E N V — идентификатор среды);

• контекст идентификатора; •адрес переменной, которой присваивается полученный функцией иден-

тификатор.