Simple Point to Point Communication Using Named Pipes

(NTier Solutions AB).

Environment: VC6 SP3, NT4 SP5


In a project I needed inter process communication and the use of named pipes seamed to be the most appropriate solution as well as the recommended when I discussed the problem (and requirements) with an other experienced developer.
Hence I started to search MSDN and CodeGuru for some nice reusable code using named pipes. At CodeGuru I found nothing usable and the code found in MSDN was ugly and not easy to reuse. Anxious to get progress, I started experimenting my self to get something that worked for me.

What I needed was for one server to communicate with several other processes and to keep it simple the server and one client only should share the same pipe. Both server and client should be able to communicate with the other at any given time. The result is the class CNamedPipe that actually uses two "one-way"-pipes and a listener thread on each side (i.e. Server and Client side). And I had the advantage of knowing that the server always has created the pipes correctly before the client tries to open them (saves me from some error handling). See the source file for further details on implementation.

It is important to remember that my implementation is simple and do not use (or support) all the fancy options available when using named pipes. Note also that the project for which the final version of CNamedPipe was intended for was non-MFC and hence the STL templates are used for strings (means some STL related warnings when compiling with warning level 4).

Basic piping

The named pipe must have a name. It looks like this:
The bold parts (including back slashes) are mandatory. ServerName should be a dot (i.e. \\.\PIPE\...) if the pipe is created (the creator will be called the server side of the pipe or the computer name if the name is to be used by a client.
pipe is a name used to uniquely identify a pipe on a certain computer. Note that pipe names are always case insensitive.

The server side of a pipe is the creator of a pipe and the pipe may be created with read, write or read/write access. For full information on how to use different options, check MSDN help file for CreateNamedPipe.

CNamedPipe creates a pipe like this:

m_hInPipe = CreateNamedPipe(
 GetRealPipeName(true).c_str(), //Gets the Pipename
 PIPE_ACCESS_INBOUND,           //Server will read from this pipe
                                //Client will write
 PIPE_WAIT,                     //Do not return Read/write calls
                                //until read/write is complete
 1,                             //allow only 1 instance of this pipe
 PIPE_BUF_SIZE,                 //Macro defined by me.
 PIPE_BUF_SIZE,                 //Macro defined by me.
 PIPE_TIMEOUT,                  //Macro defined by me.
 NULL);                         //Do not inherit security.

A client then connects to the pipe like this:

m_hOutPipe = 
 CreateFile(GetRealPipeName(true).c_str(), //Gets the Pipename
 GENERIC_WRITE,           //Client only writes to this pipe.
 0,                       //Do not share this pipe with others.
 NULL,                    //Do not inherit security.
 OPEN_EXISTING,           //Pipe must exist.
 FILE_ATTRIBUTE_NORMAL,   //I have no special requirements on 
                          //file attributes
 NULL);                   //This parameter not used since pipe 
                          //created with PIPE_WAIT.

When using pipes it is important that the client opens the pipe with correct options. If the server will only read from the pipe, the client must open it as write only etc.

When reading and writing from pipes, one just uses the functions ReadFile and WriteFile. If the PIPE_WAIT flag is used, the ReadFile function will not return until something is written to the pipe and vice versa. Hence it is important to create a separate thread which tries to read from the pipe. This thread will be waiting until a WriteFile operation is made by the other side.

Features in CNamedPipe

bool Initialize(bool bAsServer, 
                string szStopListnenCmd,
                void (WINAPI *fCallBack)(string buf))

Initialize must be called to create/open the pipes. The server must be initialized first. To Initialize the server, parameter bAsServer should be true (hence false when initializing the client). The szStopListnenCmd parameter is used to tell the listener thread to stop listen. When the listening thread receives a message identical to this parameter (case sensitive), the thread will exit its listening loop. The last parameter is a function pointer and this function is called for every completed successful ReadFile the listening thread performs. The buffer read will be the argument of the call.

SetPipeName and GetRealPipeName are used to set and get the used names. SetPipeName takes two arguments and makes a string like this:
GetRealPipeName uses the constructed string and adds "_IN" or "_OUT" depending on its argument. So the used names are:
Server reads from: \\<arg2>\PIPE\<arg1>_IN
Server writes to: \\<arg2>\PIPE\<arg1>_OUT

PipeTest - a demo of CNamedPipe

Running demo as server
Running demo as client

Only one client per server is possible. Server name must be the server computer's entry in DNS.

To see examples of the use of CNamedPipe, check the following functions in class CPipeTestDlg:

  • OnBConnect - Creating pipes...
  • OnBSend - Send a message to the pipe...
  • funcCallBack - implementation of the callback function called by the CNamedPipe listener thread.


Download demo project - 18 Kb
Download source - 3 Kb


  • Little fix...

    Posted by aurelien on 08/22/2006 10:28am

    hi, and sorry for my english
    when I tried this project, I have noticed that it consumed much CPU time. so this is my little piece of code for fix it :
    DWORD WINAPI CNamedPipe::ListnerProc(LPVOID lpParameter)
    	ListnerParam* pLP = (ListnerParam*)lpParameter;
    	if (pLP == NULL)
    		return 1;
    	DWORD dwRetVal = 0;
    	for (bool bContinue = true; bContinue && dwRetVal == 0; Sleep( 10 )/* <- little sleep */ )
    		char buf[PIPE_BUF_SIZE];
    		DWORD lpNumberOfBytesRead = 0, dwRead = 0;
    		BOOL bOK;
    		// Test the total number of bytes available to be read from the pipe
    		PeekNamedPipe( pLP->hPipe, NULL, 0, NULL, &lpNumberOfBytesRead, NULL);
    		if (lpNumberOfBytesRead == 0)
    		bOK = ReadFile( pLP->hPipe, buf, PIPE_BUF_SIZE, &dwRead, NULL );				
    		if (!bOK)
    			dwRetVal = 2;
    		string szMsg = buf;
    		if (szMsg == pLP->szStopCmd)
    			bContinue = false;
    		pLP->funcCallBack( &buf, dwRead );
    		// Add-on for multiple pipe write :p
    		// DisconnectNamedPipe( pLP->hPipe );
    		// ConnectNamedPipe( pLP->hPipe, NULL );
    	delete pLP;
    	return dwRetVal;
    I hop it will help somebody

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • On-demand Event Event Date: September 23, 2015 The cloud is not just about a runtime platform for your projects – now, you can do your development in the cloud, too. Check out this webcast to learn how the cloud improves your development experience and team collaboration. Join Dana Singleterry, Principal Product Manager for Oracle Dev Tools, as he discusses how to simplify every aspect of the development lifecycle, including requirements gathering, version management, code reviews, build automation, and …

  • As the mobile enterprise marketplace expands and customer needs grow more diverse, Samsung recognizes that solution partners and developers play an essential role by continually innovating to meet their customers' needs. Samsung works to provide these developers and partners with the latest tools and resources needed to create these solutions. Read this program guide to learn how the Samsung Enterprise Alliance Program provides partners and developers with Samsung enterprise software development kits (SDKs) …

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date