CGI 程 式 设 计

----------------------------------------------------------------------
----------

大 纲
一 、 为 什 么 要 使 用 CGI ? 
二 、 什 么 是 CGI ? 
2-1 CGI 简 介 
2-2 CGI 的 输 入 输 出 
2-3 CGI 可 用 的 程 式 语 言 
三 、 CGI 的 输 入 介 面 
3-1 ISINDEX 
3-2 FORM 
3-2-1 FORM 标 签 
3-2-2 INPUT 标 签 
3-2-3 SELECT 标 签 
3-2-4 TEXTAREA 标 签 
四 、 CGI 如 何 运 作 ? 
4-1 CGI 运 作 流 程 
4-2 CGI 传 递 资 料 的 方 法 
4-3 CGI 的 参 数 
五 、 CGI 输 出 介 面 
5-1 CGI 输 出 格 式 
5-2 基 本 程 式 范 例 
5-2-1 Perl 
5-2-2 C for POST METHOD 
5-2-3 C for GET METHOD 
附 录 A 、 相关 参 考 资 料 
附 录 B 、 范例 原 始 程 式 
附 录 C 、 CGI 函 式 库

----------------------------------------------------------------------
----------

一 、 为 什 么 要 使 用 CGI ?
随 著 全 球 资 讯 网 (World Wide Web, WWW) 的 兴 起 , 网 路 从 平 淡 
的文 字 世 界 进 入 了 影 音 声 光 的 新 纪 元 。 同 时 也 引 进 了 新
 的阅 读 方 法 , 一 种 有 别 於 传 统 循 序 式 的 阅 读 方 法 ━ Hype
rText 。 让 人 们 能 够 直 接 从 有 兴 趣 的 主 题 切 入 , 并 且 在 其
 间 相互 跳 跃 、 链 结 , 以 取 得 所 想 要 的 资 料 。 也 因 此 带 动
 了 网路 人 口 的 激 增 以 及 无 限 的 商 机 , 所 以 在 商 业 应 用 上
 这 是一 个 值 得 开 发 的 空 间 。 
但 是 这 样 的 方 式 却 缺 少 了 一 个 商 业 应 用 上 一 个 重 要 的特
 性 , 那 就 是 ━ 互 动 性 。 而 CGI 的 出 现 正 是 为 了 弥 补 其 不
足 ! 有 了 CGI 功 能 的 加 入 可 以 使 得 WWW 的 环 境 不 仅 有 单 向
的 资 讯 浏 览 , 更 可 以 有 双 向 的 互 动 。 若 说 CGI 的 发 展 是 
WWW 能 受 广 大 使 用 者 喜 爱 的 最 大 原 因 是 不 为 过 的 。 
事 实 上 , CGI 的 应 用 相 当 的 广 泛 , 可 以 藉 著 与 其 它 系统 的
 结 合 而 增 强 WWW Server 的 功 能 。 例 如 ∶ 与 资 料 库 管 理系 统
 (DBMS) 结 合 , 便 是 一 种 最 常 见 , 而 且 是 最 具 扩 充 性 的方 
式 。 因 为 经 由 不 同 的 资 料 库 , 可 以 使 WWW Server 提 供 或者 
是 记 录 多 样 化 的 资 讯 。 
同 时 , 也 可 利 用 CGI 制 作 登 录 (Login) 系 统 , 将 具 有 机 密性
 的 资 料 , 以 密 码 的 方 式 加 以 保 护 。 不 但 省 去 了 系 统 过於
 开 放 的 困 扰 , 也 可 以 有 效 的 管 理 使 用 者 。 更 进 一 步 ,可
 以 记 录 使 用 者 的 使 用 情 形 , 以 便 加 以 计 费 或 者 是 在 网路
 上 进 行 电 子 交 易 。 
是 故 如 果 要 将 商 业 应 用 在 WWW 上 , CGI 势 必 是 不 可 或 缺的 
一 环 。 以 下 我 们 将 会 以 和 资 料 库 管 理 系 统 结 合 为 核 心,
 逐 步 介 绍 何 谓 CGI 、 CGI 如 何 输 入 资 料 、 CGI 如 何 运 作 以及
 CGI 怎 么 输 出 资 讯 回 给 使 用 者 , 并 且 在 最 後 附 上 几 个 CG
I 应 用 的 范 例 , 让 您 了 解 并 且 实 作 CGI 。 
此 外 , 本 章 的 实 作 以 及 范 例 使 用 的 作 业 系 统 为 MicroSoft 
NT , WWW Server 为 EMWAC HTTPS , 资 料 库 管 理 系 统 为 MicroSoft S
QL Server , 程 式 语 言 为 Microsoft C 与 资 料 库 管 理 系 统 的 介 
面 为 DB-Library 。 关 於 这 些 部 分 的 详 细 资 料 将 不 在 赘 述 ,
 如 果您 对 其 它 的 CGI 系 统 有 兴 趣 或 是 想 要 更 深 入 了 解 本 
章 实 作的 非 CGI 部 分 , 请 自 行 参 考 相 关 资 料 。  
二 、 什 么 是 CGI ?
2-1 CGI 简 介 
CGI 是 Common Gateway Interface 的 简 称 。 其 主 要 的 功 能 是 在 WW
W 环 境 下 , 藉 由 从 客 户 端 传 递 一 些 讯 息 给 WWW Server , 再 
由 WWW Server 去 启 动 所 指 定 的 程 式 码 来 完 成 特 定 的 工 作 。
 所以 更 明 确 的 说 , CGI 仅 是 在 WWW Server 上 可 执 行 的 程 式 码
 ,而 她 的 工 作 就 是 控 制 讯 息 要 求 而 且 产 生 并 传 回 所 需 的
 文件 。 
使 用 CGI , 你 的 Server 可 以 读 取 并 显 示 在 客 户 端 无 法 读取 
的 格 式 (像 是 SQL DataBase) 。 而 且 可 以 像 闸 道 (Gateway) 一 样,
 在 伺 服 端 和 客 户 端 之 间 , 产 生 客 户 端 所 需 要 的 讯 息 。基
 本 上 , 在 此 种 主 从 式 (Client/Server) 的 环 境 之 下 , 其 IPC (
InterProcess Communication) 的 协 定 是 利 用 讯 息 传 递 及 记 忆 体分
 享 (环 境 变 数) 的 方 式 来 完 成 。 CGI 有 其 特 定 的 写 法 及 规格
 , 必 须 遵 守 其 原 则 , 方 可 达 到 主 从 端 资 讯 交 流 的 目 的。
 
2-2 CGI 的 输 入 输 出 
CGI 可 以 使 用 在 很 多 方 面 , 大 部 份 是 控 制 ISINDEX 和 FORM 的
需 求 , 亦 即 ISINDEX 和 FORM 最 常 被 使 用 作 CGI 的 输 入 介 面 。
但 也 有 利 用 链 结 (LINK) 的 方 式 来 呼 叫 所 要 执 行 的 程 式 , 
通常 是 在 使 用 者 的 资 讯 已 固 定 , 或 是 为 达 成 某 种 单 一 目
 的而 使 用 。 而 使 用 链 结 方 式 其 程 式 执 行 所 需 的 参 数 是 以
 GET METHOD 的 方 式 含 在 URL 中 传 入 , 亦 即 CGI 程 式 在 发 展 时
 必 须使 用 GET METHOD 的 方 式 来 读 取 参 数 。 在 第 四 节 , 我 们
 将 会详 细 介 绍 传 递 参 数 的 方 法 。 
输 出 的 部 分 则 大 部 分 是 利 用 程 式 来 产 生 虚 拟 文 件 , 也就
 是 文 件 并 不 是 储 存 Server 的 储 存 媒 体 中 , 而 是 由 程 式 建
构 出 来 的 , 浏 览 程 式 结 束 之 後 文 件 即 不 再 存 在 。 大 部 分
的 文 件 格 式 是 超 本 文 标 示 语 言 (HTML) 或 是 文 字 档 。 也 有 
利用 程 式 链 结 到 另 一 份 文 件 , 或 是 只 记 录 使 用 者 输 入 资
 讯而 不 做 输 出 ! 
下 面 是 常 见 输 入 输 出 的 例 子 ∶ 
转 换 您 的 系 统 参 考 手 册 变 成 超 本 文 标 示 语 言 (HTML) 的 格 
式, 接 著 将 结 果 送 给 客 户 端 。 
当 做 WAIS 和 ARCHIE 资 料 库 的 界 面 , 将 结 果 转 成 超 本 文 标 示
语 言 (HTML) 的 格 式 送 给 客 户 端 。 
允 许 使 用 者 透 过 HTML FORM 和 附 加 的 CGI 解 码 来 回 给 你 的 Se
rver 。 
在 下 面 各 节 , 我 们 将 会 进 一 步 说 明 有 关 这 一 部 分 的 使 用
方 法 , 或 是 简 单 的 范 例 。 
2-3 CGI 可 用 的 程 式 语 言 
至 於 CGI 要 使 用 何 种 程 式 语 言 来 达 成 ? 从 前 面 的 说 明 可 
以知 道 , CGI 仅 是 在 WWW Server 上 可 执 行 的 程 式 码 。 是 故 ,
 只要 是 您 的 WWW Server 以 及 WWW Server 所 在 的 作 业 系 统 可 执 
行 的程 式 语 言 皆 能 使 用 在 CGI 上 。 以 下 列 出 几 种 较 常 在 C
GI 中使 用 的 语 言 ∶ 
C/C++ 
PERL 
THE BOURNE SHELL 
THE C SHELL 
TCL 
Visual Basic 
AppleScript 
这 些 程 式 在 完 成 之 後 要 放 置 於 何 处 ? 事 实 上 , 不 同 的 W
WW Server 有 不 同 的 规 定 。 以 HTTPS 为 例 , 她 只 执 行 副 档 名 
为 EXE 的 执 行 档 , 且 程 式 不 能 为 图 形 介 面 (GUI) 的 程 式 。 
而 程 式只 要 放 置 在 指 定 文 件 的 树 状 目 录 中 任 一 位 置 即 可
 。 但 是值 得 注 意 的 是 , 大 部 分 的 WWW Server 尤 其 是 UNIX 上 
的 WWW Server , 都 将 CGI 程 式 放 置 在 一 共 同 的 指 定 目 录 之 下
 。 所 以 在 放置 CGI 程 式 时 , 请 先 参 考 您 的 WWW Server 手 册 。

三 、 CGI 的 输 入 介 面
在 一 个 完 整 的 系 统 中 , 输 入 介 面 是 直 接 和 使 用 者 接 触 的
第 一 线 。 所 以 输 入 介 面 , 在 整 个 系 统 中 扮 演 著 举 足 轻 重
的 地 位 , 输 入 介 面 的 好 坏 将 直 接 影 向 系 统 的 成 败 。 好 的
输 入 介 面 可 以 弥 补 系 统 设 计 上 的 某 些 缺 陷 , 但 是 要 如 何
设 计 出 一 个 好 的 输 入 介 面 呢 ? 所 谓 「 工 欲 善 其 事 , 必 先
利 其 器 」 , 要 设 计 出 好 的 输 入 介 面 , 第 一 步 应 了 解 手 边
究 竟 有 哪 些 修 缮 门 面 的 工 具 ! 在 这 一 节 中 , 我 们 将 为 您
介 绍 CGI 的 主 要 输 入 介 面 , 让 您 做 好 成 功 的 第 一 步 。 
在 CGI 中 较 常 见 的 输 入 介 面 有 ISINDEX 和 FORM 两 种 , 详 细内 
容 分 述 如 下 ∶ 
3-1 ISINDEX 
ISINDEX 是 一 个 特 殊 的 标 签 , 使 用 的 方 法 如 下 ∶ 
<ISINDEX ACTION="URL"> 
其 中 URL 为 想 要 执 行 的 程 式 之 所 在 位 址 及 档 名 。 
如 此 会 使 浏 览 程 式 产 生 一 个 输 入 的 视 窗 , 当 使 用 者 完成
 输 入 按 下 ENTER 键 後 , Server 会 执 行 参 数 ACTION 中 指 定 的程
 式 。 下 面 是 一 个 简 单 的 范 例 ∶

----------------------------------------------------------------------
----------
可以搜索该索引。请键入要搜索的关键字:
----------------------------------------------------------------------
----------

常 见 的 用 法 是 与 WAIS Server 结 合 , 或 是 做 档 案 的 搜 寻 。本
 节 的 重 点 将 放 在 FORM 的 实 作 上 , 所 以 我 们 在 这 里 不 对 I
SINDEX 做 详 细 的 介 绍 , 如 有 兴 趣 请 自 行 参 考 相 关 资 料 。

3-2 FORM 
FROM 在 CGI 中 是 最 常 被 使 用 的 输 入 介 面 , 虽 然 并 不 十 分 完
美 , 但 却 是 目 前 WWW 中 最 强 大 的 输 入 工 具 。 FORM 是 由 一 组
相 关 连 的 标 签 所 组 成 , 使 用 方 法 就 像 其 它 标 签 一 样 。 在
 FORM 中 提 供 了 我 们 多 种 输 入 资 料 的 工 具 , 例 如 文 字 输 入
区 (Text) 、 下 拉 式 表 单 (Select Box) 、 按 钮 (Button) 、 选
择 钮 (Radio Button) 等 等 。 
就 目 前 所 定 义 的 标 准 中 , FORM 的 标 签 可 分 为 三 大 类 ∶ <I
NPUT> 、 <SELECT> 以 及 <TEXTAREA> 。 下 面 的 例 子 是 FORM 的 一 个 
概 观 ∶

----------------------------------------------------------------------
----------

INPUT 标 签 ∶ 
← TYPE: TEXT 
← TYPE: PASSWORD 
这是确定纽1 ← TYPE: CHECKBOX CHECKED 
这是确定纽2 ← TYPE: CHECKBOX 
这是选择纽1 ← TYPE: RADIO CHECKED 
这是选择纽2 ← TYPE: RADIO 
← TYPE: SUBMIT 
← TYPE: RESET 
← TYPE: IMAGE
SELECT 标 签 ∶ 
这是选项1这是选项2这是选项3 
TEXTAREA 标 签 ∶ 
这是文字输入区

----------------------------------------------------------------------
----------

接 下 来 , 我 们 将 依 这 三 大 类 以 及 FORM 的 基 本 标 签 做 介绍 

3-2-1 FORM 标 签 
使 用 格 式 如 下 ∶ 
<FORM METHOD="POST/GET" ACTION="URL"> ... </FORM> 
FORM 这 个 标 签 是 FORM 的 基 本 标 签 , 所 有 与 FORM 有 关 的 标 签
必 须 要 放 在 <FORM> 与 </FORM> 这 标 签 之 内 。 如 果 没 有 将与 FO
RM 有 关 的 标 签 放 在 <FORM> 与 </FORM> 这 个 标 签 之 内, 则 这 些
 标 签 将 不 会 产 生 作 用 。 
FORM 的 参 数 解 释 如 下 ∶ 
· ACTION 是 指 定 当 使 用 者 完 成 输 入 并 将 资 料 传 回 Server 时
, Server 会 将 资 料 送 入 的 位 址 ; 如 果 这 个 参 数 没 有 被 指 
定时 , FORM 所 在 超 本 文 标 示 语 言 (HTML) 文 件 的 URL 将 成 为 内
 定值 。 
· METHOD 是 指 定 使 用 者 输 入 的 资 料 会 以 何 种 方 式 传 回 给 
Server 。 
· GET -- 是 CGI 内 定 的 传 输 方 法 , 使 用 者 输 入 的 资 料 会 以
含 入 URL 的 方 式 传 回 。 
· POST -- 此 种 方 式 有 别 於 GET 将 使 用 者 输 入 的 资 料 含 入 U
RL 的 方 式 。 在 程 式 端 , 资 料 会 以 STDIN 的 方 式 被 接 收 。

· ENCTYPE -- 这 个 参 数 只 有 在 METHOD 被 设 定 为 POST 时 才 会 产
生 作 用 , 其 作 用 是 将 使 用 者 输 入 的 资 料 加 码 传 回 。 
3-2-2 INPUT 标 签 
使 用 格 式 如 下 ∶ 
<INPUT TYPE=TypeName NAME=ValName VALUE=Value> 
其 参 数 如 下 ∶ 
· TYPE -- 设 定 使 用 输 入 的 方 法 。 输 入 的 方 法 一 共 有 下 列
数 种 ∶ 
· TEXT -- 文 字 输 入 区 。 这 是 内 定 值 。 
· PASSWORD -- 基 本 上 和 TEXT 是 相 同 的 。 只 是 专 门 提 供 给 文
件 阅 读 者 输 入 密 码 之 用 。 不 管 输 入 什 么 字 , 在 画 面 上 都
只 能 看 到 「 * 」 这 个 符 号 。 
· CHECKBOX -- 选 择 方 块 , 不 是 ON 就 是 OFF 。 
· RADIO -- 选 择 圆 扭 。 和 CHECKBOX 不 同 的 是 , 选 择 圆 扭 通 常
成 群 出 现 , 并 且 在 这 群 选 项 中 只 能 选 择 其 中 一 个 。 
· SUBMIT -- 也 就 是 按 钮 (Button) 。 文 件 阅 读 者 会 在 画 面 上
看 到 一 个 按 钮 。 一 旦 按 下 这 个 按 钮 , 浏 览 程 式 (Browser)就
会 把 这 个 FORM 上 文 件 使 用 者 所 输 入 的 一 切 资 料 传 回 给 WW
W Server 做 处 理 。 
· RESET -- 它 的 外 观 和 SUBMIT 相 似 , 不 过 一 旦 文 件 阅 读 者 
按下 它 , 这 个 FORM 上 面 的 所 有 输 入 工 具 的 值 都 会 被 清 除 
,或 者 是 回 到 初 始 值 。 
· HIDDEN -- 这 个 TYPE 将 不 会 出 现 在 FORM 上 , 而 是 隐 藏 在 FO
RM 之 下 。 其 目 的 是 为 了 将 使 用 者 不 需 要 知 道 而 程 式 流 程
 上却 需 要 的 资 讯 记 录 在 FORM 上 , 以 便 追 踪 使 用 者 现 在 的
 使用 状 况 。 
