龚 建 勇
( 华 中 理 工 大 学 图 像 识 别 与 人 工 智 能 所)
( 通 信 地 址: 华 中 理 工 大 学 西 五 舍203 室,PC:430074)
摘 要: 本 文 介 绍 了 实 现web 交 互 的 两 种 方 法,CGI 及ISAPI。 对 它 们 的 原 理、 实 现 方 法 作 了 阐 述, 并 就 它 们 的 性 能 进 行 了 比 较。 最 后 简 单 介 绍 了ISAPI 应 用 的 具 体 实 现。
关 键 词: WEB 交 互 CGI ISAPI
一、 引 言
ISAPI 与CGI 都 属 于 通 用 的 网 关 接 口, 主 要 用 来 实 现WWW 服 务 器 与 客 户 端 的 信 息 交 互。
随 着WWW 爆 炸 式 的 发 展 及 其 日 益 普 及, 人 们 的 眼 光 已 被 充 斥 其 上 的 商 机 所 吸 引。 在WWW 上 求 取 经 济 利 益 的 方 式 主 要 有 以 下 几 种:
通 过 为 企 业 等 作 广 告 宣 传 收 取 广 告 费;
向 入 网 观 看 者 收 取 订 阅 费;
直 接 在 网 上 出 售 商 品 和 服 务。
目 前 大 多 数 网 站 提 供 信 息 的 方 式 是 由 用 户 通 过 客 户 浏 览 器( 如Netscape 或Explorer 等) 与WWW 服 务 器 连 接, 然 后 用 鼠 标 点 按 超 连 接 以 浏 览 相 关 主 页。 在 此 过 程 中, 基 本 上 是 服 务 器 向 客 户 端 单 方 向 的 信 息 传 递, 随 着 服 务 需 求 的 不 断 扩 大, 这 种 单 纯 的 单 方 向 传 递 信 息 的 静 态 主 页 已 不 能 满 足 需 求。 不 论 是 服 务 提 供 方 还 是 客 户, 都 希 望 浏 览 服 务 器 将 信 息 发 送 到 用 户 同 时, 用 户 端 也 能 将 信 息 发 送 到 服 务 器 端, 实 现 服 务 器 与 客 户 的 交 互。 典 型 的 应 用 如: 用 户 登 记 表、 用 户 留 言 板 以 及 用 户 通 过WWW 检 索 服 务 器 端 的 数 据 库 等。
要 实 现 一 个 可 与 用 户 交 互 信 息 的 服 务 系 统, 所 需 增 加 的 有 两 项: 交 互 式 主 页 和 用 户 输 入 信 息 处 理 程 序。 交 互 式 主 页 即 有 输 入 信 息 的 编 辑 框, 选 择 菜 单 按 钮 之 类 的 主 页, 以 供 用 户 输 入 信 息; 用 户 输 入 的 信 息 则 交 由 用 户 信 息 处 理 程 序 处 理。 实 现 该 程 序 可 以 有 多 种 途 径, 该 程 序 可 以 放 在 服 务 器 端, 也 可 以 放 在 客 户 机 端, 前 者 如CGI、ISAPI, 后 者 如JAVA APPLET 等。 本 文 只 讨 论 前 者, 将 阐 述ISAPI 的 优 点, 并 就 其 实 现 举 例 说 明。
二、WEB 交 互 环 境 的 实 现
2.1 交 互 式 主 页
要 实 现WEB 上 的 交 互 环 境, 用 户 必 须 能 够 在 他 浏 览 到 的 主 页 上 输 入 信 息, 这 就 是 一 个 交 互 式 的 主 页。 一 般 来 说, 用 户 输 入 信 息 的 形 式 有 填 写 编 辑 框, 点 选 无 线 按 钮 等 选 择 框 及 选 择 下 拉 菜 单 等, 所 以 交 互 主 页 也 必 须 有 这 些 输 入 元 素 项。 下 面 是 一 个 简 单 的 交 互 主 页 例 子:
交 互 式 主 页HTML 源 文 件:isapi1.htm
「HTML」
「TITLE」 TEST 「/TITLE」
「HEAD」
ISAPI TEST
「/HEAD」
「BODY」
「form action="/gjy/isapi1/debug/isapi1.dll?RegisterUser" method=post」
Input your Register Infomation:「br」
Name :「input type="text" name="First"」「br」
Address:「input type="text" name="Middle"」「br」
Email:「input type="text" name="Last"」「br」「p」
「input type="submit"」
「input type="reset" 」「/p」
「/form」
「/body」
「/html」
通 过Explorer 浏 览 器 打 开 该 文 件, 可 以 看 到 如 下 效 果( 编 辑 框 中 已 输 入 内 容):
2.2 实 现 交 互 主 页 的 途 径。
从 上 述 主 页 制 作 描 述 可 见, 一 个 交 互 式 主 页 的 制 作 是 很 简 单 的, 但 要 真 正 实 现 与 用 户 的 交 互, 还 必 须 要 有 应 用 程 序 的 参 与。 这 个 程 序 可 以 属 于 多 种 样 式, 如CGI、JAVA APPLET 以 及ISAPI。 在 上 述 主 页 文 件 中, 有 一 项:
「form action="/gjy/isapi1/debug/isapi1.dll?RegisterUser" method=post」
这 里 就 指 明 了 对 应 处 理 该 主 页 输 入 信 息 的 程 序(isapi1.dll), 这 是ISAPI 的 应 用 程 序 动 态 连 接 库。 对 于CGI 应 用 程 序 也 是 一 样 的 处 理。
一 般 来 说, 该 程 序 的 功 能 就 是 要 将 用 户 输 入 信 息 传 到 服 务 器 应 用 程 序。
CGI 是 大 家 都 比 较 熟 悉 的 一 种 实 现 上 述 功 能 的 有 效 途 径, 也 可 能 是 当 前 最 为 流 行 的 一 种, 而ISAPI 是 微 软 独 特 的 具 有 类 似CGI 功 能 的 网 络 应 用 接 口 标 准。ISAPI 在 性 能 上 较 之CGI 具 有 许 多 优 良 特 性。 下 面 我 们 简 单 介 绍 一 下CGI 与ISAPI 以 及 它 们 之 间 的 性 能 差 别。
三、CGI 原 理 及 其 性 能
3.1 CGI 概 念
CGI 即 通 用 网 关 接 口(Common Gateway Interface), 它 是 一 个WWW 服 务 器
主 机 对 外 服 务 的 标 准 接 口, 一 般 来 说, 一 个CGI 接 口 的 功 能 就 是 在 超 文 本 文 件 和 服 务 器 主 机 应 用 程 序 间 传 递 信 息。
3.2 CGI 程 序 语 言
事 实 上, 任 何 一 种 程 序 语 言, 只 要 能 在 服 务 器 主 机 上 利 用CGI 接 口 来 编 写 应 用 程 序, 都 可 以 叫 作CGI 程 序 语 言。 目 前 最 为 流 行 的CGI 程 序 语 言 有 四 种:C,Shell,Perl 和Visual Basic, 其 它 一 些 语 言 也 有 许 多 人 在 用, 如TCL,Fortran 及AppleScript 等。
3.3 CGI 程 序 的 执 行
CGI 程 序 一 般 是 个 可 执 行 程 序。 编 译 好 的CGI 程 序 一 般 要 集 中 放 在 一 个 目 录 下。 具 体 存 放 的 位 置 随 操 作 系 统 的 不 同 而 不 同, 例 如UNIX 系 统 下 是 放 在cgi-bin 子 目 录 下, 而 在Windows 操 作 系 统 下( 注 意, 这 里 不 包 括NT4.0) 以Webstar 或Website 作WWW 服 务 器,CGI 程 序 都 放 在cgi-win 下。CGI 程 序 的 执 行 一 般 有 两 种 调 用 方 式:1 是 通 过URL 直 接 调 用, 如:“http://202.114.2.182/cgi-win/cgi.exe”, 在 浏 览 器 的URL 栏 里 直 接 写 入 上 述 描 述 就 可 以 调 用 该 程 序; 另 一 种 方 式, 也 是 主 要 的 方 式, 是 通 过 交 互 式 主 页 里 的FORM 栏 调 用, 通 常 都 是 用 户 在 填 完 一 张 输 入 信 息 主 页 后 按 确 认 按 钮 启 动CGI 程 序, 前 面 的 交 互 主 页 就 是 一 个 如 此 调 用CGI 的 典 型 例 子。
3.4 CGI 工 作 的 主 要 流 程
CGI 工 作 的 主 要 流 程 是:1. 一 个 用 户 请 求 激 活 一 个CGI 应 用 程 序;2.CGI 应 用 程 序 将 交 互 主 页 里 用 户 输 入 信 息 提 取 出 来;3. 将 用 户 输 入 的 信 息 传 给 服 务 器 主 机 应 用 程 序( 如 数 据 库 查 询〕;4. 将 服 务 器 处 理 结 果 通 过HTML 文 件 返 回 给 用 户;5.CGI 进 程 结 束。
3.5 CGI 的 性 能 评 价
CGI 的 跨 平 台 性 能 极 佳, 几 乎 可 以 在 任 何 操 作 系 统 上 实 现, 如DOS、WINDOWS、UNIX、OS/2、Macintosh 等。 实 现CGI 的 编 程 语 言 也 有 很 多 选 择。CGI 的 应 用 程 序 一 般 都 是 一 个 独 立 的 可 执 行 程 序, 和WWW 服 务 器 各 自 占 据 着 不 同 的 进 程, 而 且 一 般 一 个CGI 程 序 只 能 处 理 一 个 用 户 请 求。 这 样, 每 有 一 个 用 户 请 求, 都 会 激 活 一 个CGI 进 程, 当 用 户 请 求 数 量 非 常 多 时, 会 大 量 挤 占 系 统 的 资 源 如 内 存,CPU 时 间 等, 造 成 效 能 低 下。
四、ISAPI 原 理 及 其 性 能
4.1 ISAPI 概 念
ISAPI 即Internet Server Application Program Interface, 是 微 软 提 供 的 一 套 面 向Internet 服 务 的API 接 口, 它 能 实 现CGI 能 提 供 的 全 部 功 能, 并 在 此 基 础 上 进 行 了 扩 展, 如 提 供 了 过 滤 器 应 用 程 序 接 口。
4.2 ISAPI 程 序 语 言
由 于 开 发ISAPI 应 用 要 用 到 微 软 的 一 套API, 所 以 能 用 来 开 发ISAPI 应 用 的 语 言 不 如CGI 那 么 多。 主 要 有Visual C++ 4.1 以 上 版 本,Visual Basic 5.0、Borland C++ 5.0 也 可 以。
4.3 ISAPI 原 理
ISAPI 的 工 作 原 理 和CGI 大 体 上 是 相 同 的, 都 是 通 过 交 互 式 主 页 取 得 用 户 输 入 信 息, 然 后 交 服 务 器 后 台 处 理。 但 是 二 者 在 实 现 机 制 上 大 相 庭 径。ISAPI 与CGI 最 大 的 区 别 在 于: 不 同 于CGI, 在ISAPI 下 建 立 的 应 用 程 序 是 以 动 态 连 接 库 的 形 式 存 在; 而CGI 的 应 用 程 序 一 般 都 是 可 执 行 程 序。
4.4 ISAPI 程 序 的 执 行
ISAPI 应 用 的 工 作 流 程 与CGI 有 一 些 不 同。ISAPI 应 用 的DLL 不 仅 可 以 象CGI 程 序 一 样 被 用 户 请 求 激 活, 还 可 以 被 系 统 预 先 激 活 来 监 视 用 户 输 入; 对 于 被 用 户 激 活 的DLL, 在 处 理 完 一 个 用 户 请 求 后 不 会 马 上 消 失, 而 是 继 续 驻 留 在 内 存 中 等 待 处 理 别 的 用 户 输 入, 直 到 过 了 一 段 时 间 后 一 直 没 有 用 户 输 入。
4.5 ISAPI 性 能 评 价
一 个ISAPI 的DLL, 可 以 在 被 用 户 请 求 激 活 后 长 驻 内 存, 等 待 用 户 的 另 一 个 请 求, 还 可 以 在 一 个DLL 里 设 置 多 个 用 户 请 求 处 理 函 数, 此 外,ISAPI 的DLL 应 用 程 序 和WWW 服 务 器 处 于 同 一 个 进 程 中, 效 率 要 显 著 高 于CGI。
不 过ISAPI 的 平 台 兼 容 性 较 差, 目 前 只 能 用 于 微 软 自 己 的Windows 95 和NT 操 作 系 统 上, 服 务 器 平 台 也 仅 限 于IIS(Internet Information Server) 和MS personal web server 以 及NT workstation 上 的peer web server。
五、ISAPI 的 实 现
能 够 支 持ISAPI 开 发 的 平 台 只 有 微 软 的 几 个 平 台 组 合( 如NT+IIS,WIN95+MS personal web server)。 因 此 开 发ISAPI 只 能 这 几 个 平 台 上。 开 发 语 言 前 已 有 述, 这 里 向 大 家 推 荐Visual C++ 4.2 版, 它 的Wizard 提 供 了 专 门 制 作ISAPI 的 功 能 项。
下 面 是 个 简 单 的 例 子, 功 能 是 将 用 户 从 浏 览 器 上 的 输 入 简 单 地 回 显 给 用 户, 功 能 简 单, 但 是 具 备 一 个 典 型 的ISAPI 全 部 流 程。 源 程 序 如 下( 大 部 分 为Wizard 生 成 的 代 码):
1. 主 程 序:
// ISAPI1.CPP - Implementation file for your Internet Server
#include "stdafx.h"
#include "isapi1.h"
///////////////////////////////////////////////////////////////////////
// The one and only CWinApp object
// NOTE: You may remove this object if you alter your project to no
// longer use MFC in a DLL.
CWinApp theApp;
///////////////////////////////////////////////////////////////////////
// command-parsing map
BEGIN_PARSE_MAP(CIsapi1Extension, CHttpServer)
/************* My codes begin here ***********/
ON_PARSE_COMMAND(RegisterUser,
CIsapi1Extension, ITS_PSTR ITS_PSTR ITS_PSTR)
ON_PARSE_COMMAND_PARAMS("First Middle Last")
/************* My codes end here ***********/
END_PARSE_MAP(CIsapi1Extension)
///////////////////////////////////////////////////////////////////////
// The one and only CIsapi1Extension object
CIsapi1Extension theExtension;
///////////////////////////////////////////////////////////////////////
// CIsapi1Extension implementation
CIsapi1Extension::CIsapi1Extension()
{
}
CIsapi1Extension::~CIsapi1Extension()
{
}
BOOL CIsapi1Extension::GetExtensionVersion
(HSE_VERSION_INFO* pVer)
{
// Call default implementation for initialization
CHttpServer::GetExtensionVersion(pVer);
// Load description string
TCHAR sz[HSE_MAX_EXT_DLL_NAME_LEN+1];
ISAPIVERIFY(::LoadString(AfxGetResourceHandle(),
IDS_SERVER, sz, HSE_MAX_EXT_DLL_NAME_LEN));
_tcscpy(pVer->lpszExtensionDesc, sz);
return TRUE;
}
///////////////////////////////////////////////////////////////////////
// CIsapi1Extension command handlers
/****** My code begins here**********/
void CIsapi1Extension::RegisterUser
( CHttpServerContext* pctxt, LPCTSTR
pstrFirst, LPCTSTR pstrMiddle, LPCTSTR pstrLast )
{
// do processing here!
*pctxt << _T("Your name is:");
*pctxt << _T(pstrFirst);
*pctxt << _T("\n");
*pctxt << _T("Your Address is:");
*pctxt << _T(pstrMiddle);
*pctxt << _T("\n");
*pctxt << _T("Your E_mail is:");
*pctxt << _T(pstrLast);
}
/********* My codes end here **********/
// Do not edit the following lines,
which are needed by ClassWizard.
#if 0
BEGIN_MESSAGE_MAP(CIsapi1Extension, CHttpServer)
//{{AFX_MSG_MAP(CIsapi1Extension)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif// 0
2. 主 头 文 件
// ISAPI1.H - Header file for your Internet Server
//isapi1 Extension
#include "resource.h"
class CIsapi1Extension : public CHttpServer
{
public:
CIsapi1Extension();
~CIsapi1Extension();
// Overrides
// ClassWizard generated virtual function overrides
// NOTE - the ClassWizard will add and remove member functions here.
//DO NOT EDIT what you see in these blocks of generated code !
//{{AFX_VIRTUAL(CIsapi1Extension)
public:
virtual BOOL GetExtensionVersion(HSE_VERSION_INFO* pVer);
//}}AFX_VIRTUAL
// TODO: Add handlers for your commands here.
/*********** My coded begin here ( 函 数 声 明) *********/
void RegisterUser( CHttpServerContext* pctxt,
LPCTSTR pstrFirst, LPCTSTR
pstrMiddle, LPCTSTR pstrLast );
/*********My codes end here
DECLARE_PARSE_MAP()
//{{AFX_MSG(CIsapi1Extension)
//}}AFX_MSG
};
3. 动 态 连 接 库 定 义 文 件
/*************************************/
/*ISAPI1.def */
/*************************************/
; ISAPI1.def : declares the module parameters for the DLL.
LIBRARY"ISAPI1"
EXPORTS
HttpExtensionProc
GetExtensionVersion
在 上 述 程 序 中, 定 义 了 一 个CHttpServer 的 类CIsapi1Extension, 这 是 该 程 序 的 主 要 一 个 类, 通 过 它 实 现 与 用 户 交 互 的 功 能。 由ON_PARSE_COMMAND 段 实 现 函 数 映 射, 上 述 程 序 中 定 义 了 该DLL 中 的 一 个 成 员 函 数RegisterUser, 其 功 能 就 是 将 用 户 在 编 辑 框 中 输 入 的 信 息 发 送 回 用 户。 关 于 具 体 实 现 细 节, 可 以 参 看VC4.2 帮 助 文 档。
将 上 述 文 件 编 译 成DLL 后 放 入 服 务 器 主 机 内WWW 服 务 器 指 定 的 用 户 有 执 行 权 限 的Scripts 目 录 里, 该 目 录 的 逻 辑 名 应 和 交 互 主 页 里 的 一 致。 设 置 完 后, 通 过 浏 览 器 连 到 服 务 器 上, 浏 览 该 主 页, 并 输 入 信 息 到 编 辑 框 中。
……