CGI程序开发基础

1.CGI 脚本结构

当脚本被服务器引发时,服务器常常以两种途径之一向脚本传递信息:GET或POST。这两种方法被称为请求方法。所使用的请求方法是通过环境变量传给脚本,该环境变量叫作REQUEST_METHOD(还定义了另外两种请求方法一HEAD和PUT,但它们不是特别应用于CGI,并且不鼓励使用它们)。

1)GET是对数据的一个请求——同样的方法被用于获得静态文档。GET方法以附加在URL后面的参数发送请求信息。这些参数将放在环境变量QUERY_STRING中传给CGI程序。例如,有一个叫作Myprog.exe的脚本,从如下的链接启动它:
<a href="cgi-bin/myprog.exe?lname=blow&fname=joe">
REQUEST_METHOD是GET,QUERY_STRING包含lname=b1ow&fname=joe。在“URL一编码”中将讨论QUERY_STRING的格式。

问号从QUERY_STRING的起始处分隔开脚本名字。在一些服务器上,问号是强制性的,即使后面没有跟着QUERY_STRING。另一些服务器则允许用一个正斜杠代替问号或与之附加在一起。如果使用斜杠,服务器则用PATH_INFO而不是QUERY_STRING变量将信息传给脚本。(URL解码)

2)当浏览器将数据从一个填写表单传给服务器时,发生POST操作。对于POST,QUERY一STRING可能为空或不空,这有赖于服务器。如果有信息,则其如GET的情况一样被格式化和传递。

来自POST查询的数据使用STDIN从服务器传到脚本。由于STDIN是一个源,脚本需要知道有多少有效数据。于是服务器还提供了另一个变量,CONTENT_LENGTH,以指出到来数据的字节数。而POST的数据格式为:
variable1=value1&variable2=value2&etc

你的程序必须检查REQUEST_METHOD环境变量以知道是否要读取STDIN。CONTENT_LENGTH变量一般只在REOUEST_METHOD为POST时有用。

CGI应用的基本结构既简单又直接明了:初始化、处理、输出和终止。由于讨论的是概念、数据源、编程规则,所以在例子中将使用伪码而不是使用某种特定语言。

理想情况下,一个脚本具有如下形式(do-initialize,do-process和do-output代表恰当的子例程):
程序开始
调用 do-initialize
调用 do-proces
调用 do一output
程序结束。

实际情况并非这么简单。

1.1 初始化

脚本启动后必须做的第一件事是确定其输入、环境和状态。基本操作系统环境信息能以通常方式得到:在Windows NT或windows95中从系统注册区得到,在Unix系统中从标准环境变量得到,在别的Windows版本中从INI文件得到,等等。

状态信息来自于输入,而不是操作环境或静态变量。记住:每当CGI脚本被引发时,它都好象此前从未被引发过。脚本不在调用之间持续运行,所有的东西都必须从头初始化,如下:

1.确定脚本是如何被引发的
典型情况下,这涉及读取REQUEST_METHOOD环境变量并分析其中的单词GET或POST。

