本文寫給C/C++程序猿,也適合其他對歷史感興趣的程序猿
=============================================
談到web開發,大家首先想到的PHP、JavaEE/JSP、.NET/ASP、Ruby on rails、Python的Django等等。可謂百花齊放,你一般不會想到C++和Web開發有什麼關系,但其實動態網頁的開發(web開發)可是在這些動態網頁語言誕生之前就存在了的。所以C/C++也是可以做web開發的,它利用的技術是——CGI。
在天地初開,混沌未分之時,動態網頁語言尚未出世,要實現動態網站依賴的就是CGI。谷歌/百度一下CGI,可能會出現很多名詞:CGI腳本、CGI程序、CGI標准等等。其實這些都是站在不同角度來說的,CGI即Common Gateway Interface的縮寫,直譯為“通用網關接口”。第一次聽這個名字,我也不知道是個什麼鬼東西。歸根結底CGI就是一個接口協議。協議就是大家公認的一套標准(叫CGI標准也可以),比如網絡協議。大家都遵守一套標准,就減少了溝通的難度。進行CGI開發,就是編寫一個CGI可執行程序。其實各種語言都可以編寫CGI,不但Java、Python、PHP、C#……可以,而且Shell也可以。當然C和C++也可以。由於早期CGI很多是由Perl(腳本語言)開發的,所以CGI程序也稱CGI腳本,其實這個稱呼不一定准確。因為C++編譯出的可執行文件同樣可以是CGI。
在PHP和Java大行其道的今天,很多人看來用C++編寫CGI是幾乎淘汰的技術了(其實這到不然,只是比較小眾罷了)。所以如果你對C/C++感興趣或者對歷史感興趣都可以閱讀本文。
<form action="/cgi-bin/hello.cgi" method="get"> <table> <tbody> <tr> <td>用戶名:</td> <td><input name="username" /></td> </tr> <tr> <td>密碼:</td> <td><input name="password" /></td> </tr> <tr> <td><input type="submit" value="OK" /></td> </tr> </tbody> </table> </form>form標簽的action屬性的值表示的就是表單要提交到url,即表單提交以後要跳轉的頁面(Ajax可以達到無跳轉拉取數據,刷新頁面),這裡action屬性值的是cgi程序的url地址。(WARNNING:/ 對應的是網站根目錄,而不是Linux文件系統根目錄哦)。method屬性表示數據請求方式,有兩種:get和post。不贅述。 我輸入用戶名jellywang,密碼123456之後,點擊OK按鈕,即向當前域名/cgi-bin/hello.cgi 的程序序提交了表單,並且攜帶參數username=jellywang。然後頁面會跳轉到這個cgi(就像普通網頁跳轉,浏覽器地址欄更新一樣)。 如果是get請求。那麼浏覽器地址欄的URL看起來像這樣:localhost:/cgi-bin/hello.cgi?username=jelly&password=123456。很顯然這是一種不夠安全的方式,所以我們還可以使用post請求。這樣地址欄就看不到這種提交的參數了。(其實post也不夠安全,不鼓勵直接提交明文密碼的方式,本文僅作示例,安全登錄不上本文重點)
REQUEST_METHOD
前端頁面數據請求方式:get/post
QUERY_STRING
采用GET時所傳輸的信息
CONTENT_LENGTH
STDIO中的有效信息長度
SCRIPT_NAME
所調用的CGI程序的名字
SERVER_NAME
服務器的IP或名字
SERVER_PORT
主機的端口號
這些環境變量是從何而來,是誰定義的?是Linux嗎?POSIX嗎?當然不是。這裡就要再次聲明一下CGI是一個接口協議,這些環境變量就是屬於該協議的內容,所以不論你的server所在的操作系統是Linux還是Windows,也不論你的server是Apache還是Nginx,這些變量的名稱和含義都是一樣的。實際就是Apache/Nginx在將這些內容填充到環境變量中,而具體填充規范則來自於CGI接口協議。 在C語言標准中有獲取環境變量值得庫函數——getenv。(頭文件stdlib.h)//比如 chr* str = NULL; str = getenv("QUERY_STRING");對於get請求,可以從環境變量QUERY_STRING中取出字符串 username=jelly&password=123456。然後程序自己做字符串的解析操作,解析出參數的key和value。而對於post請求,則是直接通過標注輸入(STDIN)來獲取這個參數字符串,比如使用scanf或cin都可以。 在解析了請求、進行了相應的邏輯處理之後(比如檢查用戶名密碼是否一致),CGI程序要向前端頁面返回內容,這是通過標准輸出(STDOUT)完成的,比如printf或cout,你可以返回xml,json,plain text或一個html網頁等等。這一步完成的是就是HTTP的響應過程。所以在返回直接的數據之前,要先輸出HTTP協議的首部。比如,假設你想返回一個html網頁,那麼你首先要輸出:
cout<<"Content-Type:text/html\n\n"<後面直接cout出html代碼(比如輸出你剛才輸入的用戶名成功登陸)。前端頁面就會收到這些html代碼,然後浏覽器就渲染成網頁啦。這就是一次CGI完成的動態網頁操作了。WARNNING:這裡要注意,一定要輸出兩個換行符(\n)。因為HTTP協議的首部和消息實體(如HTML代碼)之間用空行分割。