Reading and Writing Asynchronously

Asynchronous I/O operations are frequently the most efficient choices when developing ISAPI extensions. For an overview of asynchronous operations in ISAPI, see Asynchronous I/O Processing.

Asynchronous Reading

In order to perform asynchronous reads, your ISAPI extension must perform the following steps:

  1. Set the special asynchronous callback function by calling the HSE_REQ_IO_COMPLETION support function, through the ServerSupportFunction function.
  2. Request that IIS begin the asynchronous read operation by calling the HSE_REQ_ASYNC_READ_CLIENT support function, using the ServerSupportFunction function.
  3. Exit the HttpExtensionProc function, and indicate that the extension is waiting for further callbacks by returning the status code HSE_STATUS_PENDING.
  4. When IIS has completed the read—or has generated an error trying to read—IIS will call the asynchronous callback function specified in step 1. The extension can now perform any processing on the newly read data, and return to step 2 if there is more data available.
  5. When no more data is available to send, and the extension has completed any cleanup necessary for the current request, the extension should inform IIS that it is done with the request by using the ServerSupportFunction HSE_REQ_DONE_WITH_SESSION.

Note that only one asynchronous read operation can be pending for each ISAPI extension at any given time. If your ISAPI extension has issued a request for an asynchronous read, and you have determined that the request has timed out, you can cancel the request and close the connection by using the HSE_REQ_CLOSE_CONNECTION ServerSupportFunction. If you do this, however, you must still wait for IIS to call the asynchronous callback function before you can consider the connection terminated.

Asynchronous Writing

There are two options available to ISAPI extensions for performing asynchronous write operations. One option uses an asynchronous flavor of the WriteClient function, the other uses the functionality provided by the Win32 API TransmitFile function through the HSE_REQ_TRANSMIT_FILE ServerSupportFunction.

Tip   In most cases, using the TransmitFile-based ServerSupportFunction will yield the highest performance.

Both options are included in the following procedure:

  1. Provide IIS with a pointer to the asynchronous callback function. If using the WriteClient option, this is accomplished with the HSE_REQ_IO_COMPLETION support function, through the ServerSupportFunction function. If using the TransmitFile option, set the pfnHseIO member of the HSE_TF_INFO structure to point to the asynchronous callback function.
  2. Request that IIS begin the asynchronous write operation, calling either WriteClient (with the dwSync parameter set to HSE_IO_ASYNC) or the HSE_REQ_TRANSMIT_FILE ServerSupportFunction.
  3. Exit the HttpExtensionProc function, and indicate that the extension is waiting for further callbacks by returning the status code HSE_STATUS_PENDING.
  4. When IIS has completed the write—or has generated an error trying to write—IIS will call the asynchronous callback function specified in step 1. The extension can now perform any further processing, and return to step 2 if there is more data to send.
  5. When no more data is available to send, and the extension has completed any cleanup necessary for the current request, the extension should inform IIS that it is done with the request by using the ServerSupportFunction HSE_REQ_DONE_WITH_SESSION.
Example

The following code initiates an asynchronous read from a client.

DWORD DoAsyncRC(
  EXTENSION_CONTROL_BLOCK * pecb
)
{
  char  szHeader[256] = "";
  BOOL  fReturn = TRUE;
  DWORD dwFlags;
  DWORD cbTotalToRead = MAX_BUF_SIZE;
  DWORD hseStatus = HSE_STATUS_PENDING;
 

  // Initialize the context for ReadClient.
  pByteReadSoFar = &(pecb->cbAvailable);
  
  // Specify the asynchronous callback function.
  fReturn = pecb->ServerSupportFunction(
      pecb->ConnID,
      HSE_REQ_IO_COMPLETION,
      AsyncReadClientIoCompletion,
      0,
      pByteReadSoFar
      );
 
  // Error?
  if (!fReturn) {
    hseStatus = HSE_STATUS_ERROR;
  }
 
  //  Request that IIS begin asynchronous read operation.
  dwFlags = HSE_IO_ASYNC;
  fReturn = pecb->ServerSupportFunction(
      pecb->ConnID,
      HSE_REQ_ASYNC_READ_CLIENT,
      g_ReadBuffer,
      &cbTotalToRead,
      &dwFlags
      );
 
  // Error?
  if (!fReturn) {
    hseStatus = HSE_STATUS_ERROR;
  }
  
  // Return HSE_STATUS_PENDING, unless an error occurred.
  return (hseStatus);
}
 

For complete working samples that demonstrate all the possible synchronous and asynchronous operations, see the Synchronous and Asynchronous I/O sample.