大二的时候就开始接触CGI了,那时候用perl、php都写过CGI程序,对CGI的了解
也浮于表面上,最近由于工作需要,需要用C来写CGI程序,是时候弄清楚CGI内部的工
作机制了。
1. CGI是什么?
相信很多人和我之前一样,说到CGI,会熟练的蹦出一句“Common Gateway
Interface ”,没错,这确实是CGI的全称,可以翻译为“通用网关接口”,可一说到它的
用处,有多少人能够讲清楚? 没关系,现在我就帮大家来解决这个困惑。按照CGI 1.1
里面的说法“The Common Gateway Interface (CGI) is a simple interface for
running external programs, software or gateways under an information server in
a platform–idependent manner. Currently, the supported information servers
are HTTP servers.”,和我们熟悉的一样,CGI现在都用在http服务器上,那么CGI能够
提供怎样的便利呢?答案如下:“A plain HTML document that the Web daemon
retrieves is static, which means it exists in a constant state: a text file
that doesn’t change. A CGI program, on the other hand, is executed in
real-time, so that it can output dynamic information.”
2. CGI接口定义
目前关于CGI接口最新的版本是1.1, 既然CGI程序充当的角色是一个Gateway,那么
这个Gateway的两端是什么?没错,是Http Server(Web Server)的输入和输出,换句话说
,CGI程序从Web Server那里获得浏览器发过来的数据,进行相应处理后,输出浏览器识别
的html文本给Web Server。为了便于理解, 还是用流程图示意一下。
client Web Server CGI程序
http协议 CGI接口
发送请求---->接受请求并将数据处理发送给CGI程序--->获得处理过的数据并解析
接受数据<----获得CGI返回的数据并发送给客户端<---处理数据并返回html数据
图 1
本文讨论的重点就是这个CGI接口, CGI程序通过环境变量和标准输入获得数据,通过标
准输出和标准错误输出发送数据,那么这个到底是怎么实现的呢?
3. CGI接口实现
其实Web Server和CGI程序就是两个进程,要实现CGI接口就是如何实现这两个进程的通信
,Web Server获得浏览器发送过来的请求后,将数据做相应处理,然后fork一个子进程处
理客户请求,子进程组织相应的环境变量和参数准备传递给CGI程序,然后调用execvp执
行CGI程序。CGI程序有自己的环境变量,就是如上实现的,第二节说过,CGI程序除了通
过环境变量获得数据外(其实这是get方法获取数据的手段),还通过标准输入获得数据(pos
t方法获取数据的方法),并且返回的数据是发送到标准输出。相信你和我之前有一样的疑
问,为什么CGI程序能够从标准输入、标准输出读写数据?其实这是通过管道和dup2系统
调用实现的,见下面的示意图:
_____________________
dup2| |
(CGI program)read<-stdin<--|p[0]--管道1--p[1]|<-write (http server)
|_____________________|
图2: CGI读的实现
_____________________
dup2| |
(CGI program)write->stdout-->|p[1]--管道2--p[0]|->read (http server)
|_____________________|
图3: CGI写的实现
4. 如何写CGI程序
有了上述的讲述后,应该算基本熟悉CGI的内幕了,这样写起CGI程序也会得心应手,
首先获得相应的环境变量并保存,然后就是数据处理,根据REQUEST_METHOD环境变量判断
表单提交的方法是GET还是METHOD,如何是GET,则从QUERY_STRING里面获取数据,如果是
POST, 那么从stdin读取长度CONTENT_LENGTH的数据。下面就是数据处理,组织html的输
出页面,并用printf输出。
5. 小结
上面讲的其实只是一个概况,关于CGI的接口有兴趣的可以去看看这两个网页:
http://cgi-spec.golux.com/draft-coar-cgi-v11-03-clean.html
http://hoohoo.ncsa.uiuc.edu/cgi/intro.html
我叙述的可能有些地方也有问题,欢迎提出! 另外关于CGI实现的代码可以看看
开源软件"thttpd",这是一个轻量级的http server,实现的很讲究,主页在
http://www.acme.com/software/thttpd/
完毕!