明輝手游網(wǎng)中心:是一個免費提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺!

MFC ISAPI編程探討

[摘要]山東移動通信公司 郭彬 ---- 本文通過對CGI和ISAPI的對比以及對ISAPI的工作原理的分析,闡述了使用MFC ISAPI編程的一般方法。 ---- 一、ISAPI簡介: ---- 目前大多數(shù)網(wǎng)站提供信息的方式是由用戶通過客戶瀏覽器(如Netscape或Explorer等)與WWW服務(wù)...

山東移動通信公司 郭彬  

---- 本文通過對CGI和ISAPI的對比以及對ISAPI的工作原理的分析,闡述了使用MFC ISAPI編程的一般方法。

---- 一、ISAPI簡介:

---- 目前大多數(shù)網(wǎng)站提供信息的方式是由用戶通過客戶瀏覽器(如Netscape或Explorer等)與WWW服務(wù)器連接,然后用鼠標點按超級連接以瀏覽相關(guān)的主頁。在此過程中,基本上是服務(wù)器向客戶端單方向的信息傳遞,隨著服務(wù)需求的不斷擴大,這種單純的單方向傳遞信息的靜態(tài)主頁已不能滿足需求。不論是服務(wù)提供方還是客戶,都希望在瀏覽服務(wù)器將信息發(fā)送到用戶同時,用戶端也能將信息發(fā)送到服務(wù)器端,實現(xiàn)服務(wù)器與客戶的交互。典型的應(yīng)用如:用戶登記表、用戶留言板以及用戶通過WWW檢索服務(wù)器端的數(shù)據(jù)庫等等。

---- 要實現(xiàn)一個可與用戶交互信息的服務(wù)系統(tǒng),所需增加的有兩項:交互式主頁和用戶輸入信息處理程序。交互式主頁即有輸入信息的編輯框,選擇菜單按鈕之類的主頁,以供用戶輸入信息;用戶輸入的信息則交由用戶信息處理程序處理。實現(xiàn)該程序可以有多種途徑,該程序可以放在服務(wù)器端,也可以放在客戶機端,前者如CGI、ISAPI,后者如JAVA Applet、javascript等等。

---- ISAPI(即Internet Server Application Program Interface),是微軟提供的一套面向Internet 服務(wù)的API接口,它能實現(xiàn)CGI(Common Gateway Interface,公共網(wǎng)關(guān)接口)能提供的全部功能,并在此基礎(chǔ)上進行了擴展,如提供了過濾器應(yīng)用程序接口。

---- 在Web服務(wù)器這個競爭激烈的領(lǐng)域里,微軟的IIS(Internet Information Server,Internet信息服務(wù)器)是當(dāng)今Windows NT操作平臺上執(zhí)行效率最高的Web服務(wù)器之一。IIS提供所有傳統(tǒng)的內(nèi)容傳遞方式,它對靜態(tài)網(wǎng)頁有著良好的支持。對于更復(fù)雜的應(yīng)用程序,IIS提供了功能更強的應(yīng)用框架:使用ISAPI能夠創(chuàng)造出極高性能的應(yīng)用程序。書寫良好的ISAPI擴展的性能可能超過類似的CGI一個數(shù)量級。此外,ISAPI的靈活性使一些事情變得簡單。

---- ISAPI提供了擴展支持WEB服務(wù)器的簡單而有效的方法。開發(fā)人員可以設(shè)計生成ISAPI 服務(wù)器擴展動態(tài)連接庫(ISAPI Server Extension DLL),它可以被HTTP服務(wù)器調(diào)用。例如,客戶端用戶填寫了一個表單,按下"提交"按鈕后,輸入的數(shù)據(jù)將被傳送至HTTP服務(wù)器,激活相應(yīng)的ISAPI擴展應(yīng)用程序,該應(yīng)用程序可以處理用戶的輸入信息,進行相應(yīng)的操作。或者,按照用戶的要求訪問數(shù)據(jù)庫,讀取用戶指定的數(shù)據(jù),動態(tài)生成HTML文件,再傳回客戶端。