· IMAGE -- 在 FORM 上 会 如 IMAGE 标 签 一 样 显 示 图 形 , 其 功 用
和 SUBMIT 一 样 会 将 使 用 者 所 输 入 的 一 切 资 料 传 回 给 WWW Se
rver 。 而 IMAGE 本 身 会 以 滑 鼠 点 下 的 X 和 Y 座 标 传 回 , 这 个
 座 标是 以 图 的 左 上 角 以 原 点 向 右 以 及 向 下 增 加 。 
· NAME -- 定 义 传 回 的 变 数 名 称 。 除 了 SUBMIT 与 RESET 型 态 不
需 NAME 外 , 其 馀 皆 一 定 要 有 , 因 为 如 此 程 式 才 能 分 辨 不
同 的 资 料 。 
· VALUE -- 配 合 不 同 的 TYPE 有 不 同 的 意 义 , 对 TEXT 或 PASSWO
RD 输 入 型 别 而 言 , 是 设 定 输 入 区 域 之 内 定 值 。 对 RADIO 或
 CHECKBOX 也 是 指 定 选 项 之 内 定 值 ( ON 或 是 OFF ) , 不 过 必
 须 连 CHECKED 这 个 参 数 一 起 使 用 才 有 效 。 对 SUBMIT 或 RESET 
输 入 型 别 而 言, 其 VALUE 的 值 将 会 变 成 按 钮 上 的 文 字 。 
· CHECKED -- 前 面 已 提 过 这 个 参 数 只 对 RADIO 或 CHECKBOX 之 输
入 型 别 有 效 , 有 内 定 圈 选 之 意 。 
· SIZE -- 针 对 TEXT 或 PASSWORD 输 入 型 别 , 可 以 定 义 输 入 区 
域的 大 小 , 如 果 没 有 指 定 输 入 区 域 大 小 时 , 则 内 定 的 大
 小为 20 个 英 文 字 元 的 长 度 。 
· MAXLENGTH -- 只 对 TEXT 或 PASSWORD 输 入 型 别 有 效 , 用 来 限 制
文 件 阅 读 者 输 入 字 串 的 最 大 长 度 。 若 没 有 指 定 MAXLENGTH 
大小 , 则 内 定 值 为 无 限 大 。 
· SRC -- 这 个 参 数 只 用 在 IMAGE 中 , 用 来 指 定 所 用 图 形 的 
URL 。 
请 参 见 底 下 的 范 例 ∶

----------------------------------------------------------------------
----------
<H3> <P align=center> 快 捷 线 上 邮 购 公司 杂 志 订 购 服 务 </P> </
H3> 
<Form> 
<P>请 输 入 您 的 会 员 代 号 ∶ 
<INPUT TYPE=TEXT NAME="MemberID" SIZE=10> </P> 
<P>请 输 入 密 码 以 确 认 身 份 ∶ 
<INPUT TYPE=PASSWORD NAME="Password" MAXLENGTH=8> </P> 
<P>请 选 择 您 的 付 款 方 式 ∶ </P>

  1. <INPUT TYPE=RADIO NAME="Pay" VALUE="现 金" CHECKED>现 金
  2. <INPUT TYPE=RADIO NAME="Pay" VALUE="VISA Card" >VISA Card
  3. <INPUT TYPE=RADIO NAME="Pay" VALUE="Master Card" >Master Card

<P>请 选 择 您 要 订 阅 的 杂 志 名 称 ∶ </P>

  1. <INPUT TYPE=CHECKBOX NAME="Magzine" CHECKED>天下
  2. <INPUT TYPE=CHECKBOX NAME="Magzine">远 见
  3. <INPUT TYPE=CHECKBOX NAME="Magzine">中 国生 产 力
  4. <INPUT TYPE=CHECKBOX NAME="Magzine" CHECKED>广告
  5. <INPUT TYPE=CHECKBOX NAME="Magzine">美 丽佳 人
  6. <INPUT TYPE=CHECKBOX NAME="Magzine">哈 泼时 尚

<INPUT TYPE=SUBMIT VALUE="以上资料正确无误"> 
<INPUT TYPE=RESET VALUE="清除刚才所有输入的资料"> 
</Form> 
使 用 浏 览 程 式 (Browser)来 看 看 结 果 ∶

快 捷 线 上 邮 购 公 司 杂 志 订 购 服 务
请 输 入 您 的 会 员 代 号 ∶

请 输 入 密 码 以 确 认 身 份 ∶

请 选 择 您 的 付 款 方 式 ∶

现 金 
VISA Card 
Master Card 
请 选 择 您 要 订 阅 的 杂 志 名 称 ∶ 
天 下 
远 见 
中 国 生 产 力 
广 告 
美 丽 佳 人 
哈 泼 时 尚

----------------------------------------------------------------------
----------

3-2-3 SELECT 标 签 
使 用 格 式 如 下 ∶ 
<SELECT NAME=ValName SIZE=ScrollSize> 
<OPTION SELECTED>选 项 1 
<OPTION>选 项 2 
</SELECT>
这 个 标 签 提 供 下 拉 式 表 单 或 者 是 卷 动 式 表 单 , 让 使 用 者
可 以 从 表 单 中 选 择 一 个 或 多 个 项 目 。 表 单 是 以 <SELECT> 开
 始 , 表 单 中 每 一 个 选 项 以 <OPTION> 开 头 ,最 後 以 </SELECT> 
结 束 这 个 表 单 。 SELECT 标 签 一 定 要 使 用 NAME 参 数 来 定 义 选
项 之 栏 位 名 称 。 
其 参 数 如 下 ∶ 
· SIZE -- 当 SIZE=1 时 , 此 表 单 为 「 卷 动 式 表 单 」 , 大 於 1
 时 则 是 下 拉 式 表 单 。 若 没 有 指 定 SIZE , 则 内 定 值 为 1 。
 
· MULTIPLE -- 当 指 定 此 参 数 时 , 不 管 有 无 指 定 SIZE 参 数 ,
此 表 单 一 定 是 「 卷 动 式 表 单 」 , 并 且 允 许 文 件 阅 读 者 从
表 单 中 一 次 选 取 一 个 以 上 的 选 项 。 
· OPTION 标 签 内 可 以 加 上 参 数 SELECTED , 表 示 此 选 项 为 内 
定值 , 已 经 预 先 被 选 择 了 。 在 一 个 MULTIPLE 表 单 中 可 以 有
 多个 选 项 被 设 为 内 定 值 。 
请 参 考 下 面 的 范 例 ∶

----------------------------------------------------------------------
----------
<H3><P Align=Center> 本 公 司 产 品 介 绍 </P></H3> 
<P>请 选 择 一 个 项 目 以 获 得 进 一 步 说 明 ∶ </P>

<Form>

<SELECT NAME="Product" SIZE=8> 
<OPTION>舒跑运动饮料 
<OPTION SELECTED>伯朗蓝山咖啡 
<OPTION>开喜乌龙茶 
<OPTION>雀巢柠檬茶 
<OPTION>波蜜果菜汁 
<OPTION>黑松沙士 
<OPTION>统一优酪乳 
<OPTION>可口可乐 
<OPTION>义美果茶小站 
</SELECT> 
<P><INPUT TYPE=SUBMIT VALUE="选择完毕"> </P> 
</Form>

结 果 如 下 ∶

本 公 司 产 品 介 绍
请 选 择 一 个 项 目 以 获 得 进 一 步 说 明 ∶

舒跑运动饮料 伯朗蓝山咖啡 开喜乌龙茶 雀巢柠檬茶 波蜜果菜汁 黑松沙士 统
一优酪乳 可口可乐 义美果茶小站

----------------------------------------------------------------------
----------

