Named Pipe Communication in C# Explained
This article provides an overview of pipe-based communication in C#, focusing specifically on named pipes as an efficient Inter-Process Communication (IPC) mechanism. You will learn what named pipes are, how they function within the .NET framework, the core classes used for implementation, and the primary advantages they offer over other communication methods.
What Is a Named Pipe?
A named pipe is a shared memory channel used for Inter-Process Communication (IPC). It allows two or more distinct processes—either running on the same local machine or across a local area network—to exchange data seamlessly. Unlike anonymous pipes, which are typically restricted to communication between parent and child processes on the same system, named pipes are identified by a unique system-wide name and can accept connections from any process that has the appropriate security permissions.
Named pipes operate in a client-server architecture. A server process creates the pipe and waits for a client process to establish a connection. Once connected, communication can be unidirectional (one-way) or duplex (two-way/bidirectional), allowing streams of bytes or discrete message packets to flow between the applications.
Core Classes in .NET
The .NET runtime provides built-in support for named pipes through
the System.IO.Pipes namespace. The two primary classes used
are:
NamedPipeServerStream: Used by the server application to construct the pipe instance, listen for incoming connections viaWaitForConnection()orWaitForConnectionAsync(), and handle data transmission.NamedPipeClientStream: Used by the client application to locate and connect to the listening server pipe using the designated pipe name and server name (using.for the local computer).
Because both classes inherit from System.IO.Stream,
standard stream abstractions like StreamReader,
StreamWriter, and binary buffers can be used to read and
write data directly over the pipe.
How Named Pipe Communication Works
- Creation: The server initializes a
NamedPipeServerStreamby specifying a unique pipe name and communication direction (in, out, or in-out). - Listening: The server calls
WaitForConnection(), which pauses execution until a client connects. - Connection: The client initializes a
NamedPipeClientStreamtargeting the matching pipe name and callsConnect(). - Data Exchange: Once the link is established, both sides use standard I/O streams to serialize and deserialize messages.
- Termination: When operations conclude, both ends close and dispose of their stream instances, releasing system handles.
Basic Server Implementation Example
using System.IO;
using System.IO.Pipes;
using var server = new NamedPipeServerStream("DemoPipe", PipeDirection.InOut);
server.WaitForConnection();
using var reader = new StreamReader(server);
using var writer = new StreamWriter(server) { AutoFlush = true };
string? clientMessage = reader.ReadLine();
writer.WriteLine($"Echo: {clientMessage}");Basic Client Implementation Example
using System.IO;
using System.IO.Pipes;
using var client = new NamedPipeClientStream(".", "DemoPipe", PipeDirection.InOut);
client.Connect();
using var reader = new StreamReader(client);
using var writer = new StreamWriter(client) { AutoFlush = true };
writer.WriteLine("Hello from Client");
string? serverResponse = reader.ReadLine();Key Advantages of Named Pipes
- High Performance: For local IPC, named pipes bypass the networking stack (TCP/IP), significantly reducing CPU overhead and latency compared to local sockets or HTTP services.
- Flexible Data Modes: Pipes support both raw byte streams and message-oriented transmission, enabling applications to read variable-length data without manually parsing delimiters.
- Built-in Security: Named pipes integrate with Windows Access Control Lists (ACLs), enabling developers to restrict which users or process identities can open and communicate across the pipe.