Introduction

This is a client/server implementation of Inter Process Communication using Asynchronous Named Pipes with IO completion ports to achieve scalability in situations where several applications need to send and receive large chunks of data to each other or to a central (server) application.
Named pipes provide a flexible and rather easy to implement IPC model which has a message read communication mode where a "client" process can send a message to a "server" process and get an answer to that message.
IO Completion ports, though more known for their use with sockets in server applications, can also be used with files, directories and pipes and they provide an efficient way for handling concurrent asynchronous IO requests.

Using the Code

Creating the server:

//this function will be called when a message is received
//and can be given an answer in pAnswerBuf to pass to the sender
VOID WINAPI Callback(
LPCVOID pMessage,
DWORD dwMessageLen,
LPVOID pAns,
DWORD* pdwAnsLen)
{
}
CAsyncPipesServer2 myPipeServer;
myPipeServer.Create(_T("SAMPLEIPC1"), Callback);

How Does It Work

Server Side

After creating a completion port we create a separate thread for creating pipe instances that will wait for new connections from clients. This thread will create a predefined number of instances and then wait for a signal from the main thread. When new clients connect to the server, using up pending pipe instances, main thread signals the pipe instances thread to create more. This way we don't hold up the main queue polling thread too much and replace the used up pending pipe instances as soon as possible.
After that we issue a ReadFile call to read data a newly connected client has sent.

Once read is complete we create a new thread in which we will call the callback function supplied during creation of the server this is because we want to return to GetQueuedCompletionStatus as soon as possible otherwise we unnecessarily delay both new connections and pending read/write requests this also allows the callback function to safely do any lengthy operations if needed.
After that we write any (answer) data the callback function wish to pass on to the client onto the pipe.

Client Side

There are a couple of ways to send a message to the pipes server, depending on the level of control you want. I wanted to control the timeout for connection establishment and message transfer individually so I am using the second easiest method CreateFile + WaitNamedPipe + TransactNamedPipe. Easiest method being CallNamedPipe which is equivalent to calling CreateFile, WaitNamedPipe, WriteFile, ReadFile and CloseHandle.