3-2-4 TEXTAREA 标 签 
使 用 格 式 如 下 ∶ 
<TEXTAREA NAME=ValName ROWS=Number COLS=Number> 
这 文 字 输 入 区 
</TEXTAREA>
这 个 标 签 的 目 的 在 提 供 一 个 多 行 的 输 入 区 域 。 以 <TEXTAR
EA> 开 始 , 以 </TEXTAREA> 结 束 。 这 个 标 签 也 允 许 设 定 内 定 
值, 供 使 用 者 修 改 。 输 入 区 的 大 小 由 ROWS 与 COLS 这 两 个 参
 数决 定 。 例 如 ∶ ROWS=20 COLS=5 表 示 一 个 大 小 为 20 乘 5 的 输
 入区 。 请 参 看 下 列 范 例 ∶

----------------------------------------------------------------------
----------
<Form> 
<P>请 输 入 您 对 本 公 司 的 建 议 ∶ </P> 
<TEXTAREA NAME="InputData" ROWS=15 COLS=40>我 的建 议 是 ∶</TEXTAREA>

<P> 
<INPUT TYPE=SUBMIT VALUE="我写完了"> 
<INPUT TYPE=RESET VALUE="清除重写"> 
</P> 
</Form>

结 果 如 下 ∶

请 输 入 您 对 本 公 司 的 建 议 ∶

我 的 建 议 是 ∶

----------------------------------------------------------------------
----------

当 使 用 者 输 入 的 资 料 送 到 程 式 内 时 , 程 式 会 同 时 接 收 到
 NAME 及 VALUE 的 值 。 但 当 所 使 用 的 FORM 中 有 RADIO 或 SELECT 等
多 选 择 的 资 料 输 入 型 态 时 , 程 式 则 会 接 收 到 同 一 个 NAME
 的 值 会 对 应 到 多 个 VALUE 的 值 。 程 式 可 以 藉 著 这 样 的 特 
性, 分 辨 使 用 者 所 做 的 多 重 选 择 并 加 以 处 理 。 但 是 , SE
LECT 和 RADIO 的 传 回 值 并 不 相 同 。 在 RADIO 中 , 其 值 并 不 是
 FORM 上 所 见 到 的 值 , 而 是 在 VALUE 中 所 设 定 的 值 ; 在 SELE
CT 中 ,则 是 以 OPTION 标 签 之 後 的 值 为 传 回 值 。 也 就 是 说 使
 用 SELECT , 程 式 所 收 到 的 值 和 使 用 者 看 到 的 一 样 ; 使 用
 RADIO 则 可以 设 定 不 同 的 值 , 使 得 使 用 者 可 以 见 到 有 意 义
 的 选 项 ,而 程 式 可 以 以 更 简 单 的 参 数 , 来 处 理 使 用 者 选
 择 的 资 料。 如 果 , 在 RADIO 中 没 有 设 定 VALUE 的 值 , 则 传 回
 的 是 字 串 "on" 。
四 、 CGI 如 何 运 作 ?
4-1 CGI 运 作 流 程 
首 先 在 客 户 端 , 客 户 端 按 下 FORM 上 的 SUBMIT 按 钮 或 是 按 下
链 结 (LINK) , 告 知 浏 览 程 式 (Browser)完 成 输 入 後 。 浏 览 程 
式 (Browser)将 客 户 端 输 入 的 资 讯 传 回 WWW Server , Server 启 动
 指定 的 程 式 并 将 包 装 过 的 参 数 传 入 。 接 著 程 式 依 照 传 入
 的参 数 完 成 指 定 的 工 作 。 如 果 此 时 有 需 要 传 回 结 果 的 话
 ,则 程 式 会 把 结 果 传 回 给 Server , Server 再 传 至 浏 览 程 式
 (Browser),完 成 整 个 运 作 的 流 程 。 下 图 是 CGI 运 作 流 程 的 
示 意 图 ∶

如 果 现 在 要 让 WWW Server 与 其 它 的 系 统 结 合 , 则 程 式 会扮 
演 中 介 的 角 色 , 将 接 收 到 的 参 数 转 换 成 所 要 结 合 系 统能
 识 别 的 形 式 , 并 处 理 其 传 回 的 资 讯 , 再 送 回 至 Server 让
使 用 者 看 到 。 下 图 是 结 合 其 它 系 统 之 後 CGI 运 作 流 程 的 
示意 图 ∶

接 下 来 这 二 张 图 是 以 MicroSoft SQL Server 为 例 , 结 合 WWW Ser
ver 之 後 CGI 运 作 流 程 的 示 意 图 ∶

4-2 CGI 传 递 资 料 的 方 法 
在 CGI 整 个 传 递 资 料 的 过 程 中 , 为 了 要 从 Server 传 递 有 关
输 入 资 料 给 CGI 程 式 ,Server 将 不 同 的 资 料 转 换 为 各 种 环 
境变 数 以 供 CGI 程 式 使 用 。 这 些 环 境 变 数 是 在 Server 执 行 
CGI 程 式 时 被 设 定 。 我 们 在 下 一 小 节 , 将 会 介 绍 各 环 境 
变 数, 在 这 里 我 们 将 重 点 放 在 , CGI 如 何 将 使 用 者 经 FORM
 所 输入 的 资 料 会 被 如 何 处 理 再 送 到 CGI 程 式 中 。 这 是 CGI
 的 关键 所 在 , 有 了 这 项 资 料 才 能 正 确 的 收 到 并 处 理 使 用
 者 输入 的 资 料 。 
在 FORM 中 , 每 一 资 料 输 入 栏 中 必 须 设 定 NAME 之 参 数 。当 资
 料 被 送 出 时 , NAME 参 数 的 值 会 和 其 相 对 应 的 VALUE 参数 之
 值 , 被 转 换 为 "NAME=VALUE" 的 形 式 。 不 同 的 资 料 输 入 栏, 
中 间 会 以 "&" 作 分 隔 , 亦 即 会 形 成 "NAME1=VALUE1&NAME2=VALUE2"
 的 形 式 。 如 果 各 参 数 值 中 间 有 空 白 的 话 会 以 "+" 代 替 ,
 有特 殊 字 元 则 以 "%XX" 代 替 , 其 中 "XX" 为 特 殊 字 元 的 16 进
 位 ASCII 码 。 这 些 特 殊 字 元 包 括 了 "&" 、 "=" 、 中 文 以 及 A
SCII 码 为 128 以 上 的 字 元 。 
资 料 经 过 这 样 的 包 装 後 , 如 果 METHOD 是 设 定 为 POST 的 话,
 资 料 会 以 STDIN 的 方 式 送 入 CGI 程 式 中 ; 如 果 METHOD 是 设定
 为 GET 的 话 , 资 料 会 被 送 入 QUERY_STRING 的 环 境 变 数 中 ,以
 供 程 式 读 取 。 
在 前 面 的 小 节 曾 说 过 , CGI 的 程 式 可 以 用 链 结 的 方 式起 动
 , 此 时 资 料 须 以 上 述 的 方 法 包 装 後 , 加 在 程 式 名 称的 後
 方 , 最 前 面 要 有 一 "?" 符 号 与 程 式 名 称 分 隔 。 以 下 是一 
简 单 的 范 例 ∶ 
<A HREF="/CGI-BIN/TEST?NAME1=AA+BB&NAME2=CC%3DDD">按这里 
接 著 , 我 们 分 别 就 不 同 的 传 输 METHOD 做 出 的 小 范 例 , 来 
比较 不 同 的 METHOD , 在 读 取 环 境 变 数 时 有 何 不 同 ∶ 
<FORM METHOD=POST ACTION="/CGI-BIN/TEST"> 
栏位 #1: <INPUT NAME="NAME1" VALUE="AA BB"><BR> 
栏位 #2: <INPUT NAME="NAME2" VALUE="CC&DD"><p> 
<INPUT TYPE="SUBMIT" VALUE="执行">  
<INPUT TYPE="RESET" VALUE="取消"> 
</FORM> 
以 上 是 以 METHOD POST 的 方 式 传 输 资 料 , 所 应 参 考 的 环 境 变
数 如 下 ∶ 
CONTENT_LENGTH = 25 
CONTENT_TYPE = application/x-www-form-urlencoded 
REQUEST_METHOD = POST 
SCRIPT_NAME = /CGI-BIN/TEST 
上 面 环 境 变 数 中 , 较 值 得 注 意 的 是 CONTENT_LENGTH , 这 个 环
境 变 数 代 表 的 是 输 入 资 料 的 长 度 , 以 供 CGI 程 式 参 考 。 
其计 算 的 方 式 是 以 包 装 过 後 的 实 际 长 度 为 其 值 , 所 以 上
 例的 输 入 资 料 为 "NAME1=AA+BB&NAME2=CC%3DDD" , 长 度 25 个 字 元。
 
