Some History of the Named Pipe, Part 4

Here are the past articles in the series to get up to date:

The last part in this series is to bring the history of the named pipe up to the named pipe implementation in WCF.

Although the .Net framework now has a named pipe implementation in System.IO.Pipes, the WCF named pipe implementation actually precedes that by a few years (this is why there is a type System.IO.PipeException that comes in System.ServiceModel.dll). That means we directly sit on top of the native Windows named pipe implementation I talked about last time, such as the CreateNamedPipe function in kernel32.dll. Named pipes are probably our second largest source for using native methods after the queuing functions in mqrt.dll used by the MSMQ channel.

The basic building blocks that we use for a named pipe implementation are:

- Creating and waiting for incoming connections (CreateNamedPipe, ConnectNamedPipe)

Creating a client connection (CreateFile, SetNamedPipeHandleState)  
  • Reading and writing to a connection (ReadFile, WriteFile, GetOverlappedResult, HasOverlappedIoCompleted)
  • Handling errors (FormatMessage, DisconnectNamedPipe)

The named pipes in WCF are intended for use as a fast, local machine communication mechanism. Although a Windows named pipe can be used to connect to other machines, we use the security permissions of the pipe to deny network connections. This is done by denying the special well-known Network SID S-1-5-2 (there was previously an option on CreateNamedPipe to do this directly but that was deprecated in favor of the current approach). From time to time you might see this cause a problem with a service that bridges external communication from one service to talk to a second service over a named pipe. The Network SID is added to the process token when a user logs on across a network, preventing that logon from later talking across one of our named pipes.

As you might have guessed from the supported channel shapes and the information above, we use bidirectional pipes with overlapped IO operations. Both reads and writes are done using the pipe stream in message mode. These messages don’t equate to the messages you think of in your application (that’s what the higher-level message framing is for) but are instead to have coherent exchanges along the pipe.