Click here to Skip to main content
Click here to Skip to main content

Asynchronous IO within ISAPI modules

, 3 May 2000
Rate this:
Please Sign up or sign in to vote.
How to use asynchronous IO to send data from an ISAPI module
  • Download source files - 12 Kb

    Asynchronous IO within ISAPI modules

    Asynchronous IO under ISAPI is often viewed as something of a black art. But it's actually quite straight forward and it will yield the highest level of performance and scalability for your application.

    A project to demonstrate Asynchronous IO

    Browsing the Code Project site I stumbled across an example ISAPI project by Jorge Lodos Vigil which demonstrated sending back a page of HTML and an image. Two different types of data are returned by Jorges' ISAPI. The page is contained in an in-memory buffer while image is contained in a file on disk. Sending a buffer of data to a client and sending a file to a client just happen to encompass the two possible ways to send data asynchronously using the ISAPI API - WriteClient and TransmitFile.

    ImageServer Project

    The ImageServer ISAPI extension essentially brokers requests for images from some hidden directory. ImageServer satisfies those requests by returning a page of HTML containing an IMG element that has, as it's source, the ImageServer extension. The source URL is specially formatted to let ImageServer know that it should send back the actual image instead of a containing page.

    Two ways to perform asynchronous IO

    Within the context of an ISAPI module there are two ways to recieve or send data asynchronously. You can use ReadClient or WriteClient to read/write an arbitrary buffer of data to the client asynchronously or you can use TransmitFile to send a file to a client asynchronously. TransmitFile is a Win32 function which is accessed by using the ISAPI function ServerSupportFunction and specifying the HSE_REQ_TRANSMIT_FILE option.

    The MSDN online library provides a good overview of asynchronous IO but in general you will need to perform these steps:

    • Setup a callback through which you will be notified when an IO completion event occurs.
    • Start the asynchronous IO.
    • Return HSE_STATUS_PENDING from the HttpExtensionProc.
    • When IO completes cleanup any context information and notify IIS you're done with this session.
    There's really only one other thing to keep in mind about asynchronous IO. That is whatever data is being sent to the client must survive until a completion notification is received. Which means it's almost always going to be placed on the heap.

    This last requirement usually entails the most grief from a design standpoint. The extreme levels of performance and reliability required from ISAPI extensions precludes a design that constantly accesses the heap. Limiting access to the heap is often accomplished by implementing pools of buffer objects that are re-used.

    ImageServers requirements are not as stringent. When ImageServer needs a buffer, or transmission context, it simply creates it on the heap. Likewise when it's finished with a buffer is just destroys it. Although creating a protected buffer pool is not difficult it would distract from the central purpose of ImageServer - which is to demonstrate basic asynchronous IO.

    Tour of the code

    The code is simple and heavily commented so it should be easy to understand. Here are the highlights of what you'll find.

    • There is one main class CImageServer which encapsulates all the functionality required for this application. This class is declared in Server.h and implemented in Server.cpp.
    • A single static instance of CImageServer resides in ImageServer.cpp. Also in this file are the main entry points for the ISAPI DLL - DllMain, GetExtensionVersion, TerminateExtension and HttpExtensionProc. They are all basic boiler plate code except HttpExtensionProc which delegates it's behavior CImageServer::ServiceRequest
    • There are two other classes which serve as transmission contexts for the asynchronous IO calls. The first is CFilePacket which is a context for TransmitFile. The second is tWriteClientPacket, which is actually a structure not a class. It serves as a context for, you guessed it, WriteClient. Both CFilePacket and tWriteClientPacket are declared as nested classes/structures inside the declaration of CImageServer. There was no real need for this but it makes the code a little cleaner as those classes are only used inside the functions of CImageServer.
    Understanding how CImageServer works is best accomplished by reading the source. Everything starts with CImageServer::ServiceRequest and the comments will guide you from there.

    Setup

    As with any ISAPI module you'll have to locate the DLL in some path your web server has access too - with execute permissions. You'll also need a directory containing images that matches whatever you've hard coded into CImageServer::GetImageDirectory.

    <!-- Author Bio Starts -->

    About the author

    The company I work for, Financial Insight Systems Inc., specializes in creating high performance internet applications using Microsoft Back Office products. I have a MCSD, with certifications in Visual C++ and SQL Server, and for the last five years most of my time has been spent developing ISAPI modules and Winsock based client/server solutions. Suggestions and comments are welcome.

    <!-- Author Bio Ends -->
  • License

    This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

    A list of licenses authors might use can be found here

    Share

    About the Author

    Mike Junkin

    United States United States
    No Biography provided

    Comments and Discussions

     
    GeneralMapping virtual path to physical path Pinmemberpratheesh4-Feb-10 20:05 
    Do you know about any easier way of mapping virtual file path to the actual physical path that can be used in TransmitFile()?
    This will be useful to avoid an additonal configuration in registry as you have mentioned.
    I know there is Server.MapPath() in .Net.
     
    Thanks!
    Pratheesh
    GeneralGreat help for me. Pinmembersmallbarrow3-Nov-09 23:30 
    GeneralProblem with the ServerSupportFunction function. Help! PinmemberPCC7518-Apr-07 19:37 
    QuestionCan you tell me how can I control speeds of IIS. Pinmember10244225-Aug-05 20:04 
    GeneralThanks. I have a quick question. PinsussKeeyong23-Oct-02 7:08 
    GeneralRe: Thanks. I have a quick question. PinmemberMike Junkin23-Oct-02 8:37 
    GeneralVery good! PinmemberAdrian Bacaianu24-Mar-02 23:00 

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

    Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

    | Advertise | Privacy | Mobile
    Web04 | 2.8.140827.1 | Last Updated 4 May 2000
    Article Copyright 2000 by Mike Junkin
    Everything else Copyright © CodeProject, 1999-2014
    Terms of Service
    Layout: fixed | fluid