大二的時候就開始接觸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/
完畢!