views:

264

answers:

5

I need a client networking thread to be able to respond both to new messages to be transmitted, and the receipt of new data on the network. I wish to avoid this thread performing a polling loop, but rather to process only as needed.

The scenario is as follows:

A client application needs to communicate to a server via a protocol that is largely, but not entirely, synchronous. Typically, the client sends a message to the server and blocks until a response is received.

The server may process client requests asynchronously, in which case the response to client is not a result, but a notification that processing has begun. A result message is sent to to the client at some point in the future, when the server has finish processing the client request.

The asynchronous result notifications can arrive at the client at any time. These notifications need processed when they are received i.e. it is not possible to process a backlog only when the client transmits again.

The clients networking thread receives and processes notifications from the server, and to transmit outgoing messages from the client.

To achieve this, I need to to make a thread wake to perform processing either when network data is received OR when a message to transmit is enqueued into an input queue.

How can a thread wake to perform processing of an enqueued work item OR data from a socket?

I am interested primarily in using the plain Win32 APIs.

A minimal example or relevant tutorial would be very welcome!

+2  A: 

You can set up an I/O Completion Port for the handles and have your thread wait on the completion port:

Actually, you can have multiple threads wait on the port (one thread per processor usually works well).

Michael Burr
+1 - What Michael doesn't say is that once you have your socket i/o coming through the I/O completion port there's nothing to stop you posting your own completion values to the port to deal with your work items. So your thread can wake up and deal with either the socket events or the work items - which is pretty much what you asked for :)
Len Holgate
A: 

Well, if both objects have standard Windows handles, you can have your client call WaitForMultipleObjects to wait on them.

You might want to investiate splitting the servicing of the network port off onto its own thread. That might simplify things greatly. However, it won't help if you just end up having to synchonize something else between that new thread and your main one.

T.E.D.
+2  A: 

Following on from Michael's suggestion, I have some free code that provides a framework for IO Completion Port style socket stuff; and it includes an IOCP based work queue too. You should be able to grab some stuff from it to solve your problem from here.

Len Holgate
+2  A: 

An alternative to I/O Completion Ports for sockets is using WSAEventSelect to associate an event with the socket. Then as others have said, you just need to use another event (or some sort of waitable handle) to signal when an item has been added to your input queue, and use WaitForMultipleObjects to wait for either kind of event.

TheUndeadFish
+1; solves the problem even if it doesn't scale especially well (sometimes I get an 'IOCP is the only solution' mentality ;) and often there are much easier to implement solutions...).
Len Holgate