C語言CGI編程入門(一)
CGI是指web服務器調用編程語言編寫的程序的一個接口。比如我們可以編寫一個用戶註冊的頁面,用戶將其輸入的郵箱、用戶名、密碼輸入並點擊註冊,此時瀏覽器就將用戶輸入的內容發送給了我們後臺的CGI程序,我們的CGI程序接受到這些信息,可以對其進行處理。比如送入數據庫、判斷輸入的信息是否合法等。
主流的CGI程序用Perl編寫,Perl是一款強大的腳本語言,不過我這裏不太懂,我也不去比較某兩個語言間的優劣。我說一下用C和C++如何編寫CGI程序,告訴大家用C語言也能編寫web應用程序,用C語言也能寫一個網站。
1.準備工作
首先要先安裝一款web服務器。我就用windows系統下的Apache,當然Linux下大同小異,可能需要設置的東西多一些。
大家可以在apache官網下載最新版的Apache for Windows,天空也有下載:http://www.skycn.com/soft/1218.html。安裝後打開安裝目錄,大致就是這樣一些文件:
看到那個“cgi-bin”了嗎,這是默認的cgi程序目錄。當然,我們也可以手動設置其位置:用記事本打開conf/httpd.conf,這是Apache的配置文件。找到類似下面這一行
ScriptAlias /cgi-bin/ "d:/Program Files (x86)/Apache Software Foundation/Apache2.2/cgi-bin/" |
"/cgi-bin/"表示web地址,比如默認是http://localhost/cgi-bin/,即訪問cgi的根目錄。"d:/Program Files (x86)/Apache Software Foundation/Apache2.2/cgi-bin/"表示對應的絕對路徑。這應該不難理解,我們瀏覽器訪問http://localhost/cgi-bin/就是代表訪問了服務器上的相應的絕對路徑。所以修改這個絕對路徑,就可以指定我們的CGI程序存放的根目錄。
我這裏就不改了,一會我們寫好的CGI程序直接放在這個cgi-bin文件夾下,再通過http://localhost/cgi-bin/訪問即可。
2.開始寫程序
用VS2010新建一個控制檯應用程序工程,我的就叫cgi_test。在main函數裏寫
1 |
printf ( "Content-type:text/html\n\n" ); |
2 |
printf ( "hello
world!!" ); |
當然也可以用C++的cout來代替printf輸出。先別急着編譯,我們先在工程上點右鍵,選擇屬性:
在配置設置-常規中,更改輸出目錄爲cgi-bin下。我就改成cgi-bin\test\,這樣我們生成的可執行文件就會被放在這裏。目標文件的擴展名我也順便從exe改成cgi,如果不改,迅雷等下載可能會讓你下載而不是讓瀏覽器解析它。
再就可以編譯了。F7編譯後,我們來到cgi-bin/test/中,就可以看到我們編譯生成好的"cgi_test.cgi"文件。
打開瀏覽器,輸入http://localhost/cgi-bin/test/cgi_test.cgi,就可以看到hello world了:
這就是我們的第一個cgi程序。
3.怎麼寫一個CGI程序
剛纔寫程序的工作是我來完成的,雖說那兩個語句很簡單,但有的同學會問爲什麼要這麼寫。
我簡單解釋一下,第一個printf輸出的"Content-type:text/html\n\n"是一個文件的標誌,告訴瀏覽器以html的語法來解析此文件,而不是去下載它(注意末尾需要兩個換行,即一個空行,這是標準)。只要我們需要輸出內容到瀏覽器,都得加這一句話在最前面,記住就好。
後面的printf就是輸出到瀏覽器上的信息,注意需要用html的語法才能正常顯示在瀏覽器上。比如換行,需要用<br />,而不是\n了。不懂的去學習關於html的知識(如果不學習html就別想做一個網站或web程序)。
所以,只要通過printf,就可以將任何html代碼輸出在瀏覽器裏。而且,因爲是用C/C++寫的程序,所以C/C++下的一切函數,都可以用在CGI程序裏。(也包括windowsAPI)
比如,用戶填寫好了註冊表單,將信息傳遞給我的CGI程序,我就可以調用ODBC的函數,連接數據庫,將信息寫入數據庫。也可以通過if判斷句,來檢查用戶是否輸入了非法信息。
不過有同學又要問了,用戶填寫的信息怎麼就傳給我們的CGI程序了呢?程序又是怎麼接受這些數據?
4.接受GET或POST來的信息
如果不知道GET和POST的意思,我建議你還是去看一下PHP。我這裏只簡單地提一下,我們新建一個html網頁,在其中添加一個表單,其中有一個文本框和一個按鈕,大致代碼如下:
1 |
< form id = "form" name = "form" method = "post" action = "http://localhost/cgi-bin/test/cgi_test.cgi" > |
2 |
< p >輸入內容: |
3 |
< input type = "text" name = "user" id = "user" /> |
4 |
</ p > |
5 |
< p > |
6 |
< input type = "submit" name = "submit" id = "submit" value = "提交" /> |
7 |
</ p > |
8 |
9 |
</ form > |
大家可以看到,form有個屬性method,表示你用什麼方式提交(post或get),action屬性表示提交的地址。get方式提交,意思就是把提交的內容放在地址後面,用?隔開。post提交就是把數據放在數據包裏發送給目標地址。我們在文本框內填入信息,點擊按鈕提交,我們填入的信息就會以相應方式發送到目標地址。
C程序接受POST過來的信息比較簡單。因爲post來的信息都在輸入流裏,直接scanf或cin>>就能讀取了。
GET來的信息在地址欄裏,我們需要用到一個C庫中的函數:getenv,它的作用是獲取環境變量,其中包括獲取GET來的信息。(獲取?後的所有內容:getenv("QUERY_STRING"))
關於這個函數的所有用法我放在附件裏,下載可查。
5.做個示範
01 |
int _tmain( int argc,
_TCHAR* argv[]) |
02 |
{ |
03 |
printf ( "Content-type:text/html\n\n" ); |
04 |
printf ( "%s" , getenv ( "QUERY_STRING" )); //打印get獲取的信息 |
05 |
char szPost[256]; |
06 |
gets (szPost); |
07 |
if ( strcmp (szPost,)) |
08 |
printf ( "%s" ,szPost); //打印post獲取的信息 |
09 |
return 0; |
10 |
} |
用我們剛纔的html代碼來提交:
至於get方式獲取的信息打印出來後面爲什麼有亂碼,因爲我順便把沒有信息的szPost也打印了。實際應用的時候應該先判斷szPost中是否有信息再打印。