⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 20000806004.htm

📁 C++Builder教学大全
💻 HTM
字号:
<HTML>

<HEAD>



<TITLE>用C++Builder开发ISAPI扩展应用程序</TITLE>



<META content="MSHTML 5.00.2314.1000" name=GENERATOR>

</HEAD>

<BODY aLink=#FF0000 bgColor=#ffffff leftMargin=0 link=#187800 topMargin=0 

vLink=#990099>



<div align="center">

  <table width="744" border="0" cellspacing="0" cellpadding="0" height="76">

    <tr> 

      <td> 

        <p align="center"><b><br>

          <font size="3"> 用C++Builder开发ISAPI扩展应用程序</font></b></p>

        <p>一、ISAPI概述 Microsoft的WEB服务器提供了不同的ISAPI,应用ISAPI能够开发出高性能的应用程序。 </p>

        <p>ISAPI具有两类组件:ISAPI扩展和ISAPI过滤器,本文着重介绍ISAPI扩展的应用和开发。</p>

        <p>ISAPI应用程序通过DLL实现,DLL的特性使它能够作为WEB服务器自身的扩充来装载。在 WEB服务器的地址空间运行, 而且只在第一次请求时装载一次,以后每一个后续请求通 

          过创建一个线程(仅用一个简单的函数调用) 来完成,这比CGI创建一个进程要节约大量 的时间和空间等资源。</p>

        <p>ISAPI扩展通常代替传统Web应用程序中CGI脚本的位置,由客户触发,为其特殊请求服务。</p>

        <p>------清单1--------------</p>

        <p>1.&lt;html>&nbsp;<br>

          2. &lt;img src="myGetGrp.dll"><br>

          3.&lt;/html></p>

        <p>如清单1所示代码,服务器将调用myGetGrp.dll中提供的函数得到一GIF图像文件数据发 送给客户浏览器,在这里,myGetGrp.dll就是一个ISAPI扩展。</p>

        <p>如果服务器确定将执行一个ISAPI扩展, 他首先检查此扩展是否已经装入高速缓存,若 没有,则指定的DLL被装载;装入DLL后,服务器就调用DLL中的HttpExtensionProc()函 

          数对请求提供服务, 这里是ISAPI程序员放置具体功能操作的位置,服务器将所有必要 的信息通过一结构类型参数传递给这个函数,包括请求本身的内容和程序员将用到的回 

          调函数等,用回调函数,可以将数据传递给用户以及执行其他的操作。</p>

        <p>注意:必须牢记服务器是启动多线程来处理同时接收到的多个请求的,所以必须正 确处理线程间的同步,否则将会导致数据破坏甚至系统崩溃。</p>

        <p>二、用C++ Builder开发ISAPI扩展应用程序 C++ Builder是Inprise公司继Delphi之后开发的又一个通用的客户/服务器结构的 

          开发工具。 它使用了C++语言,可以产生更快速和更高效的代码。目前已成为继Visual Basic、Delphi之后,在32位Windows环境下最具有吸引力的开发工具之一。</p>

        <p>启动C++ Builder后,用File→New菜单项打开New Items对话框,在New页面下选中 Web Server Application选项,单击&lt;OK&gt;按纽,弹出一New 

          Web Server Application对 话框,选中ISAPI/NSAPI Dynamic将生成一ISAPI扩展应用程序框架,其主模块缺省名为 

          Project.cpp,其中主要实现了DLL的三个输出函数,说明如下:</p>

        <p>1.1 GetExtensionVersion()函数 这是一个非常简单的函数, 它唯一的目的是指定ISAPI版本,并给出扩展的描述。 

          当DLL第一次被装载时,由服务器调用。这发生在HttpExtensionProc()函数第一次调用 前, 在此函数中, 你所需做的全部就是用常量HSE_VERSION_MAJOR和HSE_VERSION_ 

          MINOR(在Isapi2.hpp中定义)设置扩展版本域。并且返回一true值。</p>

        <p>GetExtensionVersion()函数实现实例见清单2。</p>

        <p>---------清单2-----------------</p>

        <xmp> BOOL_export WINAPI GetextensionVersion(Isapi2::THSE_VERSION_INFO 

        &amp;Ver) { /*设置扩展版本域*/ Ver.dwExtensionVersion=MAKELONG(HSE_VERSION_MAJOR,HSE_VERSION_MINOR); 

        Ver.lpszExtensionDesc=&quot;Example ISAPI extension&quot;;//设置扩展描述域 return 

        true; //返回true } </xmp> 

        <p>在此函数中,程序员还可以加入初始化代码,如全局变量的初始化等。</p>

        <p>1.2 HttpExtensionProc()函数</p>

        <p>HttpExtensionProc() 函数是扩展的功能实现部分,每次产生对扩展的请求,服务 器就调用这个函数,同时传递一类型为TEXTENSION_CONTROL_BLOCK结构的参数(ECB) 

          , 这个结构在Isapi2.hpp中定义:</p>

        <xmp> struct TEXTENSION_CONTROL_BLOCK { unsigned cbSize;//结构大小 unsigned 

        dwVersion;//版本信息 unsigned ConnID; /*正在被服务的连接的ID;调用回调函数时必须作为一参数传递*/ unsigned 

        dwHttpStatusCode;/*在HttpExtensionProc () 函数返回前,在此放置HTTP状态码,参见HTTP1.0规范定义*/ 

        char lpszLogData[80];//接收一记录信息字符串 char *lpszMethod;//命名请求方式的字符串的指针 char 

        *lpszQueryString;//含一个GET请求查询的字符串指针 char *lpszPathInfo;//请求的字符串的指针 char 

        *lpszPathTranslated;//把请求的字符串指针翻译为服务器的物理路径 unsigned cbTotalBytes;//请求中字节的全部数目 

        unsigned cbAvailable;//lpbData缓冲区长度 void *lpbData;//POST请求的数据缓冲区指针 char 

        *lpszContentType;//识别请求的MIME内容类型的指针 TGetServerVariableProc GetServerVariable; 

        /*检索服务器变量值的回调函数指 针*/ TWriteClientProc WriteClient;//写数据给用户的回调函数的指针 TReadClientProc 

        ReadClient;//检索用户数据的回调函数指针 TServerSupportFunctionProc ServerSupportFunction; 

        /*支持其他操作的回调函数指针*/ }</xmp> 

        <p>这种结构包含服务请求和回调函数指针所需得信息,你可以调用它来获取信息或执 行操作,下面对其中的回调函数作一说明:</p>

        <p>(1)GetServerVariable函数</p>

        <p>原型为:</p>

        <p>typedef BOOL _stdcall (*TgetServerVarableProc) (int hConn,*VariableName, 

          void *Buff,int &amp;Size);</p>

        <p>调用这个函数来获取服务器变量(如CONTEXT_TYPE)和同请求一起收到的头部。如通 过请求, 则得到HTTP_COOKIE来检索Cookies头部的内容。参数说明:hConn为传入参数 

          ECB的连接句柄ConnID;VariableName为要检索的变量的名字(如HTTP_COOKIE);Buffer为 接收变量的缓冲区指针;Size为缓冲区大小,若由于缓冲区空间不够而失败,该值被改 

          变为必要的缓冲区大小。</p>

        <p>(2)WriteClient函数</p>

        <p>原型为:</p>

        <p>typedef BOOL _stdcall (*TWriteClientProc) (int ConnID,void *Buffer,int 

          &amp; Bytes,int dwReserver)</p>

        <p>调用这个函数来发送响应内容给用户, 参数说明:ConnID为传入参数ECB中的连接 句柄ConnID; Buffer为包含写数据缓冲区的指针; 

          Bytes为缓冲区数据的字节数; dwReserver保留。</p>

        <p>(3)ReadClient函数</p>

        <p>原型为:</p>

        <p>typedef BOOL _stdcall (*TReadClientProc) (int ConnID, void *Buffer,int 

          &amp; Size)</p>

        <p>调用这个函数读取用户的附加数据,通过检验ECB中cbAvailable和cbTotalBytes的 值来确定是否调用此函数, 若cbTotalBytes大于cbAvailable;就表明有更多的数据需 

          要调用该函数去读取。 参数说明:ConnID为传入参数ECB中的连接句柄ConnID;Buffer 为读入数据存放的缓冲区;Size在调用时,传入Buffer缓冲区的大小,返回时,等于实 

          际读取的字节数。</p>

        <p>(4)ServerSupportFunction函数</p>

        <p>原型为:</p>

        <p>typedef BOOL _stdcall (*TServerSupportFunctionProc) (int hConn, int 

          HSERRequest,void buffer,int &amp;Size,PDWORD DataType);</p>

        <p>这个函数实现其他一些操作,参数说明:hConn为传入参数ECB的连接句柄ConnID, HSERRequest为要实现操作的常量值。Size为Buffer缓冲区的大小,Buffer缓冲区指针; 

          DataType为数据类型指针;其中Buffer和DataType的含义根据HSERRequest的值变化。</p>

        <p>下面说明这个函数的几个主要操作(也就是HSERRequest的可用值,在Isapi2.hpp中 定义),以及对应不同的操作,参数Buffer,Size,DataType的不同含义:</p>

        <p>●HSE_REQ_SEND_URL_REDIRECT_RESP: 重定向客户浏览器到另一个网址上的URL。 Buffer:指向一重定向目标URL字符串;DataType被忽略。</p>

        <p>●HSE_REQ_SEND_URL: 重定向到本服务器上的一个URL,Buffer: 指向一重定向目标 URL字符串;DataType被忽略。</p>

        <p>●HSE_REQ_SEND_RESPONSE_HEADER:发送响应头部给用户;Buffer: 指向包含头部的 字符串;DataType被忽略。</p>

        <p>●HSE_REQ_DONE_WITH_SESSION: 通知服务器, 异步的请求处理已经完成。 Size, Buffer,DataType均被忽略。</p>

        <p>●HSE_REQ_MAP_URL_TO_PATH: 映射一个逻辑路径到一个物理路径。Buffer:映射在 此缓冲区上完成;DataType被忽略。</p>

        <p>HttpExtensionProc()函数的返回值必须使以下四个值(在Isapi2.hpp中定义)中的一个:</p>

        <p>●HSE_STATUS_SUCCESS:所有进程已完成。</p>

        <p>●HSE_STATUS_SUCCESS_AND_KEEP_CONN:所有进程已经完成,但希望保持连接以继 续进一步的交互。</p>

        <p>●HSE_STATUS_PENDING: 进程未完成。 当扩展异步完成进程时, 将以参数 HSERRequest=HSE_REQ_DONE_WITH_SESSION调用ServerSupportFunction(),以提醒服务 

          器进程已完成。</p>

        <p>●HSE_STATUS_ERROR:进程由于错误已异常终止。</p>

        <p>清单3包含了处理一个&quot;Hello World&quot;网页请求的简单 但必要的逻辑。</p>

        <p>---------清单3------------------------</p>

        <xmp> int _export WINAPI HttpExtensionProc(Isapi2::TEXTENSION_CONTROL_BLOCK 

        &amp;ECB) { char my_string[256]; int length; strcpy(my_string,&quot;200 

        OK/r/nContext-Type:text/html&quot;); length=strlen(my_string); ECB.dwHttpStatusCode=200; 

        ECB.ServerSupportFunction(ECB.ConnID, HSE_REQ_SEND_RESPONSE_HEADER, my_ 

        string,length,NULL);//发送头部 strcpy(my_string,&quot;Hello World!&quot;); 

        length=strlen(my_string); ECB.WriteClient(ECB.ConnID,my_string,length,0); 

        //发送数据给客户浏览器 return(HSE_STATUS_SUCCESS); }</xmp> 

        <p>这是一个简单的例子,实际应用的ISAPI扩展将需要做比这更多的工作。</p>

        <p>与GetExtenVersion()函数和TerninateExtension()函数不同,HttpExtensionProc ()函数对用户的行为产生作用。</p>

        <p>1.3 TerminateExtension()函数</p>

        <p>TerminateExtension() 函数在用户将卸载DLL时被调用,它是可选择的。传入参数 为dwFlages,类型为int,是以下两个值(在Isapi2.hpp中定义)中的一个:</p>

        <p>●请求同意卸载DLL的HSE_TERM_ADVISORY_UNLOAD值。 函数返回true将允许服务器 卸载该DLL。</p>

        <p>●强迫DLL清除并准备被卸载的HSE_TERM_MUST_UNLOAD值。 TerminateExtension()函数对服务器行为产生作用。</p>

        <p>编写完ISAPI扩展应用程序后,用C++ Builder的Project-&gt;菜单项功能,为ISAPI扩 展生成一个DLL,这个DLL就可以直接被作为ISAPI扩展使用。</p>

        <p>2.结束语</p>

        <p>本文介绍的是一种在C++ Builder开发环境下较为复杂的ISAPI扩展的实现方法,这 种方法对理解ISAPI扩展的工作方式有很大帮助,除此以外,在C++ 

          Builder中有更简单 的方法来实现, 即通过使用WebModule, 以及TISAPIApplication、 TISAPIRequest、 

          TISAPIResponse等类。详细方法参见C++ Builder文档。</p>

      </td>

    </tr>

  </table>

 

</div>

</BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -