📄 0503005.htm
字号:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title></title>
<link rel="stylesheet" type="text/css" href="../../vckbase.css">
</head>
<body>
<div align="justify">
<table border="0" width="100%" class="font" height="57">
<tr>
<td width="27%" height="6" class="bigfont" bgcolor="#B8CFE7" align="center" bordercolor="#800080">
<font color="#800080">VC知识库(五)</font>
</td>
<td width="73%" height="6" class="bigfont" bgcolor="#B8CFE7" align="center" bordercolor="#800080">
<font color="#800080">www.vckbase.com</font>
</td>
</tr>
<tr>
<td width="100%" height="4" class="header" valign="top" align="center" colspan="2">
<hr>
</td>
</tr>
<tr>
<td width="100%" height="17" class="header" valign="top" align="center" colspan="2">
<BIG> 利用<FONT class=eng>ISAPI</FONT>开发<FONT
class=eng>CGI</FONT>程序</BIG>
</td>
</tr>
<tr>
<td width="100%" height="17" class="info" align="center" colspan="2">
<SMALL> 闻怡洋 <A
href="http://www.vchelp.net/"><FONT
class=engul>http://www.vchelp.net/</FONT></A></SMALL>
</td>
</tr>
<tr>
<td width="100%" height="22" class="font" colspan="2">
<hr>
</td>
</tr>
<tr>
<td width="100%" height="5" class="font" colspan="2">
<SMALL>
<P>ISAPI(Internet Server
API)最初是微软为IIS服务器所提供的一种CGI应用开发接口,其主要的目的也是为CGI开发提供好的开发接口,如果不负责的讲ISAPI也可以认为是类似WinCGI的一种开发模式,只不过ISAPI通过映射宏来取得用户表单传送的参数。这一点上和MFC消息映射宏很相似。</P>
<P>当然ISAPI的推出同时还具备了很多其他的特性:
<UL>
<LI>ISAPI以DLL动态连接库的方式实现,所以加载较普通的EXE运行程序快,而且系统不会在使用完后马上清除掉DLL在内存中的空间,所以再次使用时会获得更快的速度。
<LI>ISAPI在调用者的内部以线程方式运行,所以和CGI进程相比较需要的运行空间也更小。
<LI>在同一个DLL中可以集中多个处理函数,并且通过映射宏来指明不同的函数分别对什么样的请求来进行处理。
<LI>由于与IIS的集成,所以可以利用ISAPI开发ISAPI过滤器。通过过滤器可以完成例如用户权限检测,数据加密,压缩,日志等功能,IIS服务器的功能也可以通过ISAPI过滤器来得到增强。
</LI></UL>到目前为止,很多非M$的WEB服务器也都添加了对ISAPI的支持。
<P></P>
<P>在同一个DLL中可以集中多个处理函数,所以执行ISAPI的请求和执行普通CGI的请求有一点区别,在URL中需要填写如下形式http://.../cgi-bin/test.dll?function_name&name=xxx&email=yyy,function_name表示的就是功能名称,为了能够正确处理你必须将其映射到DLL中的一个处理函数上。对与未映射的功能都将由一个默认函数处理。</P>
<P>VC4.2以上版本为创建一个ISAPI程序提供了向导程序,在新建工程时选择ISAPI Extension
Wizard并在以后的对话框中选择创建服务器扩展和输入相关的信息就可以了。</P>
<P>一个最简单的ISAPI程序至少包含了一个由CHttpServer类所派生的新类,并且在该类中进行了基本的映射,重载了BOOL
GetExtensionVersion(HSE_VERSION_INFO* pVer)函数和提供了形式如void
Default(CHttpServerContext*
pCtxt)的成员函数。幸运的是向导程序已经为我们做好了这一切并创建了最基本的代码。</P>
<P>Default函数用于处理没有带参数首先我们修改Default函数中的代码,首先我们该写其中的相关代码成为如下: <PRE>void CTestisaExtension::Default(CHttpServerContext* pCtxt)
{
//Print the <HTML> <BODY> tags.
StartContent(pCtxt);
//Print the title.
WriteTitle(pCtxt);
*pCtxt << _T("<p>演示</p>");
*pCtxt << _T("<p>目前是Default成员函数其作用</p>");
//Print </HTML> </BODY> tags.
EndContent(pCtxt);
}
</PRE>然后用以下方式调用:http://.../cgi-bin/test.dll?Default或http://.../cgi-bin/test.dll?。你就会看到输出的HTML页面了。
<P></P>
<P><PRE><FORM ACTION="test.dll?Add" METHOD=POST>
<INPUT NAME="name">
<INPUT NAME="id">
<INPUT TYPE=SUBMIT>
</FORM>
</PRE>上面表单要求用户输入了用户名和ID号,所以传送的数据形式形式应该如同:http://.../test.dll?Add&name=xxx&id=yyy,我们可以通过处理命令映射宏来指明处理命令的函数,然后通过参数映射宏对数据进行分解,分解后的数据将会存放入指定的变量。使用方法为:
<PRE>ON_PARSE_COMMAND(Add, CTestExtension, ITS_PSTR ITS_I4)
ON_PARSE_COMMAND_PARAMS("name id")
</PRE>ON_PARSE_COMMAND宏中需要指明函数名,类名和参数类型列表,ON_PARSE_COMMAND_PARAMS宏中需要根据前一个宏中所列出的参数列表来指明表单中的变量名称列表。最后一步就是定义一个名称与请求URL中?后命令名称相同的成员函数,参数的设置要与ON_PARSE_COMMAND宏中的参数列表定义相符合,在这个例子中为:<BR>void
CTestExtension::Add(CHttpServerContext* pCtxt,LPTSTR
pszName,int iID)。参数类型列表中可以使用下面的类型后面为该类型的说明:
<UL>
<LI>ITS_EMPTY 无数据
<LI>ITS_PSTR 字符串LPCSTR
<LI>ITS_I2 short
<LI>ITS_I4 long
<LI>ITS_R4 float
<LI>ITS_R8 double </LI></UL>
<P></P>
<P>下面我们看一个更复杂的表单,表单定义如下: <PRE><FORM ACTION="test.dll?Delete" METHOD=POST>
<INPUT NAME="name">
<INPUT NAME="month">
<SELECT NAME="mode">
<OPTION VALUE=1>All
<OPTION VALUE=2>Before
<OPTION VALUE=3>After
<INPUT TYPE=HIDDEN NAME=pwd VALUE=xxx>
<INPUT TYPE=SUBMIT>
</FORM>
</PRE>定义映射和处理函数如下:<PRE>ON_PARSE_COMMAND(Add, CTestExtension, ITS_PSTR ITS_I4 ITS_I4 ITS_PSTR)
ON_PARSE_COMMAND_PARAMS("name month mode pwd")
void CTestExtension::Add(CHttpServerContext* pCtxt,LPTSTR pszName,int iMonth,int iMode,LPTSTR pszPwd)。
</PRE>
<P></P>
<P>ISAPI程序的输出:在所有的命令处理函数中第一个参数都是CHttpServerContext*指针,我们所有的输出都要通过它进行,在CHttpServerContext类中定义了<<操作符,通过该操作符我们可以方便的输出字符串,数字,二进制数据。输出的方法为:
<PRE>*pCtxt<<"this is a string";
*pCtxt<<'c';
*pCtxt<<10;
</PRE>可以看得出输出是很简单的,一个完整的输出过程应该是如同下面的形式: <PRE> StartContent(pCtxt);//开始输出
WriteTitle(pCtxt);//输出头部信息,相当于输出<TITLE>
*pCtxt << "your string";
EndContent(pCtxt);//结束输出
</PRE>
<P></P>
<P>我们所使用的ISAPI扩展类是由CHttpServer所派生,可以调用CHttpServer::AddHeader来指明返回数据的类型,例如下面的代码演示了输出纯文本:
<PRE>void CTestisaExtension::Default(CHttpServerContext* pCtxt)
{
AddHeader(pCtxt, "Content-type = text/plain\r\n");
(*pCtxt) << "Hello world!\r\n";
}
</PRE>我们可以重载某些函数来达到加强控制的目的,可重载的函数有以下这些:
<UL>
<LI>virtual LPCTSTR CHttpServer::GetTitle( )
const;返回<TITLE>部分信息
<LI>virtual BOOL CHttpServer::OnParseError(
CHttpServerContext* pCtxt, int nCause );错误处理
<LI>virtual void CHttpServer::StartContent(
CHttpServerContext* pCtxt )
const;输出<HTML><BODY>部分信息
<LI>virtual void CHttpServer::EndContent(
CHttpServerContext* pCtxt )
const;输出</BODY></HTML>部分信息
<LI>virtual void CHttpServer::WriteTitle(
CHttpServerContext* pCtxt )
const;输出<TITLE></TITLE>部分信息 </LI></UL>
<P></P>
<P>此外我们可以在命令处理函数中利用CHttpServerContext指针来得到CGI中的相关环境变量,在CHttpServerContext中有一个成员变量m_pECB为下面的结构指针。
<PRE>typedef struct _EXTENSION_CONTROL_BLOCK {
DWORD cbSize; //IN 该结构长度
DWORD dwVersion //IN 版本
HCONN ConnID; //IN 连接上下文
DWORD dwHttpStatusCode; //OUT 状态码
CHAR lpszLogData[HSE_LOG_BUFFER_LEN]; //OUT
LPSTR lpszMethod; //IN 环境变量REQUEST_METHOD
LPSTR lpszQueryString; //IN QUERY_STRING
LPSTR lpszPathInfo; //IN PATH_INFO
LPSTR lpszPathTranslated; //IN PATH_TRANSLATED
DWORD cbTotalBytes; //IN CONTENT_LENGTH
DWORD cbAvailable; //IN
LPBYTE lpbData; //IN
LPSTR lpszContentType; //IN CONTENT_TYPE
...其他信息在此忽略
} EXTENSION_CONTROL_BLOCK, *LPEXTENSION_CONTROL_BLOCK;</PRE>
</SMALL>
</td>
</tr>
<tr>
<td width="100%" height="12" class="font" colspan="2">
</td>
</tr>
<tr>
<td width="100%" height="6" class="font" colspan="2">
</td>
</tr>
<tr>
<td width="100%" height="8" class="font" colspan="2">
</td>
</tr>
<tr>
<td width="100%" height="17" class="font" colspan="2"></td>
</tr>
</table>
</div>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -