CGI輸入輸出原理
CGI的輸入/輸出方法:CGI程序通過標準輸入(STDIN)和標準輸出(STDOUT)來進行輸入輸出,STDIN和STDOUT是兩個預先定義好的文件指針。你可以利用文件讀寫函數來對其進行操縱。
此外CGI程序還通過環境變量來得到輸入,只不過環境變量中提供的是一些常用的信息,並且通常不包括用戶在WEB頁面中輸入的信息(除使用下面講的GET方法時,通過檢查環境變量QUERY_STRING來得到輸入數據),而STDIN通常用來傳遞用戶輸入的信息。在普通CGI程序開發中我們需要關心的環境變量有以下這些:
一部分是與WEB服務器有關的環境變量:
- SERVER_NAME WEB服務器名稱
- SERVER_PORT WEB服務器監聽地址
- SERVER_PROTOCOL 用於發送請求的協議名稱和版本
- SERVER_SOFTWARE WEB服務器名稱和版本
一部分是與運行CGI有關的:
- REQUEST_METHOD 數據傳送(信息傳遞)方法
- CONTENT_LENGTH 數據長度
- QUERY_STRING 所傳送的數據
- REMOTE_ADDR 客戶方IP地址
- REMOTE_HOST 客戶方主機名程
一部分是與客戶方有關的:
- HTTP_USER_AGENT 客戶瀏覽器名稱
- HTTP_ACCEPT 客戶機所能支持的MIME類型列表
- HTTP_REFERER 客戶機中前一文檔的URL
在輸入時所使用的POST/GET方法:在WEB頁面向CGI發送數據時通常採用兩種方法:GET/POST,GET方法將數據附加在URL後發送,如:/cgi/a_cgi_test.exe?your_data,CGI程序通過檢查環境變量QUERY_STRING來得到輸入數據。而POST方法則會將數據送入CGI程序的STDIN輸入流。在表單(FORM)中的各個變量都會成爲name=value的形式向WEB服務器發送,多個數據間用&分隔,如:name=value&name2=value2。其中名字(name,name2)是Form中定義的INPUT、SELECT或TEXTAREA等標置(Tag)名字,值是用戶輸入或選擇的標置值。
有了上面的知識我們就可以馬上寫一個簡單的CGI程序了。代碼如下:
如上面說講,在CGI程序輸出時必須先輸出一個CGI標題,標題共有以下三類:
- Location: 標題,指明輸出另一個文檔的URL,例如 fprintf(stdout,"Location: http://www.vchelp.net//n/n");
- Content-Type: 標題,指明發送的數據的MIME類型,例如 fprintf(stdout,"Content-Type: text/html/n/n");
- Status: 標題,指明HTTP狀態碼,例如 fprintf(stdout,"Status: 200/n/n");
注意每種標題後都必須跟一個換行和一個空行。
MIME類型以類型/子類型的形式來表示,下面是一些常用的類型/子類型的組合:
- Text/plain 普通文本類型
- Text/html HTML格式的文本類型
- Audio/basic 八位聲音文件格式,後綴爲.au
- Video/mpeg MPEG文件格式
- Video/quicktime QuickTime文件格式
- Image/gif GIF圖形文件
- Image/jpeg JPEG圖形文件
- Image/x-xbitmap X bitmap圖形文件,後綴爲.xbm
有了上面的知識我們就可以寫出一些CGI程序,首先需要對輸入數據進行分析,方法爲:每當找到字符=,標誌着一個Form變量名字的結束;每當找到字符& ,標誌着一個Form變量值的結束。請注意輸入數據的最後一個變量的值不以&結束。這樣我們可以將輸入數據分解爲一組一組的指。
但隨後會發現CGI的輸入並不規則,例如有時會出現類似下面格式的輸入字符號串:filename=hello&cmd=world+I%27,這是因爲瀏覽器對一些上傳的特殊字符進行了編碼,所以在將數據分解開後需要進行解碼,解碼規則爲:+:將+轉換成空格符;%xx:用其十六進制ASCII碼值表示的特殊字符(%做爲轉意符)。根據值xx將其轉換成相應的ASCII字符。對Form變量名和變量值都要進行這種轉換。下面是一個對Form數據進行分析並將結果回送給Web服務器的CGI程序。
開發CGI程序可以按照下面的步驟進行:
1、判斷數據輸入方法爲GET或是POST。
2、讀取數據,根據分隔符號&分解每個接收的表單變量,並同時對數據進行解碼。
3、處理數據。
4、輸出CGI標題,輸出HTML數據。
5、退出。
利用C語言開發CGI需要自己對輸入的數據進行分析,但字符號串處理並非C語言的強項,所以我向
大家推薦一套我認爲比較不錯的開發包,CGIC,(由http://www.boutell.com/boutell/免費提供)。
我對開發包中所提供的文件進行了少量的修改,並用VC6作者成爲LIB。下載後可以看看該開發包所提供
的說明,該說明很詳細不但給出例子代碼而且對各個函數都有詳細的解說。
一部分是與WEB服務器有關的環境變量:
- SERVER_NAME WEB服務器名稱
- SERVER_PORT WEB服務器監聽地址
- SERVER_PROTOCOL 用於發送請求的協議名稱和版本
- SERVER_SOFTWARE WEB服務器名稱和版本
一部分是與運行CGI有關的:
- REQUEST_METHOD 數據傳送(信息傳遞)方法
- CONTENT_LENGTH 數據長度
- QUERY_STRING 所傳送的數據
- REMOTE_ADDR 客戶方IP地址
- REMOTE_HOST 客戶方主機名程
一部分是與客戶方有關的:
- HTTP_USER_AGENT 客戶瀏覽器名稱
- HTTP_ACCEPT 客戶機所能支持的MIME類型列表
- HTTP_REFERER 客戶機中前一文檔的URL
在輸入時所使用的POST/GET方法:在WEB頁面向CGI發送數據時通常採用兩種方法:GET/POST,GET方法將數據附加在URL後發送,如:/cgi/a_cgi_test.exe?your_data,CGI程序通過檢查環境變量QUERY_STRING來得到輸入數據。而POST方法則會將數據送入CGI程序的STDIN輸入流。在表單(FORM)中的各個變量都會成爲name=value的形式向WEB服務器發送,多個數據間用&分隔,如:name=value&name2=value2。其中名字(name,name2)是Form中定義的INPUT、SELECT或TEXTAREA等標置(Tag)名字,值是用戶輸入或選擇的標置值。
有了上面的知識我們就可以馬上寫一個簡單的CGI程序了。代碼如下:
如上面說講,在CGI程序輸出時必須先輸出一個CGI標題,標題共有以下三類:
- Location: 標題,指明輸出另一個文檔的URL,例如 fprintf(stdout,"Location: http://www.vchelp.net//n/n");
- Content-Type: 標題,指明發送的數據的MIME類型,例如 fprintf(stdout,"Content-Type: text/html/n/n");
- Status: 標題,指明HTTP狀態碼,例如 fprintf(stdout,"Status: 200/n/n");
注意每種標題後都必須跟一個換行和一個空行。
MIME類型以類型/子類型的形式來表示,下面是一些常用的類型/子類型的組合:
- Text/plain 普通文本類型
- Text/html HTML格式的文本類型
- Audio/basic 八位聲音文件格式,後綴爲.au
- Video/mpeg MPEG文件格式
- Video/quicktime QuickTime文件格式
- Image/gif GIF圖形文件
- Image/jpeg JPEG圖形文件
- Image/x-xbitmap X bitmap圖形文件,後綴爲.xbm
有了上面的知識我們就可以寫出一些CGI程序,首先需要對輸入數據進行分析,方法爲:每當找到字符=,標誌着一個Form變量名字的結束;每當找到字符& ,標誌着一個Form變量值的結束。請注意輸入數據的最後一個變量的值不以&結束。這樣我們可以將輸入數據分解爲一組一組的指。
但隨後會發現CGI的輸入並不規則,例如有時會出現類似下面格式的輸入字符號串:filename=hello&cmd=world+I%27,這是因爲瀏覽器對一些上傳的特殊字符進行了編碼,所以在將數據分解開後需要進行解碼,解碼規則爲:+:將+轉換成空格符;%xx:用其十六進制ASCII碼值表示的特殊字符(%做爲轉意符)。根據值xx將其轉換成相應的ASCII字符。對Form變量名和變量值都要進行這種轉換。下面是一個對Form數據進行分析並將結果回送給Web服務器的CGI程序。
開發CGI程序可以按照下面的步驟進行:
1、判斷數據輸入方法爲GET或是POST。
2、讀取數據,根據分隔符號&分解每個接收的表單變量,並同時對數據進行解碼。
3、處理數據。
4、輸出CGI標題,輸出HTML數據。
5、退出。
利用C語言開發CGI需要自己對輸入的數據進行分析,但字符號串處理並非C語言的強項,所以我向
大家推薦一套我認爲比較不錯的開發包,CGIC,(由http://www.boutell.com/boutell/免費提供)。
我對開發包中所提供的文件進行了少量的修改,並用VC6作者成爲LIB。下載後可以看看該開發包所提供
的說明,該說明很詳細不但給出例子代碼而且對各個函數都有詳細的解說。