接 下 来 , 我 们 看 看 METHOD GET 的 范 例 ∶ 
<FORM METHOD=GET ACTION="/CGI-BIN/TEST"> 
栏位 #1: <INPUT NAME="NAME1" VALUE="AA BB"><BR> 
栏位 #2: <INPUT NAME="NAME2" VALUE="CC&DD"><p> 
<INPUT TYPE="SUBMIT" VALUE="执行">  
<INPUT TYPE="RESET" VALUE="取消"> 
</FORM> 
以 上 是 以 METHOD GET 的 方 式 传 输 资 料 , 所 应 参 考 的 环 境 变
数 如 下 ∶ 
PATH_INFO = /CGI-BIN/TEST 
PATH_TRANSLATED = /document_root/CGI-BIN/TEST 
QUERY_STRING = NAME1=AA+BB&NAME2=CC%3DDD REQUEST_METHOD = GET
由 上 面 的 例 子 可 以 看 出 , 不 同 资 料 的 传 输 方 式 , 所 参 考
的 环 境 变 数 并 不 一 样 。 所 以 程 式 在 发 展 时 , 要 注 意 与 输
入 介 面 上 设 定 的 传 输 方 式 一 致 , 不 同 的 程 式 不 应 该 混 用
, 以 避 免 产 生 不 必 要 的 错 误 。 
4-3 CGI 的 参 数 
在 这 一 小 节 所 列 示 的 环 境 变 数 仅 供 参 考 , 并 不 见 得 会 适
用 於 每 一 个 WWW Server 。 所 以 , 您 在 使 用 这 些 环 境 变 数 时
, 请 先 阅 读 过 您 的 WWW Server 手 册 , 以 免 产 生 不 必 要 的 错
误 ! 
下 列 环 境 变 数 不 是 用 在 特 别 需 求 上 , 而 是 用 在 所 有 的需
 求 上 ∶ 
· GATEWAY_INTERFACE 
此 变 数 是 用 来 传 送 CGI 的 修 订 版 给 Server 。 
格 式 ∶ CGI/revision 
· SERVER_NAME 
此 变 数 是 用 来 传 送 Server 的 名 字 , Domain Name Server, 或 IP 
Address 。 
· SERVER_SOFTWARE 
此 变 数 是 用 来 传 送 Server 的 软 体 名 字 和 版 本 。 
格 式 ∶ name/version
下 面 的 环 境 变 数 是 给 CGI 程 式 专 用 ∶ 
· AUTH_TYPE 
如 果 Server 提 供 使 用 者 查 核 , 而 且 程 式 是 有 保 护 的 。这 是
 一 种 辨 认 使 用 者 身 份 方 法 的 一 种 协 定 。 
· CONTENT_LENGTH 
这 是 使 用 者 输 入 资 料 的 长 度 。 
· CONTENT_TYPE 
这 是 使 用 者 输 入 资 料 的 MIME 型 态 。 
· PATH_INFO 
此 变 数 是 用 来 传 送 来 自 客 户 端 额 外 的 路 径 资 讯 , 换 句话
 说 , 程 式 可 以 藉 著 真 实 的 路 径 , 加 上 路 径 尾 巴 的 额 外资
 讯 来 被 执 行 。 这 额 外 资 讯 传 给 PATH_INFO 。 如 果 它 的 URL 必
 须 先 经 过 CGI 程 式 码 时 , 则 要 由 Server 解 码 。 
· PATH_TRANSLATED 
此 变 数 是 由 Server 提 供 PATH_INFO 的 翻 译 版 本 。 
· QUERY_STRING 
此 变 数 是 传 送 使 用 者 输 入 的 资 料 。 在 任 何 的 版 本 下 不会
 被 解 码 。 只 要 有 使 用 者 输 入 的 资 料 , 此 变 数 就 会 被 设定
 , 不 管 命 令 列 的 解 码 。 
· REMOTE_ADDR 
产 生 请 求 的 远 方 主 机 的 IP 位 址 。 
· REMOTE_HOST 
产 生 请 求 的 远 方 主 机 名 字 。 如 果 Server 没 有 此 资 讯 ,则 设
 定 REMOTE_ADDR , 并 且 不 设 定 此 一 变 数 。 
· REMOTE_IDENT 
如 果 Server 提 供 RFC 931 的 认 证 , 则 这 个 变 数 会 从 远 端 的 S
erver 取 得 使 用 者 名 字 。 这 个 变 数 应 只 使 用 在 限 制 使 用 者
登 录 上 。 
· REMOTE_USER 
如 果 Server 提 供 使 用 者 查 核 , 而 且 程 式 是 有 保 护 的 ,此 变
 数 是 用 来 传 送 想 要 通 过 认 证 的 使 用 者 名 字 。 
· REQUEST_METHOD 
此 变 数 是 用 来 传 送 使 用 那 一 种 方 法 传 输 资 料 , 以 超 本文
 传 输 协 定 (HTTP) 而 言 是 "GET" 、 "POST" 以 及 "HEAD" 三 种 方 法。
 
· SCRIPT_NAME 
被 执 行 的 程 式 实 质 路 径 即 代 表 自 己 的 URL 。 
· SERVER_PORT 
此 变 数 是 用 来 传 送 那 一 个 埠 是 用 来 传 输 要 求 。 
· SERVER_PROTOCOL 
此 变 数 是 用 来 传 送 PROTCOL 的 名 字 和 版 本 。 
格 式 ∶ protocol/revision
除 此 之 外 , 如 果 有 一 行 以 上 的 档 头 (HEADER) 从 客 户 端 接 收
到 , 则 会 被 WWW Server 在 档 头 名 称 前 面 加 上 "HTTP_" 的 开 头 
之後 被 当 成 环 境 变 数 。 在 档 头 中 如 果 有 任 何 "-" 字 元 , 将
 会被 转 成 "_" 字 元 。 另 外 Server 会 除 去 任 何 已 处 理 的 开 头
 ,像 是 Authorization 、 content-type 、 content-length 。 如 果 放 入
 这些 档 头 会 超 过 系 统 环 境 限 制 , Server 会 选 择 去 删 除 全 
部 或一 些 开 头 。
五 、 CGI 的 输 出 介 面
资 料 输 出 是 CGI 流 程 的 最 後 一 部 分 , 由 於 送 出 的 资 料 不 
只一 种 型 态 。 为 了 使 WWW Server 能 够 辨 认 不 同 的 资 料 型 态 
,於 是 在 送 出 资 料 前 , 必 须 先 送 出 特 定 的 额 外 资 讯 以 做
 为辨 的 依 据 。 
接 下 来 , 要 介 绍 的 就 是 这 些 额 外 资 讯 的 格 式 , 以 及 在程
 式 实 作 上 , 如 何 去 达 成 输 入 和 输 出 的 工 作 ! 
5-1 CGI 输 出 格 式 
当 程 式 完 成 工 作 後 , 如 果 要 输 出 资 讯 回 馈 给 使 用 者 , 则
程 式 必 须 将 结 果 以 资 料 流 的 方 式 传 回 给 Server 。 Server 负
责 把 资 料 流 以 超 本 文 传 输 协 定 (HTTP) 的 形 式 包 装 起 来 , 
并利 用 HTTP1 将 资 料 流 转 换 给 客 户 端 的 浏 览 程 式 (Browser)。
 这表 示 , Server 通 常 会 将 需 要 的 超 本 文 传 输 协 定 (HTTP) 档
 头 (HEADER) 加 入 CGI 程 式 输 出 的 结 果 中 。 
输 出 的 资 料 流 中 包 含 两 大 部 份 。 第 一 是 简 短 档 头 , 用来
 告 诉 Server 一 些 和 程 式 执 行 结 果 有 关 的 讯 息 。 第 二 就 是
程 式 执 行 完 的 结 果 , Server 并 不 会 解 译 或 更 改 这 一 部 份 
的资 料 , 也 就 是 客 户 端 的 浏 览 程 式 (Browser)会 完 全 接 收 到
 这一 部 份 的 资 料 。 这 两 个 部 份 之 间 要 有 一 个 以 上 的 空 白
 行作 区 隔 。 
程 式 执 行 完 的 结 果 是 依 您 程 式 目 的 不 同 而 有 不 同 , 而档
 头 却 有 几 种 固 定 的 形 式 。 当 Server 接 到 无 法 认 定 的 档 头
时 会 原 封 不 动 地 送 给 客 户 端 的 浏 览 程 式 (Browser), 所 以 C
GI 程 式 应 避 免 送 出 不 合 超 本 文 传 输 协 定 (HTTP) 标 准 的 档 
头 ,以 免 发 生 错 误 的 动 作 。 
档 头 跟 MIME 或 MAIL 的 开 头 相 似 。 它 包 含 数 行 , 每 一 行代 表
 一 个 项 目 以 及 其 参 数 , 项 目 及 参 数 以 ":" 作 区 隔 。 以下 
