物联网网关Web服务器--CGI开发接口

1、CGI(公用网关接口)

CGI(公用网关接口)规定了 Web 服务器调用其他可执行程序(CGI 程 序)的接口协议标 准。Web 服务器通过调用 CGI 程序实现和 Web 浏览器的交互,也就是 CGI 程序接受 Web 浏览 器发送给 Web 服务器的信息,进行处理,将响应结果再回送给 Web 服务器及 Web 浏览器。CGI 程序一般完成 Web 网页中表单(Form)数据的处理、数据库查询和实现与传统应用系统的集成 等工作。CGI 程序可以用任何程序设计语言编写,如 Shell 脚本语言、Perl、Fortran、Pascal、 C 语言等。但是用 C 语言编写的 CGI 程序具有执行速度快、安全性高(因为 C 语言程序是编译执行且不可被修改等特点。

WWW 和 CGI 的工作原理 HTTP 协议是 WWW 的基础,它基于客户/服务器模型,一个 服务器可以为分布在网络中处的客户提供服务;它是建立在 TCP/IP 协议之上的“无连接”协 议,每次连接只处理一个请求。在服务器上,运行产着一个守护进程对端口进行监听,等待 来自客户的请求。当一个请求到来时,将创建一个子进程为用户的连接服务。根据请求的不 同,服务器返回 HTML 文件或者通过 CGI 调用外部应用程序,返回处理结果。 服务器通过 CGI 与外部程序和脚本之间进行交互,根据客户端在进行请求时所采取的 方法,服务器会收集客户所提供的信息,并将该部分信息发送给指定的 CGI 扩展程序。CGI 扩展程序进行信息处理并将结果返回服务器,然后服务器对信息进行分析,并将结果发送回 客户端。

外部 CGI 程序与 WWW 服务器进行通信、传递有关参数和处理结果是通过环境变量、 命令行参数和标准输入来进行的。服务器提供了客户端(浏览器)与 CGI 扩展程序之间的 信息交换的通道。CGI的标准输入是服务器的标准输出,而 CGI 的标准输出是服务器的标 准输入。客户的请求通过服务器的标准输出传送给 CGI 的标准输入,CGI 对信息进行处理 后,将结果发送到它的标准输入,然后由服务器将处理结果发送给客户端。

2、CGI接口

CGI接口标准包括标准输入、环境变量、标准输出三部分。

1.标准输入 CGI 程序像其他可执行程序一样,可通过标准输入(stdin)从 Web 服务器得到输入信息, 如 Form 中的数据,这就是所谓的向 CGI 程序传递数据的 POST 方法。这意味着在操作系统命 令行状态可执行 CGI 程序,对 CGI 程序进行调试。POST 方法是常用的方法,本文将以此方法 为例,分析 CGI 程序设计的方法、过程和技巧。

2.环境变量

操作系统提供了许多环境变量,它们定义了程序的执行环境,应用程序可以存取它们。 Web 服务器和 CGI 接口又另外设置了自己的一些环境变量,用来向 CGI 程序传递一些重要的 参数。CGI 的 GET 方法还通过环境变量 QUERY-STRING 向 CGI 程序传递 Form 中的数据。

3.标准输出 CGI 程序通过标准输出(stdout)将输出信息传送给 Web 服务器。传送给 Web 服务器的信 息可以用各种格式,通常是以纯文本或者 HTML 文本的形式,这样我们就可以在命令行状态调 试 CGI 程序,并且得到它们的输出。

3、简单的 CGI 程序

下面是一个简单的 CGI 程序,它将 HTML 中 Form 的信息直接输出到 Web 浏览器。

#include 
#include 
main()
{
int,i,n;
printf (″Contenttype:text/plain\n\n″);
n=0;
if(getenv(″CONTENT-LENGTH″))
n=atoi(getenv(CONTENT-LENGTH″));
for (i=0;i

下面对此程序作一下简要的分析。

printf (″Contenttype:text/plain\n\n″);

此行通过标准输出将字符串″Contenttype:text/plain\n\n″传送给 Web 服务器。它是 一个 MIME 头信息,它告诉 Web 服务器随后的输出是以纯 ASCII 文本的形式。请注意在这个头 信息中有两个新行符,这是因为 Web 服务器需要在实际的文本信息开始之前先看见一个空 行。

if(getenv(″CONTENT-LENGTH″))
n=atoi(getenv(CONTENT-LENGTH″));

此行首先检查环境变量 CONTENT-LENGTH 是否存在。Web 服务器在调用使用 POST 方法的 CGI 程序时设置此环境变量,它的文本值表示 Web 服务器传送给 CGI 程序的输入中的字符数 目,因此我们使用函数 atoi() 将此环境变量的值转换成整数,并赋给变量 n。请注意 Web 服 务器并不以文件结束符来终止它的输出,所以如果不检查环境变量 CONTENT-LENGTH,CGI 程 序就无法知道什么时候输入结束了。

for (i=0;i

此行从 0 循环到(CONTENT-LENGTH-1)次将标准输入中读到的每一个字符直接拷贝到标准输出,也就是将所有的输入以 ASCII 的形式回送给 Web 服务器。

通过此例,我们可将 CGI 程序的一般工作过程总结为如下几点。

1. 通过检查环境变量 CONTENT-LENGTH,确定有多少输入;

2. 循环使用 getchar()或者其他文件读函数得到所有的输入;

3. 以相应的方法处理输入;

4. 通过″Contenttype:″头信息,将输出信息的格式告诉 Web 服务器;

5. 通过使用 printf()或者 putchar()或者其他的文件写函数,将输出传送给 Web 服务 器。

总之,CGI 程序的主要任务就是从 Web 服务器得到输入信息,进行处理,然后将输出结果 再送回给 Web 服务器。

4、环境变量

环境变量是文本串(名字/值对),可以被 OS Shell 或其他程序设置 ,也可以被其他程序 访问。它们是 Web 服务器传递数据给 CGI 程序的简单手段,之所以称为环境变量是因为它们 是全局变量,任何程序都可以存取它们。

下面是 CGI 程序设计中常常要用到的一些环境变量。

  • HTTP-REFERER:调用该 CGI 程序的网页的 URL。

  • REMOTE-HOST:调用该 CGI 程序的 Web 浏览器的机器名和域名。

  • REQUEST-METHOD:指的是当 Web 服务器传递数据给 CGI 程序时所采用的方法,分为 GET 和 POST 两种方法。

  • GET 方法仅通过环境变量(如 QUERY-STRING)传递数据给 CGI 程序, 而 POST 方法通过环境变量和标准输入传递数据给 CGI 程序,因此 POST 方法可较方便地 传递较多的数据给 CGI 程序。

  • SCRIPT-NAME:该 CGI程序的名称。

  • QUERY-STRING:当使用 POST 方法时,Form 中的数据最后放在 QUERY-STRING 中,传递给 CGI 程序。

  • CONTENT-TYPE: 传 递 给 CGI 程 序 数 据 的 MIME 类 型 , 通 常 为 ″ applica tion/x-www-form-url encodede″,它是从 HTML Form 中以 POST 方法传递数据给 CGI 程序的数据编码类型,称为 URL 编码类型。

  • CONTENT-LENGTH:传递给 CGI 程序的数据字符数(字节数)。 在 C 语言程序中,要访向环境变量,可使用 getenv()库函数。

例如:

if (getenv (″CONTENT-LENGTH″)) 
n=atoi(getenv (″CONTENT-LENGTH″)); 

请注意程序中最好调用两次 getenv():第一次检查是否存在该环境变量,第二次再使用 该环境变量。这是因为函数 getenv()在给定的环境变量名不存在时,返回一个 NULL(空)指针, 如果你不首先检查而直接引用它,当该环境变量不存在时会引起 CGI 程序崩溃。

5、分析名字/值对

当用户提交一个 HTML Form 时,Web 浏览器首先对 Form 中的数据以名字/值对的形式进行编码,并发送给 Web 服务器,然后由 Web 服务器传递给 CGI 程序。

其格式如下:

name1=value1&name2=value2&name3=value3&name4=value4&... 

其中名字是 Form 中定义的 INPUT、SELECT 或 TEXTAREA 等标置(Tag)名字,值是用户输入 或选择的标置值。这种格式即为 URL 编码,程序中需要对其进行分析和解码。要分析这种数 据流,CGI 程序必须首先将数据流分解成一组组的名字/值对。这可以通过在输入流中查找下面的两个字符来完成。

每当找到字符=,标志着一个 Form 变量名字的结束;每当找到字符& ,标志着一个 Form 变量值的结束。请注意输入数据的最后一个变量的值不以&结束。一旦名字/值对分解后,还必须将输入中的一些特殊字符转换成相应的 ASCII 字符。

这些特殊字符是:

  • +:将+转换成空格符;

  • %xx:用其十六进制 ASCII 码值表示的特殊字符。

根据值 xx 将其转换成相应的 ASCII 字 符。对 Form 变量名和变量值都要进行这种转换。下面是一个对 Form 数据进行分析并将结果 回送给 Web 服务器的 CGI 程序。

#include 
#include 
#include 
int htoi(char *);
main()
{
 int i,n;
char c;
printf (″Contenttype: text/plain\n\n″);
n=0;
if (getenv(″CONTENT-LENGTH″))
n=atoi(getenv(″CONTENT-LENGTH″));
for (i=0; i

上面的程序首先输出一个 MIME 头信息给 Web 服务器,检查输入中的字符数,并循环检查 每一个字符。当发现字符为&时,意味着一个名字/值对的结束,程序输出一个空行;当发现字 符为+时,将它转换成空格; 当发现字符为%时,意味着一个两字符的十六进制值的开始,调用 htoi()函数将随后的两个字符转换为相应的 ASCII 字符;当发现字符为=时,意味着一个名字 /值对的名字部分的结束,并将它转换成字符:。最后将转换后的字符输出给 Web 服务器。

6、产生 HTML 输出

CGI 程序产生的输出由两部分组成:MIME 头信息和实际的信息。两部分之间以一个空行 分开。我们已经看到怎样使用 MIME 头信息″Cont enttype:text/plain\n\n″和 printf()、 put char()等函数调用来输 出纯 ASCII 文本给 Web 服务器。实际上,我们也可以使用 MIME 头信息″C ontenttype:text/html\n\n″来输出HTML 源代码给 Web服务器。请注意任何MIME 头信息后必须有一个空行。一旦发送这个 MIME 头信息给 Web 服务器后,Web 浏览器将认为随 后的文本输出为HTML 源代码,在HTML 源代码中可以使用任何 HTML结构,如超链、图像、Form, 及对其他 CGI 程 序的调用。也就是说,我们可以在 CGI 程序中动态产生 HTML 源代码输出 , 下面是一个简单的例子。

#include 
#include 
main(){
printf(″Contenttype:text/html\n\n″);
printf(″\n″);
printf(″An HTML Page From a CGI\n″);
printf(″
\n″); printf(″

This is an HTML page generated from with i n a CGI program.. .

\n ″); printf(″

\n″); printf( ″ Go back to out put.html page < /b>\n″); printf(″\n″); printf(″\n″); fflush(stdout); }

上面的 CGI 程序简单地用 printf()函数来产生 HTML 源代码。请注意在输出的字符串中 如果有双引号,在其前面必须有一个后斜字符\, 这是因为整个 HTML 代码串已经在双引号内, 所以 HTML 代码串中的双引号符必须用一个后斜字符\来转义。

你可能感兴趣的:(物联网Web服务器,嵌入式项目,服务器,物联网,web网关)