閱讀本文需要具備基本的Web/CGI 、MFC 以及Visual C++ v4.1或更新版本的知識。
ISAPI 與CGI
很長時期以來,CGI都作為交互web開發的一個標准工具。CGI腳本允許使用者用各種語言來編寫簡單的應用程序,它在網絡服務器上運行並直接輸出到用戶的網絡浏覽器上。用戶的數據通過環境變量或者標准輸入設備輸入,程序則會通過標准輸出返回Html文本。這麼一個簡單的設計,就結合了Perl及TCL語言,也使得CGIs非常簡單易用。
但CGIs也有一個非常大的缺點:性能問題。雖然有很多方法讓CGI運行得更快(例如:用戶可以把CGI寫成可執行的可編譯的語句,而不是PERL腳本),但速度仍是問題所在。每次進入CGI都得通過網絡,可執行CGI仍必須為每一次進入請求創建新的程序。對於一個訪問量大的站點來說,上述方法對於服務器無疑是個巨大的負擔。
當微軟開始研究他們的網絡服務器(MS IIS 或者是 IIS)時意識到CGIS對於大型的網絡服務器來說是個主要的問題所在。
一、進入ISAPI
事實上,ISAPI使用DLL。所用的DLL則會被加載進服務器中。將代碼緩存進內存的作法替代了每請求一次重新加載的做法,此種技術的應用正呈上升趨勢。
ISAPI 的優點
速度
在功能上此優點得到最大體現。
特征
ISAPI可以創建服務器過濾器。完全由MFC集成。
ISAPI的不足
標准性
目前只有少數幾種服務器支持ISAPI
開發的簡便性
文檔非常少,並且調試程序的過程比較枯燥。
二、ISAPI的基本知識
ISA是基本於MFC ChttpServer類別的,CHttpServer 基本上控制了所有的服務器內部交互行為,並包含了用戶要求的所有功能。事實上ISA能夠處理大量的相類似的請求。因此,CHttpServer為每個請求都創建了ChttpServerContext。ChttpServerContext包括了所有的專業化數據以及所有的Html。
ISAPI DLLs是由用戶的需要而開發的,用法與CGI類似。如下例"
http://www.mysite.com/myisa.dll?name=bob&id=15248
"名稱"和"ID"域以及相關數據都進入了ISA,並且數據必須在使用以前被放置進數據庫存中。為加快ISAPI則需要用到 "mapping"系統。
"mapping"系統同樣具有其它功能:ISAPI能引導 請求 到ISA內的專用功能區。"請求"串裡包含了可以令"mapping"系統用於引導"請求"至適當功能區的命令。
因為ISAPI使用了處理"請求"的指令,因此ISA開發系統就給人感覺有點遲緩。但是只要一旦掌握,確是一個處理"請求"的強有力的工具。
設置項目
開發ISA的第一步是建立一個項目工作區。正如其它由Visual C++ (VC++)創立的工作區一樣,有工作向導引導用戶完成最初步驟。選擇New-Project Workspace,選擇"ISAPI Extension Wizard"作為項目種類,命名為"Hello Web",然後點擊創建。
完成上述步驟後,會跳出對話框詢問您願意創建哪種類型的ISA。缺省設置已為ISA配置好,MFC會動態的通過缺省連接。如果您的服務器已安裝MFCDLLS,則上述步驟適用,如果沒有則ISA不會運行。如果項目需要靜態連接。完成上述步驟後,點擊"完成"。 Visual C++ 會提醒您文件正創建中,並會生成ChelloWebExtension。本文裡的所有工作都將在CHelloWebExtension"裡完成。
現在你已建立好一個項目,是時候完成一些ISAPI開發工作了。正如早先提到的,ISA在運行時則會成為IIS的一部份。IIS依次序的運行就象NT服務器一樣。這樣則會使得調試過程變得復雜化。因為VC++的調試系統不能夠控制ISA,當服務器作為一個服務系統時。為了解決這個問題,微軟將IIS分成兩個部份,一個是service,,另一個是可執行的。通過可執行的部份,利用指令行可調節服務器。雖然問題得到了解決並使得開發更為簡便,但是設置以上步驟的過程卻有點枯燥。
當你進入調試部份,在用戶的允許狀態下,VC++ (然後是 IIS)會在用戶的帳戶下運行。然而有些是用戶的指令得不到進入但IIS得執行的部份,因此用戶得做以下步驟:
打開User Manager域工具組(在Administrative Tools program 組)
在PolicIEs菜單中選擇User Rights
打開Show Advanced User Rights欄
在右邊列表中選擇Act as part of the Operating system
點擊Add按鈕以彈出Add Users and Groups對話框。點擊Show Users按鈕,選擇您需要的帳戶。然後點擊Add.
重復相同步驟以生成Generate security audits rights。
以上步驟完成後請退出然再重新登錄,以使程序生效。
IIS包含了FTP Publishing Service, Gopher Publishing Service, World Wide Web Publishing Service等三個Service。一旦調試程序從指令行裡運行IIS,則三個services則會停止運行。
如果用戶想讓程序調試得到合理分配,最好關掉IIS service,轉而使用Services Control Applet,並且禁止自動重啟功能。
一旦當Service關閉,則項目工作區則需按以下步驟來配置
從Build菜單中選擇Settings
點擊Debug標簽並選擇"General Category".
在"Executable for debug session"域中鍵入可執行IIS的位置
在"Program arguments" fIEld中鍵入"-e w3svc"
點擊Link 標簽。
在"Output filename" fIEld中鍵入路徑和文件名。路徑會在站點的目錄樹裡顯示,因此可以通過URL進入。例如:您的站點根目錄是c:www,並且您將"helloweb.dll"放在根目錄裡,因此URL則會是:
http://www.mysite.com/helloweb.dll
請在更改設置後退出登錄並重新登錄。
由ISAPI Extension 向導生成的默認設置包括了編譯ISA的所有細節。現在您已完成配置調試程序的環境,現在可以創建並運行項目。
按F5以打開ISA,當系統詢問是否建立項目時,按YES。
在程序調試創建的幾秒後,IIS會在後台運行。
後將DLL的URL輸入你喜愛的網絡浏覽器,記住在尾部加入一個問號。
則URL會顯示如下:
http://www.mysite.com/helloweb.dll?
第一次連接到ISA會耗費上幾秒。但是DLLS會在執行後進行緩存,因此速度會變得穩定。
在DLL登錄後,將會顯示以下信息:
This default message was produced by the Internet Server DLL Wizard.
Edit your CHelloWebExtension::Default() implementation to change it.
現在你已得到一個工作的ISA
Walking through the base code
當EXTENSION_CONTROL_BLOCK提出請求時,則會傳送到Command Parse Map.。 Parse Map是由一系列的宏所定義的,正如下面所舉的代碼,是從Hello Web項目中復制過來的:
ISA有兩個主要元素:Parse Map 以及 Command Handler 功能。
BEGIN_PARSE_MAP(CHelloWebExtension, CHttpServer)
// TODO: insert your ON_PARSE_COMMAND() and
// ON_PARSE_COMMAND_PARAMS() here to hook up your commands.
// For example:
ON_PARSE_COMMAND(Default, CHelloWebExtension, ITS_EMPTY)
DEFAULT_PARSE_COMMAND(Default, CHelloWebExtension)
END_PARSE_MAP(CHelloWebExtension)
BEGIN_PARSE_MAP標注了parse map的起始處,ISA's ChttpServer 和基類CHttpServer作為參數。
ON_PARSE_COMMAND_PARAMS()表明對指令處理器是一種特殊請求格式或命令,它的參數就是指向的函數的類名和請求的格式。DEFAULT_PARSE_COMMAND說明那個函數被調用,參數是被調用的類名。
Command Handler functions是主函數ChttpServer類的成員函數,parse map通過get方法調用CHttpServer。下面則是Hello Web 的"缺省"指令處理程序:
void CHelloWebExtension::Default(CHttpServerContext* pCtxt)
{
StartContent(pCtxt);
WriteTitle(pCtxt);
*pCtxt << _T("This default message was produced by the Internet");
*pCtxt << _T("Server DLL Wizard. Edit your CHelloWebExtension::Default()");
*pCtxt << _T("implementation to change it. ");
EndContent(pCtxt);
}
當請求為空或包含"Default"這個函數被調用,請求通過ChttpServerContext進入程序體,第一個參數必須是一個ChttpServerContext對象。StartContent()方法在pCtxt中放置<HTML><BODY>,WriteTitle()則是放置 <title>標記。下面 三行語句則寫入缺省消息,並使pCtxt指向CHtmlStream,在ISA處理完成後發送到客戶端。
Hello Web
第一個程序會以"HELLO WEB"替換缺省信息串。
找到CHelloWebExtension class 中的Default() 成員函數,按照下面的方式更改。
void CHelloWebExtension::Default(CHttpServerContext* pCtxt)
{
StartContent(pCtxt);
WriteTitle(pCtxt);
*pCtxt << _T("Hello Web!");
EndContent(pCtxt);
}
創建,運行DLL並從網絡浏覽器重新載入並替換DLL
缺省信息為:
produced by the InternetServer DLL Wizard. Edit
your CHelloWebExtension::Default() implementation to change it.
將會顯示:
Hello Web!
如果出現"Server Error 500: SpecifIEd module not found."提示,您所創建的項目是動態連接,而且缺少必要的DLLs。糾正這個錯誤,就必須使用MFC重新靜態的連接項目。