---- CGI很早就作為交互式的Web應(yīng)用程序的一個標準廣泛應(yīng)用在Internet之中。CGI腳本允許人們用多種編程語言如Basic、C、Perl、Shell 等等來編寫簡單的應(yīng)用程序。這些腳本運行在Web服務(wù)器上,而在客戶的Web瀏覽器上輸出運行結(jié)果。客戶的輸入通過環(huán)境變量或者標準輸入設(shè)備來進行傳遞,然后CGI程序根據(jù)需要完成特定的功能,并通過標準輸出設(shè)備送回HTML格式的結(jié)果顯示在客戶的瀏覽器中。CGI的這一特性―設(shè)計簡單,再加上它支持多種編程語言,使得開發(fā)CGI應(yīng)用程序非常簡單。盡管如此,人們在使用中還是發(fā)現(xiàn)了CGI應(yīng)用程序的一個很大的缺點:性能不高。 雖然有不少辦法來使CGI應(yīng)用程序運行得更快一些(如把它們變成編譯好的二進制代碼,而不用Perl腳本),但執(zhí)行速度仍然是一個問題。每當(dāng)通過Web訪問一個CGI程序時,CGI執(zhí)行文件(或者腳本的解釋器)都要為每一個請求創(chuàng)建一個新的進程。對于一個信息量比較大的站點來說,這無疑給服務(wù)器增加了一個沉重的負擔(dān)。

---- 二、ISAPI的工作原理:

---- ISAPI的工作原理和CGI大體上是相同的,都是通過交互式主頁取得用戶輸入信息,然后交服務(wù)器后臺處理。但是二者在實現(xiàn)機制上大相庭徑。ISAPI與CGI最大的區(qū)別在于:在ISAPI下建立的應(yīng)用程序是以動態(tài)連接庫(Dynamic Link Lib,DLL)的形式存在;而CGI的應(yīng)用程序一般都是可執(zhí)行程序。ISAPI應(yīng)用的工作流程與CGI也有一些不同。ISAPI應(yīng)用的DLL不僅可以象CGI程序一樣被用戶請求激活,還可以被系統(tǒng)預(yù)先激活來監(jiān)視用戶輸入;對于被用戶激活的DLL,在處理完一個用戶請求后不會馬上消失,而是繼續(xù)駐留在內(nèi)存中等待處理別的用戶輸入,直到過了一段時間后一直沒有用戶輸入。

---- 一個ISAPI的DLL,可以在被用戶請求激活后長駐內(nèi)存,等待用戶的另一個請求,還可以在一個DLL里設(shè)置多個用戶請求處理函數(shù),此外,ISAPI的DLL應(yīng)用程序和WWW服務(wù)器處于同一個進程中,效率要顯著高于CGI。

---- 不過ISAPI的平臺兼容性較差,目前只能用于微軟自己的Windows 95和NT操作系統(tǒng)上,服務(wù)器平臺也僅限于IIS(Internet Information Server)和MS personal web server以及NT workstation上的peer web server。

---- ISAPI DLLs的調(diào)用方法和CGI一樣:在客戶端使用GET或POST方法。例如,當(dāng)客戶作出下列請求時:

---- ---- http://www.mysite.com/myisa.dll?name=fisherman&id=12345 "name"域和"id"域以及與它們相關(guān)的數(shù)據(jù)都被傳遞給ISA。ISAPI在使用這些相關(guān)的數(shù)據(jù)之前把它們存放在相應(yīng)的數(shù)據(jù)結(jié)構(gòu)中,這是通過一個請求映射系統(tǒng)來實現(xiàn)的。

---- 每一個請求都有一個解析映射表。通過定義服務(wù)器從客戶接收的數(shù)據(jù)的類型和順序,該解析映射表可以把數(shù)據(jù)傳遞到合適的數(shù)據(jù)結(jié)構(gòu)中。例如,對于請求"name=fisherman&id=12345",解析映射表將顯示一個字符串和一個整型數(shù),并且" fisherman " and "12345"將被解析出來存放到各自的數(shù)據(jù)結(jié)構(gòu)中。

