Click here to Skip to main content
11,802,636 members (70,471 online)
Click here to Skip to main content

Asynchronous Named Pipe Server Using Overlapped I/O in C#

, 20 Jul 2008 CPOL 30.7K 827 13
Rate this:
Please Sign up or sign in to vote.
Asynchronous named pipe server in C#.


I recently read CLR via C# by J. Richter dedicated to the internals of .NET 2.0 and the C# peculiarities deriving from it. I’ve decided to practice a little and write my new application in C#. The part of this application I present here. It’s an asynchronous named pipe server using overlapped I/O plus a synchronous (or they also say blocking) named pipe client.

Problems encountered

The first problem encountered was the fact that the only example by John Korres of using overlapped structure written in VB.NET provides asynchronous calls for two Win32 API functions ConnectNamedPipe and DisconnectNamedPipe. Read and write from and to a named pipe server implemented in a blocking mode using the System.IO.FileStream .NET class. I tried to use the BeginRead and BeginWrite methods but it remained unclear how these two interact with the NativeOverlapped structure if they do interact at all. So eventually, I adopted this sample code written in C from MSDN.

And that’s how the second problem came up. After the code was re-written, I found out that the GetOverlappedResult Win32 API function works incorrectly due to the fact that the pointer to the overlapped structure is not fixed, i.e., you have to work with the unmanaged memory of the process to make it work like in plain old C. Investigating farther, I understood that all buffers for the ReadFile and WriteFile Win32 API functions must also use unmanaged memory. I decided to use pointers and compile the application with the unsafe option; that upset me a bit because my code looked like almost plain old C to me now. And that was not just the case. Byte* to IntPtr cast did not work correctly either. So I switched to using IntPtr instead for the overlapped structure and buffers that allowed me to remove this odious unsafe parameter. And I was rewarded. Now the adopted code worked exactly like the sample from MSDN.

The last but not the least problem which I have to mention here is permissions for the named pipe server. Using the default permissions won’t allow interprocess communication between two computers, so look up buildSecurityAttributes in NamedPipeServer.cs. I won’t dwell on it here since it’s not the main point of the article.

Using the code

The following code extract shows the main server loop and exposes the peculiarities of asynchronous programming. The actual overlapped magic happens when the ReadFile Win32 API inside of the selectOperation method returns FALSE and GetLastError returns ERROR_IO_PENDING which is not an error but a signal that a ReadFile asynchronous call has not succeeded to complete reading so we have to call the GetOverlappedResult Win32 API to find out if the Operating System has put cbRet bytes into mPipeServer[i].Pipe.chRequest. If it hasn’t, we call the DisconnectAndReconnect method.

Another scenario happens if the application runs under Visual Studio 2005, no matter if it’s the release or debug configuration. To actually witness the difference, uncomment MessageBox.Show(“GetOverlappedResult:...”) altogether with the line above and run the executable. Afterwards, run it under Visual Studio in the debug configuration. You might not encounter it though.

while (mListenning)
    i = (UInt32)WaitHandle.WaitAny(hEvents);
    // determines which pipe instance

    if (i < 0 || i > (mNumOfInstances - 1))
        ThrowWin32Exception ("Index out of range.");

    Debug.WriteLine("Instance -> " + i.ToString());

    #region ERROR_IO_PENDING == TRUE
    if (mPipeServer[i].Pipe.fPendingIO)
        fSuccess = NativeMethods.GetOverlappedResult(
            out cbRet,
           //if (cbRet > 0)
           //     MessageBox.Show("GetOverlappedResult: " +
           //     Marshal.PtrToStringAnsi(mPipeServer[i].Pipe.chRequest));

        switch (mPipeServer[i].Pipe.dwState)
            // Pending connect operation 
            case CONNECTING_STATE:
                if (!fSuccess)
                //SetEventAsync(CONNECTING_STATE, mPipeServer[i].Pipe.chRequest,
                //              mPipeServer[i].Pipe.cbRead);
                //STEP #0
                mPipeServer[i].Pipe.dwState = READING_STATE;
            // Pending read operation 
            case READING_STATE:
                Debug.WriteLine("READING_STATE " + cbRet.ToString());
                if (!fSuccess || cbRet == 0)
                //STEP #1
                //NB! If we got here and cbRet > 0
                //    the mPipeServer[i].Pipe.chRequest already has client data 
                mPipeServer[i].Pipe.dwState = WRITING_STATE;
            // Pending write operation 
            case WRITING_STATE:
                Debug.WriteLine("WRITING_STATE " + cbRet.ToString());
                if (!fSuccess || cbRet != mPipeServer[i].Pipe.cbToWrite)
                mPipeServer[i].Pipe.dwState = READING_STATE;
                ThrowWin32Exception("runInstance - INVALID PIPE STATE");

    } //IO_PENDING

    if (!selectOperation((Int32) i) )
    //does ReadFile or WriteFile depending on the pipe instance state
        // An error occurred; disconnect from the client. 

Points of interest

While testing the application, it turned out that it behaves differently when run under Visual Studio 2005.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Boris Kolesnikov
Software Developer
Russian Federation Russian Federation
Golang, Perl, C/C++ developer

You may also be interested in...

Comments and Discussions

QuestionException occurs when starting pipe server. Pin
Duojiao Yan7-Dec-11 0:52
memberDuojiao Yan7-Dec-11 0:52 
GeneralThere is a bug with the encoding of the message. Pin
consolejoker6-Feb-10 5:06
memberconsolejoker6-Feb-10 5:06 
GeneralProcess Hang impossible to detach or even Stop [modified] Pin
AndyHo24-Jan-10 6:11
memberAndyHo24-Jan-10 6:11 
GeneralFirst Read is missing?! Pin
Dirar H.21-Aug-09 8:44
memberDirar H.21-Aug-09 8:44 
GeneralRe: First Read is missing?! Pin
Boris Kolesnikov21-Aug-09 15:14
memberBoris Kolesnikov21-Aug-09 15:14 
GeneralThank you!! Pin
Dirar H.19-Aug-09 11:14
memberDirar H.19-Aug-09 11:14 
QuestionServer --&gt; Client communication? Pin
Greg Cadmes10-Sep-08 9:49
memberGreg Cadmes10-Sep-08 9:49 
AnswerRe: Server --&gt; Client communication? Pin
Boris Kolesnikov10-Sep-08 21:17
memberBoris Kolesnikov10-Sep-08 21:17 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.151002.1 | Last Updated 21 Jul 2008
Article Copyright 2008 by Boris Kolesnikov
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid