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

📄 55.htm

📁 水木清华的BBS文章
💻 HTM
📖 第 1 页 / 共 3 页
字号:
中的一些域,如下所示。 <br>

  <br>

注意到在这个纪录里有一个叫做WriteClient的函数指针,您可以引用这个函数把信息传 <br>

送回浏览器。当呼叫 <br>

这个函数时,您使用到了下面提到的TExtensionControl块中的ConnID字段。当函数被呼 <br>

叫时,ConnID为您自 <br>

动填充。 <br>

  <br>

在察看函数的代码之前,请让我为您演示所有用到的上文提及的HttpExtensionProc函数 <br>

的ISAPI DLL的完 <br>

整程序 <br>

  <br>

  <br>

library Isapi1; <br>

  <br>

library Isapi1; <br>

  <br>

uses <br>

  Windows, SysUtils, HTTPExt; <br>

  <br>

function GetExtensionVersion( var Ver: THSE_VERSION_INFO ): BOOL; stdcall; <br>

begin <br>

begin <br>

  Ver.dwExtensionVersion := $00010000;  // We're expecting version 1.0 support <br>

  Ver.lpszExtensionDesc := 'Written in Delphi 2.0'; <br>

  Result := True; <br>

end; <br>

  <br>

function HttpExtensionProc( var ECB: TEXTENSION_CONTROL_BLOCK ): DWORD; <br>

stdcall; <br>

var <br>

  ResStr: string; <br>

  StrLen: Integer; <br>

begin <br>

  ECB.lpszLogData := 'Delphi DLL Log'; <br>

  ECB.dwHTTPStatusCode := 200; <br>

  ResStr := ' <br>

' + <br>

            ' <br>

Test server results <br>

' + <br>

            ' <br>

Isapi says hello to DevRel <br>

  <br>

'; <br>

'; <br>

  ResStr := Format( <br>

    'HTTP/1.0 200 OK'#13#10+ <br>

    'Content-Type: text/html'#13#10+ <br>

    'Content-Length: %d'#13#10+ <br>

    'Content:'#13#10#13#10'%s', [Length(ResStr), ResStr]); <br>

  StrLen := Length(ResStr); <br>

  ECB.WriteClient(ECB.ConnID, Pointer(ResStr), StrLen, 0); <br>

  Result := HSE_STATUS_SUCCESS; <br>

end; <br>

  <br>

exports <br>

  GetExtensionVersion, <br>

  HttpExtensionProc; <br>

  <br>

begin <br>

end. <br>

  <br>

为了运行这个DLL程序,您应该把它复制到您的NT服务器下的脚本目录中去。在我的NT4.0 <br>

机器中,它就像这 <br>

样: <br>

  c:\winnt\system32\inetsrv\scripts\mystuff\isapi1.dll <br>

  <br>

  <br>

在这个例子中,我已经创建了我的名为“mystuff”的目录,它只不过是用来存储我创建的 <br>

ISAPI DLLs。您的 <br>

目录,当然和我的机器上的不完全一样,取决于您的“inetsrv”目录位置和其它因素。 <br>

  <br>

为成功调用这个DLL,您应该在您的HTML页上增添这个超链接: <br>

  <br>

  <br>

<A HREF="/scripts/mystuff/isapi1.dll" >ISAPI One</A><BR> <br>

  <br>

  <br>

当用户点击这个超链接时,ISAPI1 Dll会被呼叫,然后字符串“Hello from ISAPI”会显 <br>

示在用户的浏览器 <br>

上。如果您并不是把 ISAPI.DLL放在 mystuff 目录下,那么您应该修改上面的HTML代码 <br>

来使之与您的情况 <br>

适应。注意,您的目录必须与目录 inetsrv 有关,不应,也不能包含您的整个DLL所在的 <br>

目录。 <br>

  <br>

下面是呼叫的完整的HTML脚本: <br>

  <br>

<HTML> <br>

<HEAD> <br>

<TITLE>CharlieC Home Page</TITLE> <br>



</HEAD> <br>

<BODY> <br>

<H1>My Home Page </H1> <br>

<P> <br>

This is the home page for my home computer. <br>

<P> <br>

<A HREF="/scripts/mystuff/isapi1.dll" >ISAPI One</A><BR> <br>

</BODY> <br>

</HTML> <br>

  <br>

注意,如果您多次把程序ISAPI1.DLL复制到 mystuff 目录下,在每一次复制之前您应该 <br>

关掉网络服务器的 <br>

万维网端口。这是因为,在第一次复制这个DLL时,您可以不受限制,但在此之后,它就 <br>

属于服务器了。因 <br>

此,在您复制第一次拷贝的更新版本时,因当关掉万维网服务。您可以使用网络管理程序 <br>

来关掉万维网服 <br>

务。这个程序应该在微软网络管理程序组(Microsoft Internet Server group)下面, <br>

在安装网络信息服 <br>

务时被安装到程序管理器(Explorer/Program Manager)下。 <br>

  <br>

  <br>

与 TExtensionControlBlock 一起工作 <br>

与 TExtensionControlBlock 一起工作 <br>

  <br>

通过本文中的这一要点,您能够建立您的第一个ISAPI DLL,并且能在第二台机器上的网 <br>

页浏览器调用它。 <br>

在本文中接下来的ISAPI的其余部分将会更加深入。 <br>

  <br>

  <br>

这里是HttpExtensionProc参数中比较复杂的部分 <br>

  <br>

  <br>

PExtensionControlBlock = ^TExtensionControlBlock; <br>

TExtensionControlBlock = packed record <br>

  cbSize: DWORD;           // = sizeof(TExtensionControlBlock) <br>

  dwVersion: DWORD;        // version info of this spec <br>

  ConnID: HCONN;           // Context Do not modify! <br>

  dwHttpStatusCode: DWORD; // HTTP Status code <br>

  // null terminated log info specific to this Extension DLL <br>

  lpszLogData: array [0..HSE_LOG_BUFFER_LEN-1] of Char; <br>

  lpszMethod: PChar;            // REQUEST_METHOD <br>

  lpszQueryString: PChar;       // QUERY_STRING <br>

  lpszPathInfo: PChar;          // PATH_INFO <br>

  lpszPathTranslated: PChar;    // PATH_TRANSLATED <br>

  cbTotalBytes: DWORD;          // Total bytes from client <br>



  cbAvailable: DWORD;           // Available number of bytes <br>

  lpbData: Pointer;             // pointer to cbAvailable bytes <br>

  lpszContentType: PChar;       // Content type of client data <br>

  <br>

  GetServerVariable: TGetServerVariableProc; <br>

  WriteClient: TWriteClientProc; <br>

  ReadClient: TReadClientProc; <br>

  ServerSupportFunction: TServerSupportFunctionProc; <br>

end; <br>

  <br>

注意到这个纪录中包含了上面提到过的ConnID字段,并且向 WriteClient 传送第一个参 <br>

数。 <br>

  <br>

这个纪录中的第一个参数是为版本控制而设的。它应该是TExtensionControlBlock的大小 <br>

的规定。如果微软公 <br>

司改变了它的结构,那么它们能够通过检查纪录的大小来判断它们正在处理的结构版本。 <br>

您永远也不要这个纪 <br>

录中的前三个字段,它们早已被ISAPI填充,在您的程序中,它们只能被访问,而不能被 <br>

改变。 <br>

  <br>

这个纪录中最重要的字段可能就是lpszQueryString了,它包含了从服务器上传来的请求 <br>

的信息。例如,假设您 <br>

的信息。例如,假设您 <br>

已经创建了一个名叫 ISAPI1.Dll。为了调用这个DLL,您就要在您的浏览器的一页上创建 <br>

一个像这样的HREF <br>

[注:HTML语言中的一种格式(译者)] : <br>

  <br>

<A HREF="/scripts/mystuff/test1.dll">Test One</A> <br>

  <br>

如果您希望响应这个DLL,您就要对上面那行做这样的改动: <br>

  <br>

<A HREF="/scripts/mystuff/test1.dll?MyQuery">Test One</A> <br>

  <br>

假如HTML代码段中有像上面两行中的第二行,那么,您的DLL就会在lpszQueryString参数 <br>

中得到“MyQuery” <br>

的字符串,特别要注意跟在请求字符串后的请求标志的使用。 <br>

  <br>

当然,您可以随心所欲地改变请求字符串。例如,您可以这样写: <br>

  <br>

<A HREF="/scripts/mystuff/test1.dll?ServerName">Test One</A> <br>

  <br>

在这个请求中,这个DLL会回答服务器的名称。您在传递这个参数时,不受任何限制。您 <br>

可以传递任何您想要 <br>

的东西,而且,如何分析DLL中的信息也由您的喜好决定。 <br>

  <br>

  <br>

  <br>

当您从服务器返回信息至浏览器时,您使用到了这个纪录中的“WriteClient”函数指针 <br>

。在初始化这个指针 <br>

时您不需做任何事;它已经自动地有网络信息服务器传递给您了。 <br>

  <br>

CGI应用程序的作者会注意到传送请求字符串的语法十分熟悉。事实上,ISAPI跟随了CGI <br>

的大多数习惯,在 <br>

TExtensionControlBlock中的多数字段可以简单地被CGI技术借用。 <br>

  <br>

在TExtensionControlBlock中的另一个关键字段是 lpbData ,它包含了从浏览起上传给 <br>

您的附加信息。 <br>

例如,您有一个伴随几个字段的HTML窗体,这些自断中包含的信息就会被一个叫做“ <br>

lpData”的指针传 <br>

递。本文中的下一个主题,“从‘确认’按钮中获得信息”,将会着重讲述怎样处理这种 <br>

情况。 <br>

  <br>

到现在为止我已经介绍了TExtensionControlBlock中的四个关键字段: <br>

  <br>

WriteClient: 一个能够让您传递格式化的HTML数据到浏览器上的指针。这个函数用到了 <br>

        TExtensionControlBlock的ConnID字段。 <br>

  <br>

lpszQueryString: 从浏览骑上传来的请求。 <br>



  <br>

lpbData: 从浏览器上传给你的人一的附加数据。通常是一个HTML窗体的任意字段的内容 <br>

。我将在“确认 <br>

按钮”这部分进一步讨论。 <br>

  <br>

要获得其他TExtensionControlBlock中的字段是如何工作的感觉,最好的办法就是亲自在 <br>

浏览其中将他们 <br>

做对照。换句话说,您会希望创建一个HTML页,使得用能够调用客户端的ISAPI DLL。这 <br>

个ISAPI DLL的目 <br>

的仅仅是在HTML中格式话TExtensionControlBlock中的每一个字段,然后把它们传回浏览 <br>

器。这样就把您 <br>

的浏览器变成了一个有点可怕的调试器,来显示TExtensionControlBlock中的所有字段。 <br>

  <br>

这里有一个程序,由Borland公司的 Danny Thorpe 编写,他会执行这个任务: <br>

  <br>

  <br>

library test1; <br>

  <br>

uses <br>

  Windows, <br>

  SysUtils, <br>

  HTTPExt; <br>

  HTTPExt; <br>

  <br>

function GetExtensionVersion( var Ver: THSE_VERSION_INFO ): <br>

  BOOL; stdcall; <br>

begin <br>

  Ver.dwExtensionVersion := $00010000;  // 1.0 support <br>

  Ver.lpszExtensionDesc := 'A test DLL written in Delphi 2.0'; <br>

  Result := True; <br>

end; <br>

  <br>

  <br>

function HttpExtensionProc( var ECB: TEXTENSION_CONTROL_BLOCK ): <br>

  DWORD; stdcall; <br>

var <br>

  ResStr: string; <br>

  StrLen: Integer; <br>

  Buf: array [0..1024] of Char; <br>

begin <br>

  ECB.lpszLogData := 'Delphi DLL Log'; <br>

  ECB.dwHTTPStatusCode := 200; <br>

  ResStr := Format( <br>

    '<HTML><TITLE>Test server result</TITLE>' + <br>

    '<H1>Test server results</H1>' + <br>



    'Size = %d<BR>'+ <br>

    'Version = %.8x<BR>'+ <br>

    'ConnID = %.8x<BR>'+ <br>

    'Method = %s<BR>' + <br>

    'Query = %s<BR>' + <br>

    'PathInfo = %s<BR>'+ <br>

    'PathTranslated = %s<BR>'+ <br>

    'TotalBytes = %d<BR>'+ <br>

    'AvailableBytes = %d<BR>'+ <br>

    'ContentType = %s<BR><BR>'+ <br>

    '<H1>Some Server Variables</H1>', <br>

    [ECB.cbSize, ECB.dwVersion, ECB.ConnID, <br>

     ECB.lpszMethod, ECB.lpszQueryString, <br>

     ECB.lpszPathInfo, ECB.lpszPathTranslated, <br>

      ECB.cbTotalBytes, ECB.cbAvailable, <br>

      ECB.lpszContentType]); <br>

  with ECB do <br>

  begin <br>

    StrLen := Sizeof(Buf); <br>

    GetServerVariable(ConnID, 'REMOTE_ADDR', @Buf, StrLen); <br>

    ResStr := ResStr + 'REMOTE_ADDR = '+Buf+'<BR>'; <br>

    StrLen := SizeOf(Buf); <br>

    StrLen := SizeOf(Buf); <br>

    GetServerVariable(ConnID, 'REMOTE_HOST', @Buf, StrLen); <br>

    ResStr := ResStr + 'Remote_Host = '+Buf+'<BR>'; <br>

    StrLen := SizeOf(Buf); <br>

    GetServerVariable(ConnID, 'REMOTE_USER', @Buf, StrLen); <br>

    ResStr := ResStr + 'Remote_User = '+Buf+'<BR>'; <br>

    StrLen := SizeOf(Buf); <br>

    GetServerVariable(ConnID, 'SERVER_NAME', @Buf, StrLen); <br>

    ResStr := ResStr + 'SERVER_NAME = '+Buf+'<BR>'; <br>

    StrLen := SizeOf(Buf); <br>

    GetServerVariable(ConnID, 'SERVER_PORT', @Buf, StrLen); <br>

    ResStr := ResStr + 'SERVER_PORT = '+Buf+'<BR>'; <br>

    StrLen := SizeOf(Buf); <br>

    GetServerVariable(ConnID, 'SERVER_PROTOCOL', @Buf, StrLen); <br>

    ResStr := ResStr + 'SERVER_PROTOCOL = '+Buf+'<BR>'; <br>

    StrLen := SizeOf(Buf); <br>

    GetServerVariable(ConnID, 'SERVER_SOFTWARE', @Buf, StrLen); <br>

    ResStr := Format('%sSERVER_SOFTWARE = %s<BR>'+ <br>

      'ThreadID = %.8x<BR>',[ResStr, Buf, GetCurrentThreadID]); <br>

  end; <br>

  ResStr := ResStr + '</HTML>'; <br>

  ResStr := Format( <br>

    'HTTP/1.0 200 OK'#13#10+ <br>



    'Content-Type: text/html'#13#10+ <br>

    'Content-Length: %d'#13#10+ <br>

    'Content:'#13#10#13#10'%s', [Length(ResStr), ResStr]); <br>

  StrLen := Length(ResStr); <br>

  ECB.WriteClient(ECB.ConnID, Pointer(ResStr), StrLen, 0); <br>

  Result := HSE_STATUS_SUCCESS; <br>

end; <br>

  <br>

  <br>

exports <br>

  GetExtensionVersion, <br>

  HttpExtensionProc; <br>

  <br>

begin <br>

end. <br>

  <br>

为了调用这个DLL,您应该建立一个包括下面这行的 HRML 脚本 <br>

  <br>

<A HREF="/scripts/mystuff/test1.dll">Test One</A> <BR> <br>

  <br>

从“确认”按钮获得信息 <br>

  <br>

  <br>

   通常向您发送信息的HTML窗体中都有一个确认按钮。只要信息量小于49KB,您就可以 <br>

认为TExetensionControlBlock中的 lpbData 字段是可用的。这里显示了您可以如何在大 <br>

多数情况下获得由这个字段的指针发来的信息: <br>

  <br>

var <br>

   S: string; <br>

begin <br>

  … <br>

  S := PChar(ECB.lpbData); <br>

  … <br>

end; <br>

  <br>

    如果从这个字段传来的信息大于48KB,那么您必须呼叫 ReadClient 来获得其余的信 <br>

息。 <br>

  <br>

⌨️ 快捷键说明

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