是 各 档 头 及 其 介 绍 ∶ 
Content-type: type/subtype 
告 诉 Server 要 输 出 的 资 料 是 属 於 何 种 MIME 型 态 的 资 料 , t
ype/subtype 的 值 必 须 是 MIME 承 认 的 型 态 之 一 。 
举 例 来 说 , 如 果 要 输 出 的 是 超 本 文 标 示 语 言 (HTML) 文件 则
 type/subtype 应 改 为 text/html 。 如 果 要 输 出 的 是 JPEG 标 准的 
图 形 档 , 则 type/subtype 应 改 为 image/jpeg 。 有 关 MIME 的 资料 
请 自 行 参 考 相 关 资 料 。 以 下 有 一 简 单 的 范 例 以 供 参 考 ∶
 
--- 开 始 ---

Content-type: text/html           <== 内 容 的 MIME type

Status: 200 OK <== 超 本 文 传 输 协 定 (HTTP) 状 态
(非 必 要)

<== 档 头 和 内 容 的 分 隔 空 白 行

<HTML>                      <== 内 容 开 始

<HEAD>

<TITLE>范 例 文 件</TITLE>

</HEAD>

<BODY>

<H1>范 例 文 件</H1>

[... etc.]

</BODY>

<HTML>

---  结 束  ---
Status: 
说 明 CGI 执 行 的 况 状 , 其 值 必 须 是 超 本 文 传 输 协 定 (HTTP)
 所 认 可 的 。 如 果 CGI 程 式 传 回 的 结 果 中 , 并 未 包 含 此 一
 档头 的 话 , Server 会 认 定 CGI 已 成 功 的 完 成 了 工 作 , 并 且
 Server 会 自 行 产 生 "200 OK" 的 Status 值 。 关 於 超 本 文 传 输 协
 定 (HTTP) Status 值 的 设 定 , 请 自 行 参 考 相 关 资 料 。 
URI: <value> 
在 两 个 角 括 号 中 间 的 值 可 以 是 完 整 的 URL , 或 是 相 对 位 
址指 向 某 一 档 案 , 则 这 一 档 案 的 内 容 将 会 取 代 CGI 程 式 输
 出的 结 果 。 如 果 值 是 区 域 性 的 档 案 , Server 会 将 档 案 内 
容 直接 送 到 客 户 端 。 如 果 是 完 整 的 URL 则 Server 传 回 "401 r
edirect" 的 讯 息 , 让 浏 览 程 式 (Browser)自 行 抓 取 指 定 的 档 案
 。 
Locantion: 
与 URI 同 , 但 其 後 之 值 不 必 在 角 括 号 中 间 。 以 下 是 一 简 
短范 以 供 参 考 ∶ 
--- 开 始 ---

Location: http://crc.yzit.edu.tw/intro.htm         <== 指 定 之 URL

<== 空 白 行

--- 结 束 ---
如 果 CGI 程 式 所 送 出 的 结 果 不 希 望 经 过 Server 的 包 装 , 而
希 望 直 接 送 到 客 户 端 的 浏 览 程 式 (Browser), 则 程 式 必 须 负
责 送 出 完 整 的 超 本 文 传 输 协 定 (HTTP) 讯 息 封 包 (Message Pac
kaged) 。 当 Server 收 到 CGI 程 式 输 出 的 结 果 时 , 会 先 检 查 是
否 有 "HTTP/1.0" 的 讯 息 。 如 果 有 则 Server 会 认 为 以 下 的 讯
息 已 经包 含 了 完 整 的 超 本 文 传 输 协 定 (HTTP) 回 应 , 并 将 其
直 接 送至 客 户 端 的 浏 览 程 式 (Browser)。 以 下 是 一 简 短 的 范
例 ∶
--- 开 始 ---

HTTP/1.0 200 OK <== 超 本 文 传 输 协 定 (HTTP) 档 头
开 始

Date: Tuesday, 31-May-94 19:04:30 GMT

Server: WebSite 2.0

MIME-version: 1.0

Content-type: text/html

Last-modified: Sunday, 15-May-94 02:12:32 GMT

Content-length: 4109

<== 档 头 和 内 容 的 分 隔 空 白 行

<HTML> <HEAD>

<TITLE>范 例 文 件</TITLE>

[... etc.]

--- 结 束 ---
5-2 基 本 程 式 范 例 
在 程 式 的 实 作 上 , 第 一 步 是 要 先 读 取 环 境 变 数 REQUEST_ME
THOD 的 值 , 以 分 辨 资 料 传 输 的 方 式 。 接 著 是 依 不 同 传 输
 方 式, 接 收 使 用 输 入 资 料 ━ POST METHOD 以 STDIN 的 方 式 读 入
 资 料; GET METHOD 则 从 环 境 变 数 QUERY_STRING 中 读 取 客 户 端 输
 入 的资 料 。 第 三 步 是 将 这 个 包 装 过 的 资 料 以 反 方 向 拆 解
 开 ,分 别 置 入 不 同 的 变 数 中 。 在 处 理 过 这 些 变 数 和 完 成
 所 要的 工 作 之 後 , 输 出 资 料 回 馈 给 使 用 者 , 是 程 式 流 程
 上 的最 後 一 个 步 骤 。 输 出 的 资 依 上 一 小 节 所 介 绍 的 格 式
 以 STDOUT 的 方 式 送 出 後 , 程 式 到 此 之 後 可 以 算 是 大 功 告
 成 ! 下 面是 CGI 程 式 流 程 的 简 单 示 意 图 ∶

以 下 是 不 同 程 式 语 言 如 何 接 收 使 用 者 输 入 的 资 料 并 且输
 出 的 简 单 范 例 以 及 接 收 资 料 的 FORM ∶

----------------------------------------------------------------------
----------

输 入 栏 1:  
输 入 栏 2:  
 

----------------------------------------------------------------------
----------

以 上 的 FORM 并 未 指 定 其 METHOD 以 及 ACTION , 乃 因 以 下 的 范例
 包 含 两 种 METHOD 之 故 。 
执 行 的 结 果 如 下 ∶

----------------------------------------------------------------------
----------

查 询 结 果
您 输 入 的 查 询 值 如 下 ∶ 
Input1 = ABCD 
Input2 = EFGH

----------------------------------------------------------------------
----------

5-2-1 Perl 
在 这 一 小 节 为 您 示 范 的 是 Perl 的 程 式 。 虽 然 , 在 本 章 的
重 点 是 以 C 语 言 为 主 干 , 但 Perl 的 程 式 由 於 处 理 档 案 时 
较 C 语 言 简 洁 且 为 直 译 式 语 言 , 所 以 在 CGI 中 有 极 为 广 泛
 的应 用 。 是 故 , 我 们 增 加 了 Perl 的 范 例 , 让 您 可 以 对 如
 何用 Perl 来 写 CGI 有 初 步 的 认 识 ! 
这 个 程 式 主 要 的 目 的 是 接 收 并 且 输 出 资 料 。 接 著 我 们就
 开 始 逐 步 介 绍 程 式 中 的 重 点 部 分 。 首 先 我 们 看 的 是 利用
 STDOUT 输 出 档 头 , 告 知 Server 何 种 内 容 将 会 送 出 ∶ 
print "Content-type: text/html/n/n";
从 上 面 的 程 式 可 看 出 , 程 式 接 著 要 输 出 的 内 容 将 会 是 超
本 文 标 示 语 言 (HTML) 的 文 件 。 事 实 上 , 档 头 的 输 并 不 一 
定要 放 在 程 式 的 开 头 处 , 但 一 定 要 在 内 容 输 出 前 , 这 点
 请特 别 注 意 。 而 且 , 在 看 看 这 一 行 程 式 的 最 後 有 两 个 "
/n" 符 号 , 为 的 是 要 再 加 上 一 行 空 白 , 以 便 和 接 著 输 出 
的 内容 做 区 隔 ! 
输 出 档 头 之 後 是 辨 认 传 输 的 方 式 以 及 读 入 使 用 者 输 入的
 资 料 ∶ 
if ($ENV{'REQUEST_METHOD'} eq "POST") {
   read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
} elsif ($ENV{'REQUEST_METHOD'} eq "GET") {
   $buffer=$ENV{'QUERY_STRING'};
}
读 者 可 以 由 上 方 的 程 式 中 看 出 , 不 同 的 METHOD 读 取 使 用 
者输 入 资 料 的 方 式 并 不 相 同 , 请 勿 混 用 ! 
完 成 了 资 料 读 取 的 动 作 之 後 , 接 下 来 则 是 重 头 戏 ━ 分解
 资 料 。 
@pairs = split(/&/, $buffer);

foreach $pair (@pairs)                  
{
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
   $A{$name} = $value;
   print "

  • <code>$name = $value</code>/n/n";
    }
    事 实 上 , 本 范 例 并 未 将 不 同 的 资 料 置 入 不 同 的 变 数 中 ,
    而 是 直 接 输 出 。 如 果 您 想 要 对 资 料 做 进 一 步 的 处 理 , 可
    以 将 程 式 加 以 修 改 、 扩 充 。 请 注 意 , 在 输 出 变 数 之 前 已
    先 输 出 部 分 的 超 本 文 标 示 语 言 (HTML) 文 件 的 内 容 。 
    print "<H1>查 询 结 果</H1>";           
    print "您 输 入 的 查 询 值 如 下 ∶ <p>/n";
    print "

      • /n";

        @pairs = split(/&/, $buffer);

        foreach $pair (@pairs)                  
        {
           ($name, $value) = split(/=/, $pair);
           $value =~ tr/+/ /;
           $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
           $A{$name} = $value;
           print "

      • <code>$name = $value</code>/n/n";
        }

        print "

      • %c",10);

        for(x=0; x <= m; x++)
        printf("

      • <code>%s = %s</code>%c",entries[x].name,
                   entries[x].val,10);
        printf("
      • %c",10);

        for(x=0; x <= m; x++)
        printf("

      • <code>%s = %s</code>%c",entries[x].name,
                       entries[x].val,10);
            printf("
      • %c",10);

        for(x=0; x <= m; x++)
        printf("

      • <code>%s = %s</code>%c",entries[x].name,
                       entries[x].val,10);
            printf("
    • /n";
      由 上 可 见 , 用 程 式 输 出 超 本 文 标 示 语 言 (HTML) 文 件 和 一 
      般建 立 超 本 文 标 示 语 言 (HTML) 的 格 式 并 无 差 异 , 不 同 的 只
       是建 立 者 是 人 与 程 式 的 分 别 ! 
      以 下 是 完 整 的 程 式 列 表 ∶

      ----------------------------------------------------------------------
      ----------

      #!/usr/local/bin/perl 
      $| = 1;  
      print "Content-type: text/html/n/n";

      if ($ENV{'REQUEST_METHOD'} eq "POST") {          
         read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
      } elsif ($ENV{'REQUEST_METHOD'} eq "GET") {
         $buffer=$ENV{'QUERY_STRING'};
      }

      print "<H1>查 询 结 果</H1>";           
      print "您 输 入 的 查 询 值 如 下 ∶ <p>/n";
      print " /n"

      ----------------------------------------------------------------------
      ----------

      上 面 的 程 式 是 一 个 「 麻 雀 虽 小 , 五 脏 俱 全 」 的 程 式 。只
       要 将 其 适 当 的 位 置 加 上 所 需 的 程 式 就 可 以 达 到 预 定 的功
       能 , 相 信 能 对 您 有 所 助 益 。

      5-2-2 C for POST METHOD 
      C 语 言 ━ 本 节 的 主 角 登 场 ! 这 是 一 个 使 用 C 语 言 以 接 收 
      POST METHOD 为 目 的 的 CGI BACKEND 程 式 。 就 如 同 上 面 的 范 例 ,
       虽 然只 是 简 单 的 输 出 使 用 者 输 入 的 资 料 。 但 经 过 改 造 之
       後 ,功 能 将 不 可 同 日 而 语 ! 现 在 就 让 我 们 开 始 逐 步 分 解
       程 式的 内 容 。 
      一 开 始 我 们 看 到 的 是 档 头 的 输 出 , 如 同 上 一 个 范 例 。

      printf("Content-type: text/html%c%c",10,10);
      同 样 的 , 我 们 也 可 以 见 到 在 这 一 行 程 式 的 尾 端 送 出 了 两
      个 ASCII 码 为 10 的 字 元 , 来 产 生 与 输 出 内 容 分 隔 的 空 白 行
      。 
      if(strcmp(getenv("REQUEST_METHOD"),"POST")) {              
          printf("This script should be referenced with a METHOD of POST./n"
      );
          exit(1);
      }
      if(strcmp(getenv("CONTENT_TYPE"),"application/x-www-form-urlencoded"))
       {  
          printf("This script can only be used to decode form results. /n");

      exit(1);
      }
      这 段 程 式 是 辨 认 传 输 的 方 式 。 因 为 这 范 例 程 式 只 做 为 单
      一 传 输 方 式 使 用 , 是 故 和 上 一 个 范 例 有 些 许 的 差 距 。

      for(x=0;cl && (!feof(stdin));x++) {                      
          m=x;
          entries[x].val = fmakeword(stdin,'&',&cl);
          plustospace(entries[x].val);
          unescape_url(entries[x].val);
          entries[x].name = makeword(entries[x].val,'=');
      }
      接 下 来 的 程 式 就 是 读 入 使 用 者 输 入 的 资 料 , 及 将 使 用 者
      输 入 的 资 料 拆 解 开 。 注 意 ! 这 个 范 例 是 将 资 料 分 别 置 入
      不 同 的 阵 列 元 素 中 , 与 上 一 个 例 子 并 不 相 同 。 
      printf("<H1>查 询 结 果</H1>");               
      printf("您 输 入 的 查 询 值 如 下 ∶ <p>%c",10);
      printf(" %c",10);
      到 了 这 里 就 是 程 式 的 最 後 一 部 分 ━ 输 出 回 的 资 讯 。 
      以 下 是 完 整 的 程 式 列 表 ∶

      ----------------------------------------------------------------------
      ----------

      #include <stdio.h>
      #include <stdlib.h>
      #define MAX_ENTRIES 50
      #define LF 10
      #define CR 13

      typedef struct {
          char *name;
          char *val;
      } entry;

      char *makeword(char *line, char stop);
      char *fmakeword(FILE *f, char stop, int *len);
      char x2c(char *what);
      void unescape_url(char *url);
      void plustospace(char *str);

      main(int argc, char *argv[]) {
          entry entries[MAX_ENTRIES];
          register int x,m=0;
          int cl;

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

      if(strcmp(getenv("REQUEST_METHOD"),"POST")) {              
              printf("This script should be referenced with a METHOD of POST
      ./n");
              exit(1);
          }
          if(strcmp(getenv("CONTENT_TYPE"),"application/x-www-form-urlencode
      d")) {  
              printf("This script can only be used to decode form results. /
      n");
              exit(1);
          }
          cl = atoi(getenv("CONTENT_LENGTH"));

      for(x=0;cl && (!feof(stdin));x++) {                      
              m=x;
              entries[x].val = fmakeword(stdin,'&',&cl);
              plustospace(entries[x].val);
              unescape_url(entries[x].val);
              entries[x].name = makeword(entries[x].val,'=');
          }

      printf("<H1>查 询 结 果</H1>");               
          printf("您 输 入 的 查 询 值 如 下 ∶ <p>%c",10);
          printf(" %c",10);

      }

      char *makeword(char *line, char stop) {
          int x = 0,y;
          char *word = (char *) malloc(sizeof(char) * (strlen(line) + 1));

      for(x=0;((line[x]) && (line[x] != stop));x++)
              word[x] = line[x];

      word[x] = '/0';
          if(line[x]) ++x;
          y=0;

      while(line[y++] = line[x++]);
          return word;
      }

      char *fmakeword(FILE *f, char stop, int *cl) {
          int wsize;
          char *word;
          int ll;

      wsize = 102400;
          ll=0;
          word = (char *) malloc(sizeof(char) * (wsize + 1));

      while(1) {
              word[ll] = (char)fgetc(f);
              if(ll==wsize) {
                  word[ll+1] = '/0';
                  wsize+=102400;
                  word = (char *)realloc(word,sizeof(char)*(wsize+1));
              }
              --(*cl);
              if((word[ll] == stop) || (feof(f)) || (!(*cl))) {
                  if(word[ll] != stop) ll++;
                  word[ll] = '/0';
                  return word;
              }
              ++ll;
          }
      }

      char x2c(char *what) {
          register char digit;

      digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] -
       '0'));
          digit *= 16;
          digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] 
      - '0'));
          return(digit);
      }

      void unescape_url(char *url) {
          register int x,y;

      for(x=0,y=0;url[y];++x,++y) {
              if((url[x] = url[y]) == '%') {
                  url[x] = x2c(&url[y+1]);
                  y+=2;
              }
          }
          url[x] = '/0';
      }

      void plustospace(char *str) {
          register int x;

      for(x=0;str[x];x++) if(str[x] == '+') str[x] = ' ';
      }

      ----------------------------------------------------------------------
      ----------

      5-2-3 C for GET METHOD 
      本 节 的 最 後 一 个 范 例 是 以 C 语 言 做 一 个 接 收 GET METHOD 资 
      料的 简 单 范 例 。 基 本 上 , 这 个 范 例 与 上 一 个 范 例 没 有 太
       多的 差 异 , 主 要 的 目 的 是 让 您 比 较 在 C 语 言 中 , 这 两 种
       传输 方 式 在 程 式 写 法 上 有 何 不 同 。 以 下 只 就 有 差 异 的 部
       分作 介 绍 。 
      if(strcmp(getenv("REQUEST_METHOD"),"GET")) {              
          printf("This script should be referenced with a METHOD of GET./n")
      ;
          exit(1);
      }

      cl = getenv("QUERY_STRING");                      
      if(cl == NULL) {
          printf("No query information to decode./n");
          exit(1);
      }
      这 段 程 式 最 大 的 差 异 在 读 取 资 料 是 从 QUERY_STRING 取 得 , 
      而非 从 STDIN 取 得 。 
      for(x=0;cl[0] != '/0';x++) {                      
          m=x;
          getword(entries[x].val,cl,'&');
          plustospace(entries[x].val);
          unescape_url(entries[x].val);
          getword(entries[x].name,entries[x].val,'=');
      }
      再 者 , 是 分 解 资 料 时 使 的 函 式 有 所 不 同 。 但 这 并 不 会 影
      向 程 式 的 执 行 , 因 为 两 个 范 例 所 附 的 函 式 都 是 独 立 的 。
      且 这 些 程 式 都 已 确 认 过 可 执 行 , 只 要 不 更 动 函 式 部 分 程
      式 就 可 以 正 常 的 执 行 。 
      以 下 是 完 整 的 程 式 列 表 ∶

      ----------------------------------------------------------------------
      ----------

      #include <stdio.h>
      #include <stdlib.h>

      typedef struct {
          char name[128];
          char val[128];
      } entry;

      void getword(char *word, char *line, char stop);
      char x2c(char *what);
      void unescape_url(char *url);
      void plustospace(char *str);

      main(int argc, char *argv[]) {
          entry entries[50];
          register int x,m=0;
          char *cl;

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

      if(strcmp(getenv("REQUEST_METHOD"),"GET")) {              
              printf("This script should be referenced with a METHOD of GET.
      /n");
              exit(1);
          }

      cl = getenv("QUERY_STRING");                      
          if(cl == NULL) {
              printf("No query information to decode./n");
              exit(1);
          }
          for(x=0;cl[0] != '/0';x++) {                      
              m=x;
              getword(entries[x].val,cl,'&');
              plustospace(entries[x].val);
              unescape_url(entries[x].val);
              getword(entries[x].name,entries[x].val,'=');
          }

      printf("<H1>查 询 结 果</H1>");               
          printf("您 输 入 的 查 询 值 如 下 ∶ <p>%c",10);
          printf(" %c",10);
      }

      void getword(char *word, char *line, char stop) {
          int x = 0,y;

      for(x=0;((line[x]) && (line[x] != stop));x++)
              word[x] = line[x];

      word[x] = '/0';
          if(line[x]) ++x;
          y=0;

      while(line[y++] = line[x++]);
      }

      char x2c(char *what) {
          register char digit;

      digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] -
       '0'));
          digit *= 16;
          digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] 
      - '0'));
          return(digit);
      }

      void unescape_url(char *url) {
          register int x,y;

      for(x=0,y=0;url[y];++x,++y) {
              if((url[x] = url[y]) == '%') {
                  url[x] = x2c(&url[y+1]);
                  y+=2;
              }
          }
          url[x] = '/0';
      }

      void plustospace(char *str) {
          register int x;

      for(x=0;str[x];x++) if(str[x] == '+') str[x] = ' ';
      }

