?? teach_sp_11.htm
字號:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb_2312-80">
<meta name="GENERATOR" content="聞怡洋 wyy_cq@cmmail.com">
<title>Visual C++/MFC開發(fā)指南</title>
<SCRIPT LANGUAGE='JavaScript' SRC='../../submit_navigate_bar.js'></SCRIPT>
<link REL="stylesheet" HREF="../../main.css">
</head>
<SCRIPT LANGUAGE='JavaScript'>write_body();</SCRIPT>
<SCRIPT LANGUAGE='JavaScript'>write_bar();</SCRIPT>
<p align="center"><a
HREF="http://www.0828.com/pay/cgi-bin/random.cgi?job=go&id=820"
target="_blank">
<img SRC="http://www.0828.com/pay/cgi-bin/random.cgi?id=820" BORDER="0"
width="468" height="60"></a><br>
<font size="2"><a href="http://www.0828.com/pay/index.html"><img border="0"
src="http://www.0828.com/pay/code.gif" width="468" height="15"></a><br>
<small>你每點一下上面的廣告我就能有更多的上網(wǎng)時間為大家尋找資料</small></font>
</p>
<table width=98% cellspacing="0" cellpadding="0" align=center><!--整體框架-->
<tr><td>
<table border=0 width="100%" cellspacing="0" cellpadding="2"><!--標記放置區(qū)域-->
<tr>
<td width="30%" align="center" bgcolor="#8E8E8E" valign=middle><img src=../../img/brand_200_60.gif width=200 height=60 alt="LOGO1"></td>
<td width="70%" align="center" bgcolor="#8E8E8E" valign=middle><img src=../../img/logo_400_60.gif width=400 height=60 alt="LOGO2"></td>
</tr>
<tr>
<td colspan="2" bgcolor="#939393" align=center><font color=white>您當前位置</font> <a href=../../index.htm><font color=white>首頁</font></a> <a href=../index.htm><font color=white>開發(fā)教程</font></a> <a href=index.htm><font color=white><font class=engul>Visual C++/MFC</font>專題講座</font></a> <font color=white>1.1 如何編寫<font class=eng>CGI</font>程序</font> <font color=white><SCRIPT LANGUAGE='JavaScript'>write_command();</SCRIPT></font></td>
</tr>
</table><!--標記放置區(qū)域 END-->
<table border=0 width=100% cellspacing="0" cellpadding="0">
<tr bgcolor="#F4F4F4">
<td><!-- article title begin here-->
<br>
<p align=center><big>1.1 如何編寫<font class=eng>CGI</font>程序</big></p>
<table border=0 align=center width=100%>
<tr><td><small>
<!-- article content begin here-->
<p>CGI的工作原理介紹:CGI(Common Gateway Interface)是一個WEB服務(wù)器提供信息服務(wù)的標準接口,通過這樣一個接口,WEB服務(wù)器能夠執(zhí)行程序,并將程序輸出的信息返回給瀏覽器。因為在WEB網(wǎng)上的數(shù)據(jù)都是靜態(tài)的,通過CGI程序能夠動態(tài)的處理瀏覽者的請求,如保存用戶輸入的信息,根據(jù)用戶信息返回相關(guān)的資料等等。當客戶端發(fā)送一個CGI請求給WEB服務(wù)器后,WEB服務(wù)器將根據(jù)CGI程序的類型決定數(shù)據(jù)向CGI程序的傳送方式,一般來講是通過標準輸入/輸出流和環(huán)境變量來與CGI程序間傳遞數(shù)據(jù)。
</p>
<p align=center><img src=g_11_1.gif><br>CGI輸入輸出原理</p>
<p>CGI的輸入/輸出方法:CGI程序通過標準輸入(STDIN)和標準輸出(STDOUT)來進行輸入輸出,STDIN和STDOUT是兩個預(yù)先定義好的文件指針。你可以利用文件讀寫函數(shù)來對其進行操縱。
</p><p>此外CGI程序還通過環(huán)境變量來得到輸入,只不過環(huán)境變量中提供的是一些常用的信息,并且通常不包括用戶在WEB頁面中輸入的信息(除使用下面講的GET方法時,通過檢查環(huán)境變量QUERY_STRING來得到輸入數(shù)據(jù)),而STDIN通常用來傳遞用戶輸入的信息。在普通CGI程序開發(fā)中我們需要關(guān)心的環(huán)境變量有以下這些:
</p><p>一部分是與WEB服務(wù)器有關(guān)的環(huán)境變量:
<ul>
<li>SERVER_NAME</li> WEB服務(wù)器名稱
<li>SERVER_PORT</li> WEB服務(wù)器監(jiān)聽地址
<li>SERVER_PROTOCOL</li> 用于發(fā)送請求的協(xié)議名稱和版本
<li>SERVER_SOFTWARE</li> WEB服務(wù)器名稱和版本
</ul>
一部分是與運行CGI有關(guān)的:
<ul>
<li>REQUEST_METHOD</li> 數(shù)據(jù)傳送(信息傳遞)方法
<li>CONTENT_LENGTH</li> 數(shù)據(jù)長度
<li>QUERY_STRING</li> 所傳送的數(shù)據(jù)
<li>REMOTE_ADDR</li> 客戶方IP地址
<li>REMOTE_HOST</li> 客戶方主機名程
</ul>
一部分是與客戶方有關(guān)的:
<ul>
<li>HTTP_USER_AGENT</li> 客戶瀏覽器名稱
<li>HTTP_ACCEPT</li> 客戶機所能支持的MIME類型列表
<li>HTTP_REFERER</li> 客戶機中前一文檔的URL
</ul>
</p><p>在輸入時所使用的POST/GET方法:在WEB頁面向CGI發(fā)送數(shù)據(jù)時通常采用兩種方法:GET/POST,GET方法將數(shù)據(jù)附加在URL后發(fā)送,如:/cgi/a_cgi_test.exe?your_data,CGI程序通過檢查環(huán)境變量QUERY_STRING來得到輸入數(shù)據(jù)。而POST方法則會將數(shù)據(jù)送入CGI程序的STDIN輸入流。在表單(FORM)中的各個變量都會成為name=value的形式向WEB服務(wù)器發(fā)送,多個數(shù)據(jù)間用&分隔,如:name=value&name2=value2。其中名字(name,name2)是Form中定義的INPUT、SELECT或TEXTAREA等標置(Tag)名字,值是用戶輸入或選擇的標置值。
</p><p>有了上面的知識我們就可以馬上寫一個簡單的CGI程序了。代碼如下:
<pre>
void main(void)
{// 本程序?qū)⒂脩糨斎氲臄?shù)據(jù)打印出來
fprintf(stdout,"content-type: text/plain\n\n");
// 輸出一個CGI標題,這行代碼的意義后面會講解
char *pszMethod;
pszMethod = getenv("REQUEST_METHOD");
if(strncmp(pszMethod,"GET") == 0)
{// GET method
//讀取環(huán)境變量來獲取數(shù)據(jù)
fprintf(stdout,"input data is :\n%s",getenv("QUERY_STRING"));
}
else
{// POST method
//讀取STDIN來獲取數(shù)據(jù)
int iLength=atoi(getenv("CONTENT_LENGTH"));
fprintf(stdout,"input data is :\n");
for(int i=0;i<iLength;i++)
{
char cGet=fgetchar(stdin);
fputchar(stdout,cGet);
}
}
}
</pre>
</p>
<p>如上面說講,在CGI程序輸出時必須先輸出一個CGI標題,標題共有以下三類:
<ul>
<li>Location: 標題,指明輸出另一個文檔的URL,例如 fprintf(stdout,"Location: http://www.vchelp.net/\n\n");</li>
<li>Content-Type: 標題,指明發(fā)送的數(shù)據(jù)的MIME類型,例如 fprintf(stdout,"Content-Type: text/html\n\n");</li>
<li>Status: 標題,指明HTTP狀態(tài)碼,例如 fprintf(stdout,"Status: 200\n\n");</li>
</ul>
注意每種標題后都必須跟一個換行和一個空行。
</p><p>MIME類型以類型/子類型的形式來表示,下面是一些常用的類型/子類型的組合:
<ul>
<li>Text/plain 普通文本類型</li>
<li>Text/html HTML格式的文本類型</li>
<li>Audio/basic 八位聲音文件格式,后綴為.au</li>
<li>Video/mpeg MPEG文件格式</li>
<li>Video/quicktime QuickTime文件格式</li>
<li>Image/gif GIF圖形文件</li>
<li>Image/jpeg JPEG圖形文件</li>
<li>Image/x-xbitmap X bitmap圖形文件,后綴為.xbm</li>
</ul>
</p>
<p>有了上面的知識我們就可以寫出一些CGI程序,首先需要對輸入數(shù)據(jù)進行分析,方法為:每當找到字符=,標志著一個Form變量名字的結(jié)束;每當找到字符& ,標志著一個Form變量值的結(jié)束。請注意輸入數(shù)據(jù)的最后一個變量的值不以&結(jié)束。這樣我們可以將輸入數(shù)據(jù)分解為一組一組的指。</p>
<p>但隨后會發(fā)現(xiàn)CGI的輸入并不規(guī)則,例如有時會出現(xiàn)類似下面格式的輸入字符號串:<font color=red>filename=hello&cmd=world+I%27</font>,這是因為瀏覽器對一些上傳的特殊字符進行了編碼,所以在將數(shù)據(jù)分解開后需要進行解碼,解碼規(guī)則為:+:將+轉(zhuǎn)換成空格符;%xx:用其十六進制ASCII碼值表示的特殊字符(%做為轉(zhuǎn)意符)。根據(jù)值xx將其轉(zhuǎn)換成相應(yīng)的ASCII字符。對Form變量名和變量值都要進行這種轉(zhuǎn)換。下面是一個對Form數(shù)據(jù)進行分析并將結(jié)果回送給Web服務(wù)器的CGI程序。
<pre>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
int htoi(char *);
main()
{
int i,n;
char c;
printf (″Contenttype: text/plain\n\n″);
n=0;
if (getenv(″CONTENT-LENGTH″))
n=atoi(getenv(″CONTENT-LENGTH″));
for (i=0; i<n;i++){
int is-eq=0;
c=getchar();
switch (c){
case ′&′:
c=′\n′;
break;
case ′+′:
c=′ ′;
break;
case ′%′:{
char s[3];
s[0]=getchar();
s[1]=getchar();
s[2]=0;
c=htoi(s);
i+=2;
}
break;
case ′=′:
c=′:′;
is-eq=1;
break;
};
putchar(c);
if (is-eq) putchar(′ ′);
}
putchar (′\n′);
fflush(stdout);
}
/* convert hex string to int */
int htoi(char *s)
{
char *digits=″0123456789ABCDEF″;
if (islower (s[0])) s[0]=toupper(s[0]);
if (islower (s[1])) s[1]=toupper(s[1]);
return 16 * (strchr(digits, s[0]) -strchr (digits,′0′))
+(strchr(digits,s[1])-strchr(digits,′0′));
}
</pre>
上面的程序首先輸出一個MIME頭信息給Web服務(wù)器,檢查輸入中的字符數(shù),并循環(huán)檢查每一個字符。當發(fā)現(xiàn)字符為&時,意味著一個名字/值對的結(jié)束,程序輸出一個空行;當發(fā)現(xiàn)字符為+時,將它轉(zhuǎn)換成空格; 當發(fā)現(xiàn)字符為%時,意味著一個兩字符的十六進制值的開始,調(diào)用htoi()函數(shù)將隨后的兩個字符轉(zhuǎn)換為相應(yīng)的ASCII字符;當發(fā)現(xiàn)字符為=時,意味著一個名字/值對的名字部分的結(jié)束,并將它轉(zhuǎn)換成字符:。最后將轉(zhuǎn)換后的字符輸出給Web服務(wù)器。 </p>
<p>開發(fā)CGI程序可以按照下面的步驟進行:<br>
1、判斷數(shù)據(jù)輸入方法為GET或是POST。<br>
2、讀取數(shù)據(jù),根據(jù)分隔符號&分解每個接收的表單變量,并同時對數(shù)據(jù)進行解碼。<br>
3、處理數(shù)據(jù)。<br>
4、輸出CGI標題,輸出HTML數(shù)據(jù)。<br>
5、退出。<br></p>
<p>利用C語言開發(fā)CGI需要自己對輸入的數(shù)據(jù)進行分析,但字符號串處理并非C語言的強項,所以我向大家推薦一套我認為比較不錯的開發(fā)包,<a href=http://www.vchelp.net/source/cgic_demo.zip>CGIC</a>,(由<a href=http://www.boutell.com/boutell/ target=_blank>http://www.boutell.com/boutell/</a>免費提供)。我對開發(fā)包中所提供的文件進行了少量的修改,并用VC6編譯成為LIB。下載后可以看看該開發(fā)包所提供的說明,該說明很詳細不但給出例子代碼而且對各個函數(shù)都有詳細的解說。
</p>
<!-- article content end-->
<p align=center><a href=index.htm#charpter1>返回</a></p>
</td></tr>
</table>
<p align=center><small>版權(quán)所有 聞怡洋 <a href=http://www.vchelp.net/><font class=engul>http://www.vchelp.net/<font></a></small></p>
</td>
</tr><!-- article title end-->
</table>
</td></tr></table><!--整體框架 END-->
<!--- BEGIN CLICK2NET CODE --->
<center><a href="http://redirect.click2net.com/?A056824,92" target="_blank">
<img border=0 alt="你每點一下廣告我就能有更多的上網(wǎng)時間為大家尋找資料" src="http://image.click2net.com/?A056824,92" width="468" height="60"></a>
<br><font style=small class=engul><a href="http://www.click2net.com/" target="_blank">Free Advertising from Click2Net!</a></font></center>
<!--- END CLICK2NET CODE --->
<SCRIPT LANGUAGE='JavaScript'>write_tail();</SCRIPT>
</body></html>
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -