65.9K
CodeProject 正在变化。 阅读更多。
Home

ISAPI 模块中的异步 IO

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.95/5 (10投票s)

2000年5月4日

viewsIcon

80679

downloadIcon

1122

如何使用异步 IO 从 ISAPI 模块发送数据

引言

ISAPI 模块中的异步 IO 通常被视为一种神秘的技术。但实际上它相当直接,并且能够为您的应用程序带来最高级别的性能和可伸缩性。

一个演示异步 IO 的项目

在浏览 Code Project 网站时,我偶然发现了 Jorge Lodos Vigil 的一个 示例 ISAPI 项目,该项目演示了发送回一个 HTML 页面和一个图像。Jorges 的 ISAPI 返回两种不同类型的数据。页面包含在一个内存缓冲区中,而图像包含在磁盘文件上。向客户端发送数据缓冲区和向客户端发送文件恰好涵盖了使用 ISAPI API 异步发送数据的两种可能方式 - WriteClientTransmitFile

ImageServer 项目

ImageServer ISAPI 扩展本质上是从某个隐藏目录代理图像请求。ImageServer 通过返回一个包含 IMG 元素的 HTML 页面来满足这些请求,该 IMG 元素的源是 ImageServer 扩展。源 URL 经过特殊格式化,以便 ImageServer 知道它应该发送实际的图像而不是包含的页面。

执行异步 IO 的两种方式

在 ISAPI 模块的上下文中,有两种方法可以异步接收或发送数据。您可以使用 ReadClientWriteClient 异步读/写到客户端的任意数据缓冲区,或者使用 TransmitFile 异步将文件发送到客户端。TransmitFile 是一个 Win32 函数,通过使用 ISAPI 函数 ServerSupportFunction 并指定 HSE_REQ_TRANSMIT_FILE 选项来访问。

MSDN 在线库提供了关于 异步 IO 的良好概述,但总的来说,您需要执行以下步骤:

  • 设置一个回调,以便在发生 IO 完成事件时收到通知。
  • 启动异步 IO。
  • HttpExtensionProc 返回 HSE_STATUS_PENDING
  • 当 IO 完成时,清理任何上下文信息,并通知 IIS 您已完成此会话。

关于异步 IO,真正需要记住的只有一件事。那就是,*无论*发送给客户端的数据都必须在收到完成通知之前保持有效。这意味着,它几乎总是会放在堆上。

最后一个要求通常在设计方面会引起最大的麻烦。ISAPI 扩展对性能和可靠性的极端要求排除了频繁访问堆的设计。限制对堆的访问通常通过实现可重用缓冲区对象的池来实现。

ImageServer 的要求没有那么严格。当 ImageServer 需要一个缓冲区或传输上下文时,它只需在堆上创建它。同样,当它完成一个缓冲区的使用时,它只是销毁它。尽管创建受保护的缓冲区池并不难,但它会分散 ImageServer 的核心目的——演示基本的异步 IO。

代码导览

代码很简单,并且有大量的注释,因此应该很容易理解。以下是您会发现的主要内容:

  • 有一个主要的类 CImageServer,它封装了此应用程序所需的所有功能。此类在 Server.h 中声明,在 Server.cpp 中实现。
  • CImageServer 的一个静态实例位于 ImageServer.cpp 中。该文件还包含 ISAPI DLL 的主要入口点 - DllMainGetExtensionVersionTerminateExtensionHttpExtensionProc。它们都是基本的样板代码,除了 HttpExtensionProc 将其行为委托给 CImageServer::ServiceRequest
  • 还有两个类作为异步 IO 调用的传输上下文。第一个是 CFilePacket,它是 TransmitFile 的上下文。第二个是 tWriteClientPacket,它实际上是一个结构而不是一个类。它作为您猜到的 WriteClient 的上下文。CFilePackettWriteClientPacket 都被声明为 CImageServer 声明中的嵌套类/结构。这并没有真正的必要,但它使代码更整洁,因为这些类仅在 CImageServer 的函数内部使用。

理解 CImageServer 的工作原理的最佳方法是阅读源代码。一切都始于 CImageServer::ServiceRequest,注释将引导您继续。

安装

与任何 ISAPI 模块一样,您必须将 DLL 放置在您的 Web 服务器有权访问的某个路径中,并具有执行权限。您还需要一个包含图像的目录,该目录与您在 CImageServer::GetImageDirectory 中硬编码的名称匹配。


关于作者

我工作的公司 Financial Insight Systems Inc. 专注于使用 Microsoft Back Office 产品创建高性能的 Internet 应用程序。我拥有 MCSD 认证,并获得了 Visual C++ 和 SQL Server 的认证,在过去的五年里,我大部分时间都花在开发 ISAPI 模块和基于 Winsock 的客户端/服务器解决方案上。欢迎提出建议和意见。

许可证

本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。

作者可能使用的许可证列表可以在此处找到。

© . All rights reserved.