---- 解析映射系統(tǒng)還有另外一個功能:ISAPI可以把請求傳遞給ISA內(nèi)特定的成員函數(shù)。請求字符串可以包含一個命令,解析映射表就使用該命令把請求傳遞給ISA內(nèi)正確的成員函數(shù)。

---- 三、MFC的ISAPI編程方法:

---- 1、用戶輸入的方法:

---- Web表單:

---- Web表單(Form)提供了一種與用戶進行交互的方法。它使用"打包"的技術(shù),以收集用戶的輸入,觸發(fā)網(wǎng)絡(luò)服務(wù)器的行為,獲取用戶的響應(yīng),功能類似于Windows中的對話框。

---- 表單使用

標識定義了一個組成表單的HTML網(wǎng)頁的區(qū)域。當(dāng)選擇了表單中的Submit按鈕,兩個標識之間的數(shù)據(jù)輸入就被作為一組發(fā)送到服務(wù)器。典型的設(shè)計如下所示:

< form ACTION="input.dll" METHOD="POST" >
< input TYPE="hidden" NAME="MfcISAPICommand" value="Input" >
.
< input [attribute-list] >
.
  < input TYPE="submit" value="OK" >
  < input TYPE="reset"  value="Reset" >
< /form >

---- 其中"ACTION"屬性指定了ISAPI DLL在服務(wù)器上的存放位置。"METHOD"屬性指出了數(shù)據(jù)將被傳送到服務(wù)器的方式:如果是"GET"方式,數(shù)據(jù)就作為URL的一部分被編碼并發(fā)送到服務(wù)器;如果是"POST"方式,數(shù)據(jù)就作為消息的主體被發(fā)送。
---- < input >標識符用于從用戶收集輸入,輸入類型由"TYPE"屬性決定。由標識符支持的輸入類型如下:

¨ 文本輸入
¨ 口令輸入
¨ 單選按鈕
¨ 復(fù)選框
¨ 圖象輸入
¨ 隱藏域
¨ 提交按鈕
¨ 重置按鈕

---- 這些輸入單元都有以下的形式:
< input type="text" name="EquipName" value="MSC" >
   
---- "name"是給輸入單元一個標識,這個標識將作為ISAPI DLL中響應(yīng)函數(shù)的參數(shù)。"type"是輸入單元的類型,用以區(qū)分以上幾種輸入單元。"value"設(shè)置輸入單元的初始值。
---- 注意上面的HTML源程序,在類型為"hidden"的輸入單元中,定義了服務(wù)器端響應(yīng)此用戶輸入的函數(shù)名。而類型為"submit"和"reset"的兩個輸入單元是兩個按鈕,當(dāng)用戶按下"submit"按鈕,系統(tǒng)就將輸入的內(nèi)容發(fā)送到服務(wù)器端;當(dāng)用戶按下"reset"按鈕,系統(tǒng)就將用戶輸入的內(nèi)容重置為原來的默認值,以便重新輸入。

---- 超級連結(jié):

---- 用戶也可以使用超級連結(jié)的方法來激活一個ISAPI DLL。如下所示:

< a href="browser.dll?mfcISAPICommand
=Browser" >Browser< /a >

---- 這里,隱含地采用了"GET"的方式。在href中指明了ISAPI DLL的模塊名和具體的函數(shù)名。當(dāng)用戶點中了這個超級聯(lián)結(jié),系統(tǒng)就會將用戶的請求發(fā)送到服務(wù)器。
---- 2、MFC中對用戶數(shù)據(jù)輸入的響應(yīng)方法:

---- 從發(fā)布開始,MFC(Microsoft Foundamental Classes,微軟基礎(chǔ)類庫)就被認為是開發(fā)Windows應(yīng)用程序的標準平臺。通過提供更清晰、更簡單的Windows API接口,MFC可以幫助開發(fā)者更快、更簡單地編寫程序。

---- MFC中支持ISAPI的類有:

¨ CHttpServer
¨ CHttpServerContext
¨ CHttpFilter
¨ CHttpFilterContext
¨ CHtmlStream

---- 用戶可以方便地使用"ISAPI Extention Wizard"來生成一個ISAPI DLL的基本框架,然后只要添加自己需要的函數(shù)就可以了。
---- HTML的用戶輸入和命令處理例程是通過一個叫做"MFC PARSEMAP"的數(shù)據(jù)結(jié)構(gòu)來實現(xiàn)解析映射的。在生成的框架中,可以看到形如以下的源程序:

BEGIN_PARSE_MAP(Cbrowser
Extension, CHttpServer)
ON_PARSE_COMMAND(Browser,
CBrowserExtension, ITS_EMPTY)
DEFAULT_PARSE_COMMAND(Browser,
CBrowserExtension)

ON_PARSE_COMMAND(Query,
CBrowserExtension, ITS_PSTR)
ON_PARSE_COMMAND_PARAMS("OfficeName")
END_PARSE_MAP(CBrowserExtension)

它們的含義如下:
BEGIN_PARSE_MAP(Cbrowser
Extension, CHttpServer)和
END_PARSE_MAP(CBrowserExtension):

---- 定義PARSEMAP的開始和結(jié)束。并且指出本DLL所使用的類名及其基類名(一般是CHttpServer)。
---- ON_PARSE_COMMAND(funcName,className,paramList)

---- 定義支持服務(wù)器側(cè)接收用戶輸入的一個函數(shù),以及它所接受的參數(shù)。該函數(shù)與WEB表單的隱含輸入域中定義的"value"值要一致。用戶只要編寫此函數(shù),就可以實現(xiàn)對用戶輸入的響應(yīng)。必須要保證這里定義的參數(shù)與WEB表單中定義的輸入單元是一一對應(yīng)的。

---- ParamList是一個或多個代碼定義的函數(shù)的參數(shù)列表,可用的代碼如下:

代碼   含義  C++中與之對應(yīng)的數(shù)據(jù)類型
ITS_PSTR  字符串  LPCSTR或char * const
ITS_I2     2字節(jié)整數(shù)  Int
ITS_I4     4字節(jié)整數(shù)  long int
ITS_R4    4字節(jié)浮點數(shù)  Float
ITS_R8    8字節(jié)浮點數(shù)  Double
ITS_EMPTY  空的參數(shù)列表

ON_PARSE_COMMAND_PARAMS

---- 該宏定義參數(shù)的名稱,注意要與HTML的表單中各個輸入單元的"name"值保持一致。
---- DEFAULT_PARSE_COMMAND

---- 用于指定如果瀏覽器傳送的表單或超級連結(jié)中沒有包含一個函數(shù)名時,被DLL缺省調(diào)用的函數(shù)名。

---- 3、響應(yīng)函數(shù)的結(jié)構(gòu):

---- 響應(yīng)函數(shù)形如以下結(jié)構(gòu):

void CBrowserExtension::Browser
(CHttpServerContext* pCtxt,…)
{
StartContent(pCtxt);
*pCtxt << "< p >Hello World !< /p >";
//其它的處理。
  EndContent(pCtxt);
}

---- 響應(yīng)函數(shù)總是以StartContent(pCtxt)函數(shù)開始,以EndContent(pCtxt)函數(shù)結(jié)束。*pCtxt的作用是向用戶端傳送數(shù)據(jù)。
---- 服務(wù)器可以對輸入?yún)?shù)進行相應(yīng)處理,并將處理結(jié)果以HTML的形式發(fā)送回用戶端。所以要在此函數(shù)中,要將需要在用戶端顯示的整個網(wǎng)頁的HTML源代碼發(fā)送過去。雖然略顯麻煩,但增加了靈活性,可以按照用戶的輸入來動態(tài)地生成各式各樣的網(wǎng)頁。

---- 使用ISAPI,可以使得靜止的網(wǎng)頁立刻變得豐富多彩起來! 


相關(guān)文章