CGI 程 式 设 计相关推荐

  1. C 语 言 程 序 设 计 --国王的许诺

    国际象棋盘上共有64个格子,设想在象棋盘上放麦子.在第1个格子中放1粒,第2个格子中放2粒,第3个格子中放4粒,以后每一格都比前一格增加1倍,依此放完棋盘上的64个格子.请分别采用两种累加方法(直接计 ...

  2. 大 话 设 计 模 式

    大 话 设 计 模 式    从拿到这本书的那一刻,就很喜欢这本书.这本书的排版,编辑模式就是相当的吸引人,它是以对话的形式.以故事的形式.以生活中很常见的通俗的例子引入入胜的,跟其他的书教程大有不同 ...

  3. 卧式储罐液位体积计算公式excel_ELL外测式液位计在氢氟酸储罐上的实际应用

    1 引言 安全环境保护已经越来越受到人们的重视,我们在发展化工生产的同时,也将安全环境保护列为一项重要的基本方针,在氢氟酸储罐的液位测量中,有选用双法兰液位变送器.雷达液位计.浮球液位计等,但这些仪表 ...

  4. WK型振弦式应变计混凝土变形监测

    一种用振弦来进行测量的应变传感器,其最大的优点是传感器结构简单,工作可靠,输出信号为标准的频率信号,非常方便计算机处理或代手段的电路调理. 河北稳控科技WK型振弦式应变计广泛适用于长期埋设在水工建筑物 ...

  5. 拉绳式位移计用于山体滑坡裂缝中

    拉绳式位移计用于山体滑坡裂缝中 拉绳式位移计对滑坡裂缝进行持续监测,而滑坡处往往山高林密,落差较大,存在较大的干扰.当需要对落差较大滑坡处裂缝进行监测时,需要在滑坡处装入拉绳式位移计,并沿滑坡拉一条拉 ...

  6. GEO振弦式钢筋计适用范围

    适用范围 钢筋计:用于监测岩土工程混凝土建筑物的应力,适用于长期埋设在水工建筑物或其他建 筑物内部,测量结构物内部的钢筋应力. 锚杆应力计:钢筋计用于测量锚杆应力时,成为锚杆应力计.装上锚杆应力计的锚 ...

  7. 磁致式量水堰计怎么安装?应用方向有哪些?

    1.设备介绍: 磁致式量水堰计是采用磁致伸缩原理制造的高精度.长量程线性.绝对位置测量的液位传感器,可以精确测量水体液面的位置. 2.应用方向: 本设备与量水堰槽配用使用,适用于长期测量河流.湖泊.水 ...

  8. 放大镜 讲课_《 放 大 镜 》教 学 设 计

    (教科版)六年级科学下册第一单元 1.< 放 大 镜 >教 学 设 计 新泉中心小学 张炎祥 一.教材简析: 教科书分三部分: 第一部分:为什么要用放大镜观察:先是让学生回忆科学课学习中放 ...

  9. GEO振弦式钢筋计的组装

    (1)按钢筋直径选配相应的钢筋计,如果规格不符合,应选择尽量接近于结构钢筋直径 的钢筋计,例如:钢筋直径为 Ø35mm,可使用 NZR-36 或 NZR-32 的钢筋计,此时仪器的最小 读数应进行修正 ...

最新文章

  1. element select 不回显_Jsoup中Element对象的使用
  2. Android -----ArrayAdapter的重写 .
  3. 环信快速集成,以及实际集成中遇到的坑
  4. [codility]Min-abs-sum
  5. Java多线程同步Synchronized使用分析
  6. For web.config setting,reference the book of
  7. php 获取所有子目录名,php读取目录及子目录下所有文件名的方法,_PHP教程
  8. [测试技术分享]easyFuzzer使用案例分享
  9. 2019斯坦福CS224n深度学习自然语言处理笔记(1)Word2Vec与Glove
  10. 基于PCA的特征提取
  11. OCS 2007 R2搭建准备虚机及快照
  12. 计算机博弈大赛源代码,2020计算机博弈大赛幻影围棋分组第一天 信息交互模块...
  13. HRD 必须了解的持续绩效的优势
  14. python 处理excel公式_python 处理excel踩过的坑——data_only,公式全部丢失
  15. [win7 百度网盘] 登录安全验证显示空白页
  16. 目前是大专学历如何快速提升到本科学历?学历提升有哪几种形式呢?
  17. 离散数学复习--集合的势证明
  18. 怎样删除*.sys文件
  19. 百度之星2017资格赛1003 度度熊与邪恶大魔王
  20. javascript中this指向问题(es5)

热门文章

  1. 《从0到1:CTFer成长之路》粗心的小李
  2. 北京艾德思奇科技有限公司面试实录
  3. 正值找工作的好时光,来看看这份精心准备的面试总结吧
  4. java开发C语言编译器:把C实现的快速排序算法编译成jvm字节码
  5. 软件与程序的定义和关系
  6. 月球应该是人工制造的
  7. ElasticSearch学习(三)——Windows集群部署
  8. 电脑常用快捷键汇总!电脑小白们快来
  9. 利用ajax无刷新验证注册信息
  10. 快充协议、接口类型、接口协议的介绍