9

I've just stumbled upon Microsoft's HTTP Server API. The introduction states:

The HTTP Server API enables applications to communicate over HTTP without using Microsoft Internet Information Server (IIS). Applications can register to receive HTTP requests for particular URLs, receive HTTP requests, and send HTTP responses. The HTTP Server API includes SSL support so that applications can exchange data over secure HTTP connections without IIS. It is also designed to work with I/O completion ports.

Finding this cool, I took a long hard look at the list of functions for both versions of the API. Now, the only other part of the documentation that mentions I/O completion ports is the HttpReceiveHttpRequest() function. The last parameter is an optional OVERLAPPED structure with the following description:

For asynchronous calls, set pOverlapped to point to an OVERLAPPED structure; for synchronous calls, set it to NULL. A synchronous call blocks until a request has arrived in the specified queue and some or all of it has been retrieved, whereas an asynchronous call immediately returns ERROR_IO_PENDING and the calling application then uses GetOverlappedResult() or I/O completion ports to determine when the operation is completed. For more information about using OVERLAPPED structures for synchronization, see Synchronization and Overlapped Input and Output.

There is no other information, and all structures are opaque and deliberately hide connection information. Also notice that the Synchronization and Overlapped Input and Output subject makes no mention of the HTTP API.

Does anyone have any idea on how to connect the HTTP API's queue to an I/O completion port?

André Caron
  • 44,541
  • 12
  • 67
  • 125
  • Do you have any reason to believe you wouldn't just pass the handle to the queue as the first parameter to CreateIoCompletionPort? – Gabe Jan 02 '11 at 05:53
  • 3
    Nope. I have no reason to believe that's the right thing to do either. – André Caron Jan 02 '11 at 20:15

2 Answers2

4

Using IO completion ports is trivially simple in theory, but abomnible in practice :P

the "normal" usage is:

  1. Call CreateIOCompletionPort to create a IO completion port handle.
  2. Create a bunch of threads, and get each thread to loop, on a call to GetOverlappedResult. GetOverlappedResult will return when an overlapped operation associated with the port completes, with structures indicating which handle, and operation, was completed.
  3. As your program runs, and creates objects that it wishes to handle asynchronously, it associates each HANDLE with the IO CompletionPort handle by calling CreateIOCompletionPort again.

Now, each time the application issues an asynchronous operation on the HANDLE (which is signalled by passing in an OVERLAPPED struct) the notification of the completed operation will be indicated by one of the threads thats waiting on GetOverlappedResult returning.

The clear implication is that the HANDLE returned by HttpCreateRequestQueue can be associated with an IO Completion port and subsequent asynchronous operations will result in GetOverlappedResult's returning the result of the operation.

Chris Becke
  • 34,244
  • 12
  • 79
  • 148
  • Yes, I have an existing I/O completion port based server. However, I don't exactly share the idea that the implication is "clear". I'll try it out to see how that goes. – André Caron Jan 02 '11 at 20:16
1

I wanted to mention another page in the HTTP API documentation that talks about overlapped operations.

HTTP Completion Routines

Applications have several options for receiving completion indications and providing some flexibility for developers. The options are to block while waiting for an API call to complete or to use completion routines for asynchronous operations. The advantage of using asynchronous operations is an increase in responsiveness of the application.

Asynchronous I/O

Applications that prefer not to block can use the OVERLAPPED structure to obtain the completion results. The application supplies a pointer to an OVERLAPPED structure, which is used with an event object or a completion port. With an I/O completion port, an HTTP handle is used as a file handle would be in an asynchronous file I/O operation. The following table summarizes the completion options available to the applications.

Overlapped structure Event object Completion port Completion
NULL Not Applicable Ignored Operation completes synchronously.
Non-NULL Non-NULL NULL Operation completes asynchronously. Overlapped notification is performed by signaling an event object.
Non-NULL Ignored Non-NULL Operation completes asynchronously. Overlapped notification is performed by scheduling a completion routine.

The page also talks about retreiving the number of bytes returned:

Returning the Number of Bytes Read

Some of the functions that use the OVERLAPPED structure for asynchronous completion return a pBytesReceived (or pBytesSent or pBytesRead) parameter that indicates the number of bytes transferred synchronously. For asynchronous calls, this parameter should be set to *NULL. For synchronous calls, the pBytesReceived parameter is optional and can be either NULL or non-NULL.

If the event object is used for asynchronous completion, the GetOverlappedResult function is called to determine the number of bytes read. If the completion port is used (the hFile parameter is associated with an I/O completion port), the application calls the GetQueuedCompletionStatus function to determine the number of bytes read.

Nimantha
  • 6,405
  • 6
  • 28
  • 69
Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219