• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            思勤無邪

            上學(xué)時,因我年齡最小,個頭也最小,上課時,就像大猩猩堆里的猴一般。如今,這猴偶爾也把最近的一些情況寫在這里。

               :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
              132 Posts :: 1 Stories :: 178 Comments :: 0 Trackbacks

            公告

                 吾日常三省吾身,曰思、曰勤、曰無邪。

            積分與排名

            • 積分 - 184864
            • 排名 - 140

            最新隨筆

            最新評論

            閱讀排行榜

            評論排行榜

             

            一、 ISAPI 簡介

            通用網(wǎng)關(guān)接口 CommonGatewayInterface(CGI) 很早就作為交互式的 Web 應(yīng)用程序的一個標(biāo)準(zhǔn)廣泛應(yīng)用在 Internet 之中。 CGI 腳本允許人們用多種編程語言 ( Basic 、 C Perl Shell 等等 ) 來編寫簡單的應(yīng)用程序。這些腳本運行在 Web 服務(wù)器上, 而在客戶的 Web 瀏覽器上輸出運行結(jié)果。客戶的輸入通過環(huán)境變量或者標(biāo)準(zhǔn)輸入設(shè)備來進(jìn)行傳遞, 然后 CGI 程序根據(jù)需要完成特定的操作,并通過 HTML 格式顯示在客戶的瀏覽器中。 CGI 的這一特性給互聯(lián)網(wǎng)帶來了生機,網(wǎng)站的建設(shè)也從此從沉默的處子變?yōu)闊崃业纳倥?,隨著時間的推移,這位曾經(jīng)轟動一時的白雪公主也日益疲乏起來。

            人們在長期的使用中還是發(fā)現(xiàn)了 CGI 應(yīng)用程序的一個很大的缺點:性能不高。 我每請求一次 CGE 程序時, CGI 執(zhí)行文件(或者腳本的解釋器)都要為每一個請求創(chuàng)建一個新的進(jìn)程。對于一個信息量比較大的站點來說,這無疑給服務(wù)器增加了一個沉重的負(fù)擔(dān)。在以后的歲月里,熱鬧的互聯(lián)網(wǎng)又推出了 ASP , JSP 等好多提高安全性及服務(wù)器性能的措施,可其安全性及開發(fā)工具的成熟度遠(yuǎn)遠(yuǎn)不及 VC Delphi 等成功的工具,而作為一個熟悉軟件編程的程序員來說,利用現(xiàn)成的開發(fā)工具及現(xiàn)有的資源開發(fā)一套網(wǎng)站系統(tǒng)更是得心應(yīng)手。

            ISAPI Internet Server Aplication Programing Interfase )就是一種用編程工具進(jìn)行開發(fā),、運行于 NT 服務(wù)的一種標(biāo)準(zhǔn)的編程接口, Web 開發(fā)者可用它編寫交互式應(yīng)用程序。 ISAPI 擴展( Extension )應(yīng)用程序具有 CGI 腳本同樣的功能,但它比 CGI 具有更快、更有效的性能。

            ISAPI for Windows NT 編寫的應(yīng)用程序, Web 用戶可通過填寫 HTML 表單( Form )或單擊 Web 節(jié)點上 HTML 頁面中的鏈接來激活該應(yīng)用程序。服務(wù)器端獲取用戶提供的信息后,被激活的 ISAPI 應(yīng)用程序?qū)Λ@取的信息作出處理。根據(jù) ISAPI 應(yīng)用程序的功能或把獲取的信息存入數(shù)據(jù)庫,或以獲取的信息為條件訪問數(shù)據(jù)庫中的數(shù)據(jù),然后把結(jié)果以 HTML 頁面的形式送回到客戶端。

            ISAPI 的應(yīng)用程序被編譯為動態(tài)鏈接庫( DLL, Dynamic Linked Library ),該庫在 WWW 服務(wù)( Service )啟動時裝載入內(nèi)存。它要求較少的系統(tǒng)開銷,性能明顯優(yōu)于 CGI 應(yīng)用程序。因為每個請求并不啟動單獨的進(jìn)程。而如用 CGI 作交互程序, 每個請求需要啟動單獨的進(jìn)程。 ISAPI 有明顯的性能優(yōu)勢,但其調(diào)試不方面,開發(fā)資料較少, 一直成為開發(fā)人員不優(yōu)選的原因。為了更廣泛地運用 ISAPI ,特作此文,以供廣大開發(fā)者更快地進(jìn)入開發(fā)過程。

            二、一個簡單的 ISAPI 程序

            New,Object,ISAPI Extension Wizard,Object Name 就起個 FirstISAPI,OK, 第二步什么也不要變,點 Finshed 完成。按下 F7 把生成的 DLL 放到 C:inetpubwwwrootfirstisapi 目錄下 ( 建文件夾不用我教吧? ), 打開瀏覽器,在地址欄內(nèi)輸入

            http://127.0.0.1/firstisapi/FirstISAPI.dll

            OK, 我們立馬可以看到如下內(nèi)容: This default message was produced by the  Internet Server DLL Wizard. Edit your CFirstISAPIExtension::Default() implementation to change it.

            你看到了嗎?

            如果你看到了上面這一串英文字符,說明你的服務(wù)器可以用啦。

            如果你看到了一個下載文件對話框,別哭!說明你的服務(wù)器還沒有配置好,下面由我來一步步教你,會用的朋友也別錯過這個好機會!

            開始,程序,管理工具, Internet 服務(wù)管理器,打開左邊樹,找到 默認(rèn) Web 站點下的 firstisapi, 把鼠標(biāo)入在上面單擊右鍵,屬性,在 執(zhí)行許可 里面下拉列表,選中 腳本和可執(zhí)行程序 其他什么也別動(如果你覺得動著好玩的話就動吧, 不過服務(wù)器配置不好了可別怪我沒提前 聲明:) .

            下面我們要做什么呢 ? 忘了 , 等等 ! , 對了 , 點擊 OK, 如果沒有呢 , 你的是中文版吧 , 那就點確定吧 !

            好了 ,http://127.0.0.1/firstisapi/FirstISAPI.dll-->>>

            This default message was produced by the Internet Server DLL Wizard. Edit

            your CFirstISAPIExtension::Default() implementation to change it.

            這回看到了吧 ?

            還沒有 ?

            算了 , 別學(xué) ISAPI , 多煩 , 你不煩我都煩了 , 臭機子 ! ( 想了想 , 這種可能還是有的 , 我還是為人為到底吧 , 免得你又罵娘了 , , 把開光驅(qū) , 2000 的盤放進(jìn)去啊 , 還愣著干么 ? 添加組件 , 重裝一遍你的 INTERNET 服務(wù) !......)

            這回不會不行吧 ? 不行 ?

            如此 , 我們的第一個 ISAPI 就做成了 , 你可以放心的說 , 我會做 ISAPI ........---- ! 這也叫會 ?

            對了 , 忘了 WIN98 的朋友 , 對不起啊 , 你有沒有裝 PWS

            沒有 ?

            那裝一個吧 !

            其他的和 2000 大同小異 , 不用我教吧 ?:):)

            三、 ISAPI 實現(xiàn) 客戶 / 服務(wù)器 交互

            我們現(xiàn)在已經(jīng)可以做一個簡單的 ISAPI 程序了,但是,它什么功能也沒有實現(xiàn), 畢竟我們還沒有加讓它動起來的代碼嘛!

            CFirstISAPIExtension 類里象做一般程序一樣加入一個成員函數(shù)

            void Getdata(CHttpServerContext *pCtxt, char *data);

            然后在 BEGIN_PARSE_MAP(CFirstISAPIExtension, CHttpServer)

            END_PARSE_MAP(CFirstISAPIExtension) 之間加入

            ON_PARSE_COMMAND(Getdata, CFirstISAPIExtension,ITS_PSTR)

            ON_PARSE_COMMAND_PARAMS("data") ,如下所示:

            BEGIN_PARSE_MAP(CFirstISAPIExtension, CHttpServer)

            // TODO: insert your ON_PARSE_COMMAND() and

            // ON_PARSE_COMMAND_PARAMS() here to hook up your commands.

            // For example:

            ON_PARSE_COMMAND(Getdata, CFirstISAPIExtension,ITS_PSTR)

            ON_PARSE_COMMAND_PARAMS("data")

            ON_PARSE_COMMAND(Default, CFirstISAPIExtension, ITS_EMPTY)

            DEFAULT_PARSE_COMMAND(Default, CFirstISAPIExtension)

            END_PARSE_MAP(CFirstISAPIExtension)

            ON_PARSE_COMMAND ON_PARSE_COMMAND_PARAMS 是參數(shù)映射宏, ON_PARSE_COMMAND 的第

            一個參數(shù) Getdata 是要處理事件的函數(shù)名,第二個參數(shù) CFirstISAPIExtension 為以 CHttpServer 為父類的應(yīng)用程序子類,后面的參數(shù)要傳給 Getdata 函數(shù)的參數(shù)列表,它們可以是: ITS_EMPTY 數(shù) 據(jù); ITS_PSTR 串; ITS_I2 short 型; ITS_I4 long 型; ITS_R4 float 數(shù); ITS_R8 double 數(shù)。 參數(shù)的個數(shù)一般與下面 ON_PARSE_COMMAND_PARAMS 解析的參數(shù)相對應(yīng)。我們在這里可以 data 參數(shù)賦給一個初值,當(dāng)我們在瀏覽器里沒有傳上來這個參數(shù)的實際數(shù)值時就是它了。如 data=www.ourcode.net; 這里 data 就是我們定義函數(shù) Getdata 里所要傳入的參數(shù)名。

            有了上面這些準(zhǔn)備工作,下面我們就可以添加代碼了,因為它和平常編程時沒什么兩樣,因此我們就簡單地加上一點代碼看看我們勞動了半天到底做了些什么?

            如下:

            void CFirstISAPIExtension::Getdata(CHttpServerContext *pCtxt, char *data)

            {

            StartContent(pCtxt);// HTML 文件頭

            WriteTitle(pCtxt);// 寫標(biāo)題

            *pCtxt << _T(" 這是你提交上來的數(shù)據(jù): rn");// 向瀏覽器發(fā)送數(shù)據(jù)

            *pCtxt <<data <<"rn";// 寫上一個換行和回車

            EndContent(pCtxt)

            }  

            CHttpServerContext *pCtxt 是一個服務(wù)器上下文標(biāo)志, 我們向瀏覽器傳輸數(shù)據(jù)就全靠

            它。 *pCtxt << 后的字串就是瀏覽器里的 HTML 源碼,因此,你可以把 " 這是你提交上來的數(shù)據(jù):

            rn" ,改成你想要的 HTML ,想怎么改隨你吧?。海?/span>

            現(xiàn)在是不是要按下 F7 了?哈哈,好, F7 ,馬上把 FirstISAPI.dll   Ctrl+C,Ctrl+V........

            " 無法創(chuàng)建或替換 FirstISAPI: 指定的文件正被 Windows 使用 " ,沒法了?我就重起計算機啦,誰教它裝入內(nèi)存呢?。ㄆ鋵嵵灰貑?/span> IIS 或結(jié)束進(jìn)程 Win2003 w3wp.exe Win2000 aspnet_wp.exe

            下面 ISAPI 調(diào)試的文章,不愛老重起計算機的朋友可以看一下。

            ISAPI 在運行時是 IIS 的一部分,而 IIS 又作為 NT 的一個服務(wù)而運行。這一事實使用調(diào)試過程變得復(fù)雜了,因為在 IIS 運行時, VC++ 的調(diào)試器不能夠接管 ISA 。為了解決這個問 題,微軟公司以兩種形式發(fā)行了 IIS :作為一項服務(wù),以及作為一個單獨的可執(zhí)行程序。 對于后一種情況,我們就可以在命令行上來控制服務(wù)器。雖然這樣可以解決上述問題并使得開發(fā)過程變得容易一些,但實現(xiàn)起來顯得很繁瑣。下面我們來介紹這個過程。

            當(dāng)用戶處于 debug 調(diào)試模式時, VC++( 以及 IIS) 將在用戶的帳號和權(quán)限下運行。由于通常 IIS 完成的一些工作是不允許大多數(shù)用戶有相應(yīng)的權(quán)限的,因此用戶(或用戶的系統(tǒng)管理員)需要做以下工作:

            在桌面上選擇 開始程序管 理工具(公用)域用戶管理器 ”, 打開域用戶管理器;

            規(guī)則 菜單中選擇 用戶 權(quán)限

            選擇 顯示高級用戶權(quán)限 查框;

            權(quán)限 下拉列表中選擇 以操作系統(tǒng)方式操作

            選擇 添加 按鈕得到 添加 用戶及組 對話框,選擇 顯示用戶 按鈕,并在 列表中選擇用戶使用的帳號,然后選擇 添加 按鈕;

            選擇 確定 按鈕;

            產(chǎn)生安全審核 權(quán)限重復(fù) 上述步驟。

            為了使這些設(shè)置生效,用戶必 須先退出登錄,然后再登錄回來。

            IIS 中包含了三項服務(wù): FTPPublishing Service,GopherPublishingService WorldWideWeb 。由于調(diào)試器要在命令行上運行 IIS ,所以所有這三項服務(wù)都必須停止。 這可以通過 控制面板 中的 服務(wù) 程序或者使用 IIS “Internet 服務(wù)管理器 來實現(xiàn)。如果需要進(jìn)行大量的調(diào)試工作, 我們建議用戶通過 控制面板 中的 服務(wù) 程序來關(guān)閉 IIS 服務(wù)并禁止它們自動啟動,這樣可以避免用戶每次啟動計算機時都要進(jìn)行關(guān)閉服務(wù)的操作。

            接下來就必須對工程進(jìn)行一些 配置了:

            Project 菜單中選擇 Settings 菜單 項;

            選擇 Debug 面板,并在 Category 下拉 列表中選擇 General

            Executablefordebugsession 框中輸入 或者尋找 IIS 執(zhí)行文件的路徑 (通常情況下位于 WINNTsystem32inetsrvinetinfo.exe );

            Programarguments 框中輸入 -ew3svc ,如 3 所示;圖3  Debug 面板設(shè)置選擇 Link 面板;

            Outputfilename 框中輸入被編譯 后的 DLL 將被放置的路徑和文件名。這個路徑必須位于 Web 服務(wù)器的根目錄下或者某個虛擬目標(biāo)下,以便客戶可 以通過 URL 來訪問。例如,我們的 Web 服務(wù)器的目錄是 c:InetPubwwwrootfirstisapi ,我們把 firstisapi.dll 放置在該目錄下,這樣客戶就可以使用 下面的 URL 來訪問它:

            http://127.0.0.1/firstisapi/firstisapi.dll

            如果用戶現(xiàn)在還沒有退出登錄 以改變權(quán)限,請現(xiàn)在行動,然后再登錄回來。

            如此,我們的服務(wù)器 DLL 就大功告成啦,趕快在瀏覽器里輸入 http://127.0.0.1/firstisapi/firstisapi.dll?Getdata&data= 這是我發(fā)給服務(wù)器的信息!

            OK ?

            這是你提交上來的數(shù)據(jù):

            這是我發(fā)給服務(wù)器的信息!

            OK !

            要是我們想以 FORM 的表單形式向服務(wù)器提交數(shù)據(jù)呢?

            把下面這段 HTML 源碼存為一個 firstisapi.htm 文件,放在 DLL 相同目錄下。

            <form method="post" action="firstisapi.dll?">

            <p align="center">   </p>

            <input type="hidden" name="MfcISAPICommand" VALUE="Getdata">

            <p align="center"> 要提交的數(shù)據(jù): <input type="text" name="data" size="20"></p>

            <p align="center"><input type="submit" value=" 提交 " > </p></form> </body>

            四、 ISAPI 操作數(shù)據(jù)庫

            上面我們定義了一個 Getdata 函數(shù) , 在函數(shù)里我們實現(xiàn)了這樣一個功能 : 把客戶傳送上的數(shù)據(jù)發(fā)給客戶 . 要是操作數(shù)據(jù)庫呢 ? 一樣的道理 , 我們只要在自己定義的函數(shù)里添加上操作數(shù)據(jù)庫的代碼 , 就可以實現(xiàn)存取數(shù)據(jù)庫 . 輸入的數(shù)據(jù)在變量 data 里,輸出給客戶機用 *pCtxt 發(fā)給瀏覽器。

            現(xiàn)在我們建立一個數(shù)據(jù)庫,用什么庫由你選取吧,可以是 ACCESS,SQL Server ,Sbase 等,我們只要用數(shù)據(jù)源來操作它就行了,我們在建好庫后建立系統(tǒng)數(shù)據(jù)源(不要建成用戶數(shù)據(jù)源?。繛槭裁??問比爾 . 蓋茨去吧) FirstODBC, 用下面的 SQL 建立一個簡單的表。

            : 用戶資料

            create table user_info (

            id int (4) not null,

            friend_id int(4) not null,

            user_name varchar (30) not null,

            user_sex varchar (2) not null,

            address varchar (20),

            age int (4),

            zip char (6),

            phone varchar (20) )

            有了數(shù)據(jù)源,我們就可以添加代碼實現(xiàn)數(shù)據(jù)庫的查詢,修改等。同上一節(jié)一樣,在 CFirstISAPIExtension 里添加一個成員函數(shù)

            void Reg(CHttpServerContext *pCtxt,char *user_name,char *sex,char*address,int age,

            char*zip,char*phone)

            參數(shù)分別是 : 用戶名 , 性別 , 地址 , 年齡 , 郵編和電話 . 我們要它實現(xiàn)的功能是把用戶通過表單提交的數(shù)據(jù)寫到 FirstODBC 數(shù)據(jù)庫 . 然后同樣在

            BEGIN_PARSE_MAP(CFirstISAPIExtension, CHttpServer)

            END_PARSE_MAP(CFirstISAPIExtension) 之間加入

            ON_PARSE_COMMAND(Reg, CFirstISAPIExtension,

            ITS_PSTR ITS_PSTR ITS_PSTR ITS_I2 ITS_PSTR ITS_PSTR)

            ON_PARSE_COMMAND_PARAMS("user_name sex address='' age=20 zip='' phone='')

            ,如下所示:

            BEGIN_PARSE_MAP(CFirstISAPIExtension, CHttpServer)

            // TODO: insert your ON_PARSE_COMMAND() and

            // ON_PARSE_COMMAND_PARAMS() here to hook up your commands.

            // For example:

            ON_PARSE_COMMAND(Reg, CFirstISAPIExtension,ITS_PSTR ITS_PSTR ITS_PSTR ITS_I2 I

            ITS_PSTR ITS_PSTR)

            ON_PARSE_COMMAND_PARAMS("user_name sex address age zip phone)

            ON_PARSE_COMMAND(Getdata, CFirstISAPIExtension,ITS_PSTR)

            ON_PARSE_COMMAND_PARAMS("data")

            ON_PARSE_COMMAND(Default, CFirstISAPIExtension, ITS_EMPTY)

            DEFAULT_PARSE_COMMAND(Default, CFirstISAPIExtension)

            END_PARSE_MAP(CFirstISAPIExtension)

            下面我們定義自己的函數(shù)并進(jìn)行數(shù)據(jù)庫的操作 , 單擊左邊 FirstISAPI classes,New Class,

            Name:CUserSet,Base class:CRecordset---------------OK,ODBC:FirstODBC,

            Table Name:user_info,OK.

            ( 請先看看 stdafx.h 里有沒有 #include )

            void Reg(CHttpServerContext *pCtxt,char *user_name,char *sex,char*address,

            int age,char*zip,char*phone)

            {// 打開數(shù)據(jù)庫源代碼

            StartContent(pCtxt); // 打印 <HTML> <BODY> 標(biāo)記

            WriteTitle(pCtxt); // 打印 <TITLE> 標(biāo)題內(nèi)容 </TITLE> 標(biāo)記等

            CDatabase db;

            if(!db.Open(_T("FirstODBC"), // (系統(tǒng)源名)

            FALSE, //bExclusive

            FALSE, //bReadOnly

            _T("ODBC; UID=sa; PWD=;"), //lpszConnect (與數(shù)據(jù)庫的連接方式)

            FALSE))

            { //bUseCursorLib

            *pCtxt << "Could not open database.";

            return;

            }

            CRecordset set(&db);

            try

            {

            set.Open();

            }

            catch (CDBException* pEx)

            {

            *pCtxt << _T("Error Selecting from table:");

            TCHAR szErrorMessage[1024];

            if (pEx->GetErrorMessage(szErrorMessage, sizeof(szErrorMessage)))

            {

            *pCtxt << szErrorMessage;

            *pCtxt << _T("rn");

            }

            return;

            }

            set.AddNew();

            set.Edit();

            set.m_id=0;

            set.m_user_name=user_name;

            set.m_sex=sex;

            set.m_address=address;

            set.m_age=age;

            set.m_zip=zip;

            set.m_phone=phone;

            set.Update();

            set.Close();

            db.Close();

            *pCtxt << _T(" 你已成功注冊 !rn");

            // 打印 </BODY> </HTML> 標(biāo)記

            EndContent(pCtxt);

            }

            把下面的 HTML 存為 reg.htm

            <HTML>

            <BODY>

            <CENTER>

            <FONT COLOR='#FF0000'><H3> 請在下面輸入你的注冊信息 ( * 的為必填內(nèi)容 )</H3>

            </FONT>

            </CENTER>

            <HR>

            <CENTER>

            <form method="post" action="firstisapi.dll?">

            <p align="center">   </p>

            <input type="hidden" name="MfcISAPICommand" VALUE="Reg">

            <p align="center"> 姓名: <input type="text" name="user_name" size="20"></p>

            <p align="center"> 性別:

            <select name="sex" size="1">

            <option selected value="1"> </option>

            <option value="0"> </option>

            </select></p>

            <p align="center"> 地址: <input type="text" name="address" size="20"></p>

            <p align="center"> 年齡: <input type="text" name="age" size="20"></p>

            <p align="center"> 郵編: <input type="text" name="zip" size="20"></p>

            <p align="center"> 電話: <input type="text" name="phone" size="20"></p>

            <p align="center"><input type="submit" value=" 提交 " > </p></form>

            </center>

            </BODY>

            </HTML>

            然后放到 firstisapi 目錄里 ,..................

            http://127.0.0.1/firstisapi/reg.htm 這樣在瀏覽器的表單里輸入你的數(shù)據(jù)后提交 , 看看你我服務(wù)器數(shù)據(jù)庫 , , 有了 -----------> 你已成功注冊 !! 本想再做一個查詢程序 , 可是時間太緊 , 還是自己想想吧 , 和注冊程序沒什么兩樣 , 只要再加一個 Chaxun(...) OK That is all right! 程序還有一些不完美的地方就是還不能檢驗用戶名是否已被注冊,還沒有到得 ID 的最大值,不過在此只是為了演示如何操作數(shù)據(jù)庫,筆者因此沒有深慮,有興趣的朋友自己可以加上這方面的代碼。

            五、利用 ISAPI 進(jìn)行網(wǎng)絡(luò)數(shù)據(jù)傳送

            所謂網(wǎng)絡(luò)數(shù)據(jù)傳送 , 簡單地說 , 就是把數(shù)據(jù)從一臺計算機傳輸?shù)骄W(wǎng)絡(luò)上的另外一臺計算機 . 說起數(shù)據(jù)傳輸 , 大家最熟的不過 socket 套接字了 , 無論在 UNIX,WINDOWS, 它一貫都是公認(rèn)的傳輸方案 . 筆者在研究了 ISAPI 之后 , 成功地實現(xiàn)了用 ISAPI 進(jìn)行網(wǎng)絡(luò)數(shù)據(jù)傳輸 , 并且解決了局域網(wǎng)防火墻內(nèi)數(shù)據(jù)的有效傳輸 .

            首先 , 我們要建立服務(wù)器數(shù)據(jù)接收 ISAPI 程序 . 在第三節(jié) <ISAPI 實現(xiàn) 客戶 / 服務(wù)器 交互 > 里我們已經(jīng)建立了一個 Getdata(..char *data) 函數(shù) , 其中 data 里存放的就是我們從客戶機傳上來的數(shù)據(jù) , 在這個函數(shù)里 , 我們就可以對它進(jìn)行處理 , 如寫文件 , 寫數(shù)據(jù)庫等 , 再通過 *pCtxt 向客戶發(fā)送回執(zhí) . 關(guān)于如何寫庫寫文件已超出本節(jié)范圍 , 在此不再贅述。

            在第三節(jié)里,我們是通過 FORM 表單通過瀏覽器把數(shù)據(jù)發(fā)送給服務(wù)器,在這里,我們要通過我們客戶機的程序向服務(wù)器發(fā)送數(shù)據(jù)。在你的程序里添加一個成員函數(shù):

            BOOL SendData(char *ip,char *request, char *buffer, unsigned int bufferlen)

            其中參數(shù) ip 為服務(wù)器 IP 地址,如果是本機調(diào),傳入 127.0.0.1;request 為要發(fā)送到服務(wù)器的數(shù)據(jù),最終由 Getdata ()接收,存放在 data 里供服務(wù)器處理程序處理 ;buffer 為服務(wù)器傳回回執(zhí)存放綬沖區(qū),即 *pCtxt 串行回的數(shù)據(jù) bufferlen buffer 綬沖區(qū)長度。 SendData 代碼如下:

            BOOL SendData(char *ip,char *request, char *buffer, unsigned int bufferlen)

            {

            int ret=0;

            CString URL;

            URL="http://";

            URL+=(CString)ip;

            URL+="/firstisapi/firstisapi.dll?Getdata&data=";

            URL+=(CString)request;

            //

            //AfxMessageBox(URL);

            CInternetSession session;

            CInternetFile *cf;

            //----------------

            try

            {

            cf = (CInternetFile * )session.OpenURL (URL);

            }

            catch (CInternetException * Exp)

            {

            char err[1024];

            Exp->GetErrorMessage (err, 1024, NULL);

            AfxMessageBox(err);

            cf = NULL;

            Exp->Delete ();

            }

            if (cf)

            {

            ret=cf->Read(buffer, bufferlen);

            cf->Close ();

            }

            session.Close ();

            return(ret);

            }

            這樣我們在程序里可以這樣調(diào)用它:

            void CSassDlg::OnButton1()

            {

            // TODO: Add your control notification handler code here

            CString ip="127.0.0.1",data=" 這是我要發(fā)給服務(wù)器的數(shù)據(jù) ",buffer;

            BOOL b=SendData((char *)LPCTSTR(ip),(char *)LPCTSTR(data),

            buffer.GetBuffer(1204), 1024);

            if(b)

            {

            MessageBox(" 數(shù)據(jù)發(fā)送成功 ");

            }

            }

            這樣,我們只要把要發(fā)送給服務(wù)器的數(shù)據(jù)傳給 SendData 的第二個參數(shù),服務(wù)器 data 就可收到,你想怎么處理就怎么處理吧。

            六、 ISAPI 傳輸數(shù)據(jù)的加密

            為了提高數(shù)據(jù)傳的安全性,可靠性,我們在數(shù)據(jù)傳輸之前都要對數(shù)據(jù)進(jìn)行加密,但是無論哪種加密算法,進(jìn)行加密的數(shù)據(jù)都有可能出現(xiàn)諸如 "@#$%^&*-+" 及不可字符,可是用 ISAPI 這種方法傳輸時, 服務(wù)器經(jīng)過 ON_PARSE_COMMAND ON_PARSE_COMMAND_PARAMS 參數(shù)映射宏進(jìn)行處理后,如 "%,&" 等字符將會進(jìn)行自動轉(zhuǎn)換或作為分隔字符處理 , 這樣, 服務(wù)器收到的數(shù)據(jù)將會是錯誤的。為了保證數(shù)據(jù)傳輸?shù)目煽啃裕P者經(jīng)過多方面研究,自己定義了下面兩個函數(shù),分別作為客戶機加密后上傳前數(shù)據(jù)處理和服務(wù)器接收到數(shù)據(jù)后解密前處理??蛻魴C加密后上傳前數(shù)據(jù)處理函數(shù):

            void code(char *buf, int len, char *outstr)// 加密后處理

            {

            CString str;

            int outstr_len;

            outstr_len=0;

            char *tmp;

            tmp=new char[16];

            outstr[0]=0;

            for (int i=0; i<len ;i++)

            {

            tmp[0]=0;

            if(buf[i]=='%'||buf[i]=='&'||

            buf[i]=='!'||buf[i]=='?'||

            buf[i]=='+'||buf[i]==''||

            buf[i]=='/')

            {

            str.Format("%%%x",buf[i]);

            strcpy(tmp,str);

            outstr_len+=3;

            }

            else

            {

            tmp[0]=buf[i];

            tmp[1]=0;

            outstr_len++;

            }

            if (buf[i]=='$')

            {

            strcpy(tmp,"$$");outstr_len+=2;}

            if (buf[i]==0)

            {

            strcpy(tmp,"$0");outstr_len+=2;

            }

            strcat(outstr,tmp);

            }

            return;

            }

            其中 buf 為傳入數(shù)據(jù)綬沖區(qū)指針, len buf 數(shù)據(jù)長度, outbuf 為處理后數(shù)據(jù)存放綬沖區(qū) . 處理時將諸如 "%,&,+" 等特殊字符及 0 字符進(jìn)行處理,這樣, 數(shù)據(jù)傳送到服務(wù)器后將會是正確的,之后經(jīng)過服務(wù)器處理函數(shù)進(jìn)行還原,再解密,那我們的數(shù)據(jù)就不會有錯了。

            服務(wù)器接收到數(shù)據(jù)后解密前處理函數(shù):

            int decode(char *buff, int len, char *outstr)

            // 上傳后處理

            {

            int i, p;

            char v;

            p=0;

            for (i=0; i<len; i++)

            {

            if (buff[i]=='$')

            {

            if (buff[i+1]=='$')

            {

            v='$';

            }

            else

            {

            if(buff[i+1]=='0')

            v=0;

            }

            i++;

            }

            else

            {

            v = buff[i];

            }

            outstr[p]=v;

            p++;

            }

            return(p);

            }

            其中 buff 為傳入數(shù)據(jù)綬沖區(qū)指針, len buff 數(shù)據(jù)長度, outstr 為處理后數(shù)據(jù)存放綬沖區(qū) .

            處理流程:對 Data 進(jìn)行加密 -->code 函數(shù)進(jìn)行處理 --> 服務(wù)器接到 data-- >decode 進(jìn)行上傳后處理 --> 解密

            七、 ISAPI 網(wǎng)絡(luò)數(shù)據(jù)傳送進(jìn)階(網(wǎng)絡(luò)大數(shù)據(jù)包傳送)

            筆者曾嘗試用上述方法傳輸大數(shù)據(jù)包,可是發(fā)現(xiàn)這種方法只可傳輸小于 2K 的數(shù)據(jù)包,這無疑成為它一個缺點。經(jīng)過多方面的研究,發(fā)現(xiàn)這種方法是用 GET 方法發(fā)送數(shù)據(jù), 操作系統(tǒng)本身就限制了它的數(shù)據(jù)量。以后經(jīng)過測試,如用 POST 方法傳輸,發(fā)送數(shù)據(jù)包的大小將不受限制。下節(jié)將講解如何用 POST 方法向服務(wù)器發(fā)送數(shù)據(jù)。

            BOOL PostData(char *ip,char *request,char *out_buf,int buf_len)

            {

            BOOL ret=FALSE;

            char *buffer,*buff,*out;

            buffer=new char[2048];

            int bb_len=strlen(request);

            buff=new char[bb_len];

            out=new char[bb_len+1000];

            CInternetSession session;

            CHttpFile* pFile=NULL;

            CHttpConnection* pConnection=NULL;

            CString m_ip,sql;

            m_ip=(CString)ip;

            //---------------------------- request 加密

            strcpy(buff,request);

            for(int i=0;i<bb_len;i++)//

            buff[i]=buff[i]^(char)((i+0x56)%255);

            code (buff,bb_len,out);// 上傳前處理

            //-----------------------------------

            sql=(CString)out;

            CString strHeaders =_T("Content-Type: application/x-www-form-urlencoded");

            CString str,strFormData = _T("data=");

            strFormData+=sql;

            try

            {

            pConnection =

            session.GetHttpConnection(m_ip);

            pFile =

            pConnection->OpenRequest(CHttpConnection::HTTP_VERB_POST,

            _T("/firstisapi/firstisapi.dll?Getdata"));

            BOOL result = pFile->SendRequest(strHeaders,

            (LPVOID)(LPCTSTR)strFormData, strFormData.GetLength());

            DWORD dwRet;

            pFile->QueryInfoStatusCode(dwRet);

            //--------------

            if (dwRet == HTTP_STATUS_OK)

            {

            buf_len=pFile->Read(buffer,2048);

            str=(CString)buffer;

            str=str.Left(buf_len);

            ret=TRUE;

            }

            else

            str=" 服務(wù)器處理錯誤! ";

            pFile->Close ();

            delete pFile;

            pConnection->Close();

            delete pConnection;

            }

            catch(CInternetException* pEx)

            {

            TCHAR szErr[1024];

            pEx->GetErrorMessage(szErr, 1024);

            str=szErr;

            pEx->Delete();

            }

            catch (...)

            {

            str=" 和服務(wù)器通信時發(fā)生意外! ";

            }

            session.Close();

            strcpy(out_buf,str);

            buf_len=str.GetLength ();

            MessageBox(NULL, str, " 系統(tǒng)提示 ", MB_OK);

            delete buffer;

            delete buff;

            delete out;

            return ret;

            }

            其中參數(shù) ip 為服務(wù)器 IP 地址,如果是本機調(diào),傳入 127.0.0.1; request 為要發(fā)送到服務(wù)器的數(shù)據(jù),最終由 Getdata ()接收,存放在 data 里供服務(wù)器處理程序處理 ;buffer 為服務(wù)器傳回回執(zhí)存放綬沖區(qū),即 *pCtxt 串行回的數(shù)據(jù) bufferlen buffer 綬沖區(qū)長度。服務(wù)器接收程序同前,這樣,我們就可以發(fā)送大于 2K 的數(shù)據(jù)了。

             

            posted on 2006-05-31 17:43 思勤無邪 閱讀(4629) 評論(12)  編輯 收藏 引用 所屬分類: C++ 、其他與技術(shù)相關(guān)

            Feedback

            # 很不錯的東西 2006-09-12 16:38 @read
            雖然簡單但是實用,  回復(fù)  更多評論
              

            # re: 整理的一些ISAPI編程基礎(chǔ) 2007-03-06 14:21 CUNSHAN
            謝謝  回復(fù)  更多評論
              

            # re: 整理的一些ISAPI編程基礎(chǔ) 2007-06-08 10:59 niunv
            我想請問一下,我在調(diào)試注冊那一段的時候,提交注冊運行到添加記錄這部分時一直沒有反應(yīng),再刷新提交就提示

            服務(wù)器錯誤
            服務(wù)器遇到內(nèi)部錯誤或錯誤配置無法完成該請求.

            如果把這段代碼去掉,則運行是正常的..加上以后就不行了,請問這個要怎么解決呢.我的表是把id設(shè)置為自增的,所以我有改過CUserSet,去掉了ID字段.
            set.AddNew();

            set.Edit();

            set.m_user_name=user_name;

            set.m_user_sex=sex;

            set.m_address=address;

            set.m_age=age;

            set.m_zip=zip;

            set.m_phone=phone;

            set.Update();   回復(fù)  更多評論
              

            # re: 整理的一些ISAPI編程基礎(chǔ) 2007-06-08 11:48 niunv
            我的問題已解決,我修改初始化時m_nDefaultType = dynaset;就可以更新了.之前我沒有在AddNew的地方進(jìn)行try調(diào)試,就顯示
            服務(wù)器錯誤
            服務(wù)器遇到內(nèi)部錯誤或錯誤配置無法完成該請求.
            這樣,加了調(diào)試以后就提示記錄集為只讀,查了一下MSDN修改m_nDefaultType 就好了.還有,set.Edit();這句我刪除了..
            初學(xué),讓你笑話了,請多見指點!謝謝你提供這么好的例子,讓我一下子在腦子里有了比較實際的概念,前段時間看的一些教程什么的,總是看不懂是怎么回事,你的這篇文章讓我覺得講得通欲易懂,又能理解ISAPI編程的思想.謝謝!!  回復(fù)  更多評論
              

            # re: 整理的一些ISAPI編程基礎(chǔ) 2007-06-08 11:59 niunv
            是通俗易懂,打錯字了,..
            還有個問題想請教一下,就是CDatabase.ExecuteSQL()直接執(zhí)行insert的話要好一點嗎?你能講講為什么這里要通過AddNew()來添加呢?是因為派生類里的DoFieldExchange嗎?  回復(fù)  更多評論
              

            # re: 整理的一些ISAPI編程基礎(chǔ) 2008-04-06 17:54 jevinss
            D:\Program Files\Microsoft Visual Studio\MyProjects\Pisapi\Pisapi.cpp(183) : error C2039: 'm_user_name' : is not a member of 'CRecordset'
            d:\program files\microsoft visual studio\vc98\mfc\include\afxdb.h(564) : see declaration of 'CRecordset'
            D:\Program Files\Microsoft Visual Studio\MyProjects\Pisapi\Pisapi.cpp(185) : error C2039: 'm_sex' : is not a member of 'CRecordset'
            d:\program files\microsoft visual studio\vc98\mfc\include\afxdb.h(564) : see declaration of 'CRecordset'
            D:\Program Files\Microsoft Visual Studio\MyProjects\Pisapi\Pisapi.cpp(187) : error C2039: 'm_address' : is not a member of 'CRecordset'
            d:\program files\microsoft visual studio\vc98\mfc\include\afxdb.h(564) : see declaration of 'CRecordset'
            D:\Program Files\Microsoft Visual Studio\MyProjects\Pisapi\Pisapi.cpp(189) : error C2039: 'm_age' : is not a member of 'CRecordset'
            d:\program files\microsoft visual studio\vc98\mfc\include\afxdb.h(564) : see declaration of 'CRecordset'
            D:\Program Files\Microsoft Visual Studio\MyProjects\Pisapi\Pisapi.cpp(191) : error C2039: 'm_zip' : is not a member of 'CRecordset'
            d:\program files\microsoft visual studio\vc98\mfc\include\afxdb.h(564) : see declaration of 'CRecordset'
            D:\Program Files\Microsoft Visual Studio\MyProjects\Pisapi\Pisapi.cpp(193) : error C2039: 'm_phone' : is not a member of 'CRecordset'
            d:\program files\microsoft visual studio\vc98\mfc\include\afxdb.h(564) : see declaration of 'CRecordset'
            Error executing cl.exe.
            Creating browse info file...

            Pisapi.dll - 6 error(s), 0 warning(s)


            這是什么原因?老是通不過?  回復(fù)  更多評論
              

            # re: 整理的一些ISAPI編程基礎(chǔ) 2008-04-06 22:10 超人
            你沒有把'm_user_name' 、'm_sex' 、'm_address' 、'm_age' 、'm_zip' 、'm_phone' 設(shè)置成為CRecordset' 的成員啊?你看一看它們放到哪里去了吧@jevinss
              回復(fù)  更多評論
              

            # re: 整理的一些ISAPI編程基礎(chǔ) 2008-04-15 18:43 jevinss
            服務(wù)器遇到內(nèi)部錯誤或錯誤配置無法完成該請求. 還是不行啊,,誰來幫幫我???...  回復(fù)  更多評論
              

            # re: 整理的一些ISAPI編程基礎(chǔ) 2008-04-16 11:15 jevinss
            我的IIS是裝在另外一臺機子上,是不是ODBC在別的機子上就不能連接啊?  回復(fù)  更多評論
              

            # re: 整理的一些ISAPI編程基礎(chǔ) 2008-04-17 21:37 hexing
            我快要瘋了,弄了兩天,一直都是內(nèi)部錯誤....反正就是加不到到數(shù)據(jù)庫里面去,跪求高手幫我一下啊!!  回復(fù)  更多評論
              

            # re: 整理的一些ISAPI編程基礎(chǔ) 2008-04-19 15:27 tign

            ISAPI技術(shù)群


            QQ群號:60328982   回復(fù)  更多評論
              

            # re: 整理的一些ISAPI編程基礎(chǔ) 2008-04-30 19:07 qqqqqqqqqq
            我想請問一下,ISAPI中如何利用 catch ()來輸出異常啊?  回復(fù)  更多評論
              

            欧美激情精品久久久久久| 中文字幕久久亚洲一区| 久久久无码一区二区三区| 久久久久无码精品国产| 国产精品成人久久久久三级午夜电影| 国内精品伊人久久久久影院对白| 亚洲AⅤ优女AV综合久久久| 色综合久久久久综合体桃花网| 国产成人久久精品区一区二区| 久久精品国产精品亚洲下载| 2020国产成人久久精品| 久久香蕉国产线看观看乱码| 久久久久人妻一区精品果冻| 久久国产色AV免费看| 青草久久久国产线免观| 久久er热视频在这里精品| 日韩欧美亚洲国产精品字幕久久久| 久久久噜噜噜www成人网| 久久综合一区二区无码| 久久精品一区二区国产| 亚洲AV无一区二区三区久久| 久久久精品波多野结衣| 狠狠色丁香久久婷婷综| 久久精品国产99久久久古代| 久久综合狠狠综合久久97色| 成人国内精品久久久久影院VR| 青草国产精品久久久久久| 伊人久久大香线蕉无码麻豆| 精品国产乱码久久久久久浪潮| 99久久99这里只有免费费精品| 一本色道久久88精品综合| 青青草原综合久久大伊人导航| 久久久久久国产a免费观看不卡| 久久精品九九亚洲精品天堂| 久久久久无码精品国产| 久久婷婷五月综合97色| 久久久久人妻精品一区| 国产一级做a爰片久久毛片| 久久精品中文无码资源站| 久久久国产精品亚洲一区| 国产精品久久久久久吹潮|