注意
尽管当前定义应用于coi的操作只有GET和posT,你或许会时不时地遇到PUT或HEAD,假王口你的服务器支持它并且用户的剜览器或一个机器人使用它就可能发生这种情况。 PUl7k作为PosT的另选提供,但从未得多(认可的RFC资格,一般不被使用。HEAD被一些剜览器fotL器人(自动剜览器账用,仅用于提取HTML文在的头部,不适用于C6路程。此外还有一些古怪的请求方法。你的代码应该检查是否为GET和PosT,拒绝任何其他方法,不要假设请求方法如果不是GET便是PosT,或者相反。

2.提取输入数据
如果方法是GET,必须获得、分析、解码QUERY_STRING环境变量。如果方法是POST,必须检查QUERY_STRING并还要分析STDIN。如果CONTENT_TYPE环境变量是设为application/x-www-form-urlencoded,来自STDIN的源也需要解码。

1.2处理

脚本通过读取和分析其输入从而对环境初始化之后,便准备进入工作。在此阶段发生的事情则远没有初始化阶段那样确定。在初始化时,参数是知道的(或是可以被发现),所要做的任务对于各个脚本都多多少少地相同。然而,处理阶段是脚本的核心,在此时要做的事情几乎完全依赖于脚本的目标。

1.处理输入数据
此时做什么取决于脚本。例如,你可以忽略全部输入而仅仅输出数据,可能以有条理格式化的HTML将输入在吐出去,或许会在一个数据库中猎取信息在将其显示出来,或者是从前没有想到的任何事情。处理数据一般意味着,以某种方式对其进行转换。在传统的数据处理术语中,这叫做转换步骤,因为,在面向批作业的处理中,程序读取一个记录并对其施加一些规则(转换它),然后将其写回。CGI 程序很少被看作传统的数据处理,但思想是一样的。程序的处理数据阶段不同的CGI 程序,——在数据处理阶段,你拿到输入,并从其中做出一些新的东西来。

2.输出结果
在一个简单的CGI脚本中,输出常常只是一个头部和一些HTML。更复杂些的脚本可能;输出图形、图形与文本的混和,或者为了用一些附加信息再次调用脚本而必要的全部信息。一个常用并且更精巧的技术是使用GET调用脚本一次,这可以用一个标准的<A HREF>标记做到。脚本可以感知它是用GET调用的,并动态地创建HTML表单一一包括隐藏变量和再次用POST调用脚本所需的代码。

兼容性问题

在UNIX世界中,字符流是一种特殊的文件。默认地,STDIN和STDOUT是字符流。操作系统很有帮助地为你分析流,确保所通过的全是正确的7-bitASCII码,或者是认可的控制码。

7-bit?是的。对于HTML,这没有问题。然而,如果你的脚本发送图形数据,使用面向字符的流则意味着立即失败。解决方法是将流切换到二进制模式。在C语言中,可以使用setmode函数:setmode(fileno(stdout),O_BINARY)。通过setmode(fi1eno(stdout),O_TEXT)在流当中进行切换。一个典型的图形脚本以字符模式输出头部,而后切换到二进制模式用于图形数据。

在windows NT世界中,为了兼容性,流有着同样方式的行为。输出中的一个简单\n,当写到STDOUT时,被变换为\r\n。一般的windows NT调用,如write Fi1e(),不发生上述变换,如果同时想要一个回车和一个换行,则必须显式地指出\r\n。

字符模式和二进制模式的另一种说法是cooked和raw,知道这两个名词的人或许会使用它们,而不是更常见的说法。不管使用什么词,在什么平台上,关于流存在着另一问题:默认情况下,它们是有缓冲区的,意思是操作系统挂起数据,直至看见一个行结束符、缓冲区满或者流被关闭。这意味着,你如果将有缓冲区的prinif()语句同无缓冲区的fwriie()或fprintf()语句混合在一起,事情可能就变得混乱了,尽管它们都会是写到STDOUT。printf()有缓冲区地将数据写到流,面向文件的例程则无缓冲区地输出数据。结果是乱序的一团糟。

你可能将此归咎于后向兼容性。除了许多老程序之外,流实在没理由将默认定为有缓冲区和cooked。这应当是在需要时可以打开的选项,而不是在不要时关闭。幸运的是,你能够用setvbuf(stdout,NULL,_IONBF,0)解决这一困难,这个函数关闭UTDOUT流的全部缓冲区。

另一个解决是避免混和不同类型的输出语句,即使这样,也不能使cooked输出变成raw。所以最好是关闭所有缓冲区。许多服务器和浏览器不喜欢接收单调乏味的输入。

注意
那些常把UNIX挂在嘴边的人可能会对名词CRLF(回车与换行)皱眉,而那些在其他平台上编程的人也许不认识\n或\r\n。CRLF等于\r\n。C编程者用\r表示一个回车(CR)符号,用\n表示一个换行(LF)符。(对于Basic编程,LF是Chr$(10,CR是Chr$(13)。)

1.3 终止

终止就是清理和退出。你如果对任何文件加了锁,则必须在程序结束前释放它们。你如果分配了内存、信号量或其他对象,也必须进行释放。不正确完成这些会导致脚本“昙花只能一现”。即脚本在第一次调用时能工作,而在以后的调用中就会崩溃。更有甚者,脚本由于没有正确释放资源和锁,将会妨碍甚至破坏其他脚本或服务器本身。

在一些平台上一Windows NT最显著, UNIX次之——文件句柄和内存对象在进程终止时会被关闭和收回。即使这样,依赖操作系统为你清理垃圾也非明智之举。例如,在Windows NT上,如果一个程序对一个文件全部或部分加锁,而后不释放锁便终止,则文件系统的行为将是不确定的。

必须确保你的出错一退出例程——如果有(也应该有)——了解脚本的资源并能象主退出例程一样彻底地对它们进行清理。

2.计划脚本

现在读者已经看到了一个脚本的基本结构,下面将要学习如何从头计划一个脚本。按照如下基本步骤进行:
用一些时间定义程序的任

 

聚拓互联(http://www.ejutuo.com).Net平台至强虚拟主机供应商,是领先的互联网基础应用服务提供商,主要面向全球客户提供域名注册、国内、香港/美国虚拟主机、企业邮箱、智能建站、虚拟服务器(VPS)、服务器租用、服务器托管等丰富的网络产品服务。

聚拓互联的快速发展与其企业文化密不可分,易网人秉持“团结互助、敬业负责、恪守信誉、积极进取、勇于创新”的企业文化,汇聚了行业内的大量专业人士,拥有多位国内顶尖的linux/freeBSD/unix经验的系统工程师、微软认证工程师和网络安全技术人才。核心团队均为该行业从业多年的专业人士,拥有丰富行业经验和较高威望,并不断改革创新,以满足客户多元化需求为己任,不断进取。 同时,易网坚守 “专业品质、服务为本、诚信经营、恪守信誉”的核心价值观,为客户提供多样、安全、稳定、放心的产品。

posted on 2012-08-23 22:25  天外飞仙2  阅读(218)  评论(0)    收藏  举报

导航