大二的時候就開始接觸CGI了,那時候用perl、php都寫過CGI程序,對CGI的了解
也浮于表面上,最近由于工作需要,需要用C來寫CGI程序,是時候弄清楚CGI內部的工
作機制了。
1. CGI是什么?
相信很多人和我之前一樣,說到CGI,會熟練的蹦出一句“Common Gateway
Interface ”,沒錯,這確實是CGI的全稱,可以翻譯為“通用網(wǎng)關接口”,可一說到它的
用處,有多少人能夠講清楚? 沒關系,現(xiàn)在我就幫大家來解決這個困惑。按照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現(xiàn)在都用在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程序充當?shù)慕巧且粋€Gateway,那么
這個Gateway的兩端是什么?沒錯,是Http Server(Web Server)的輸入和輸出,換句話說
,CGI程序從Web Server那里獲得瀏覽器發(fā)過來的數(shù)據(jù),進行相應處理后,輸出瀏覽器識別
的html文本給Web Server。為了便于理解, 還是用流程圖示意一下。
client Web Server CGI程序
http協(xié)議 CGI接口
發(fā)送請求---->接受請求并將數(shù)據(jù)處理發(fā)送給CGI程序--->獲得處理過的數(shù)據(jù)并解析
接受數(shù)據(jù)<----獲得CGI返回的數(shù)據(jù)并發(fā)送給客戶端<---處理數(shù)據(jù)并返回html數(shù)據(jù)
圖 1
本文討論的重點就是這個CGI接口, CGI程序通過環(huán)境變量和標準輸入獲得數(shù)據(jù),通過標
準輸出和標準錯誤輸出發(fā)送數(shù)據(jù),那么這個到底是怎么實現(xiàn)的呢?
3. CGI接口實現(xiàn)
其實Web Server和CGI程序就是兩個進程,要實現(xiàn)CGI接口就是如何實現(xiàn)這兩個進程的通信
,Web Server獲得瀏覽器發(fā)送過來的請求后,將數(shù)據(jù)做相應處理,然后fork一個子進程處
理客戶請求,子進程組織相應的環(huán)境變量和參數(shù)準備傳遞給CGI程序,然后調用execvp執(zhí)
行CGI程序。CGI程序有自己的環(huán)境變量,就是如上實現(xiàn)的,第二節(jié)說過,CGI程序除了通
過環(huán)境變量獲得數(shù)據(jù)外(其實這是get方法獲取數(shù)據(jù)的手段),還通過標準輸入獲得數(shù)據(jù)(pos
t方法獲取數(shù)據(jù)的方法),并且返回的數(shù)據(jù)是發(fā)送到標準輸出。相信你和我之前有一樣的疑
問,為什么CGI程序能夠從標準輸入、標準輸出讀寫數(shù)據(jù)?其實這是通過管道和dup2系統(tǒng)
調用實現(xiàn)的,見下面的示意圖:
_____________________
dup2| |
(CGI program)read<-stdin<--|p[0]--管道1--p[1]|<-write (http server)
|_____________________|
圖2: CGI讀的實現(xiàn)
_____________________
dup2| |
(CGI program)write->stdout-->|p[1]--管道2--p[0]|->read (http server)
|_____________________|
圖3: CGI寫的實現(xiàn)
4. 如何寫CGI程序
有了上述的講述后,應該算基本熟悉CGI的內幕了,這樣寫起CGI程序也會得心應手,
首先獲得相應的環(huán)境變量并保存,然后就是數(shù)據(jù)處理,根據(jù)REQUEST_METHOD環(huán)境變量判斷
表單提交的方法是GET還是METHOD,如何是GET,則從QUERY_STRING里面獲取數(shù)據(jù),如果是
POST, 那么從stdin讀取長度CONTENT_LENGTH的數(shù)據(jù)。下面就是數(shù)據(jù)處理,組織html的輸
出頁面,并用printf輸出。
5. 小結
上面講的其實只是一個概況,關于CGI的接口有興趣的可以去看看這兩個網(wǎng)頁:
http://cgi-spec.golux.com/draft-coar-cgi-v11-03-clean.html
http://hoohoo.ncsa.uiuc.edu/cgi/intro.html
我敘述的可能有些地方也有問題,歡迎提出! 另外關于CGI實現(xiàn)的代碼可以看看
開源軟件"thttpd",這是一個輕量級的http server,實現(xiàn)的很講究,主頁在
http://www.acme.com/software/thttpd/
完畢!