命名管道 是 Windows 高效能、安全、雙向的進程間通訊機制,支援跨機器 (SMB)、模擬、訊息/位元組模式。.NET 提供 NamedPipeServerStream/NamedPipeClientStream (System.IO.Pipes),封裝底層 Win32 API。本文提供完整伺服器/用戶端雙向通訊範例,含非同步讀寫、連線生命週期、例外處理、多執行緒伺服器模式。
核心類別
| 類別 | 角色 | 關鍵方法 |
NamedPipeServerStream | 伺服器端 | WaitForConnectionAsync, ReadAsync, WriteAsync, Disconnect |
NamedPipeClientStream | 用戶端 | ConnectAsync, ReadAsync, WriteAsync |
PipeDirection | 方向 | In, Out, InOut (雙向) |
PipeOptions | 選項 | Asynchronous (啟用非同步 I/O 完成埠) |
1. 伺服器端 (Console App)
using System;
using System.IO.Pipes;
using System.Text;
using System.Threading.Tasks;
class PipeServer
{
const string PipeName = "np-test-demo";
static async Task Main()
{
Console.WriteLine($"啟動命名管道伺服器: {PipeName}");
while (true) // 持續接受連線
{
using var server = new NamedPipeServerStream(
PipeName, PipeDirection.InOut, 1, // max 1 instance for demo
PipeTransmissionMode.Message, PipeOptions.Asynchronous);
Console.WriteLine("等待用戶端連線...");
await server.WaitForConnectionAsync();
Console.WriteLine("用戶端已連線");
try
{
// 讀取訊息 (Message 模式:一次讀一個完整訊息)
var buffer = new byte[1024];
int bytesRead = await server.ReadAsync(buffer, 0, buffer.Length);
string request = Encoding.UTF8.GetString(buffer, 0, bytesRead);
Console.WriteLine($"收到: {request}");
// 回覆
string response = $"Server Echo: {request}";
byte[] respBytes = Encoding.UTF8.GetBytes(response);
await server.WriteAsync(respBytes, 0, respBytes.Length);
await server.FlushAsync();
Console.WriteLine($"已回覆: {response}");
if (request.Trim().Equals("exit", StringComparison.OrdinalIgnoreCase))
break;
}
catch (Exception ex)
{
Console.WriteLine($"通訊錯誤: {ex.Message}");
}
finally
{
server.Disconnect();
}
}
}
}
2. 用戶端
using System;
using System.IO.Pipes;
using System.Text;
using System.Threading.Tasks;
class PipeClient
{
const string PipeName = "np-test-demo";
static async Task Main()
{
using var client = new NamedPipeClientStream(".", PipeName, PipeDirection.InOut, PipeOptions.Asynchronous);
Console.WriteLine("連線至伺服器...");
await client.ConnectAsync(5000); // 5 秒逾時
Console.WriteLine("已連線");
while (true)
{
Console.Write("輸入指令 (exit 結束): ");
string input = Console.ReadLine();
if (string.IsNullOrEmpty(input)) continue;
byte[] req = Encoding.UTF8.GetBytes(input);
await client.WriteAsync(req, 0, req.Length);
await client.FlushAsync();
var buffer = new byte[1024];
int read = await client.ReadAsync(buffer, 0, buffer.Length);
string resp = Encoding.UTF8.GetString(buffer, 0, read);
Console.WriteLine($"伺服器回覆: {resp}");
if (input.Equals("exit", StringComparison.OrdinalIgnoreCase)) break;
}
}
}
3. 進階:多執行緒伺服器 (同時處理多用戶端)
class ConcurrentPipeServer
{
const string PipeName = "np-concurrent";
static async Task Main()
{
var tasks = new List();
for (int i = 0; i < Environment.ProcessorCount; i++)
{
tasks.Add(AcceptLoopAsync(i));
}
await Task.WhenAll(tasks);
}
static async Task AcceptLoopAsync(int instanceId)
{
while (true)
{
using var server = new NamedPipeServerStream(
PipeName, PipeDirection.InOut, -1, // -1 = 不限實例數
PipeTransmissionMode.Message, PipeOptions.Asynchronous);
await server.WaitForConnectionAsync();
_ = HandleClientAsync(server, instanceId); // Fire-and-forget
}
}
static async Task HandleClientAsync(NamedPipeServerStream server, int id)
{
try
{
var buffer = new byte[4096];
int read = await server.ReadAsync(buffer, 0, buffer.Length);
string req = Encoding.UTF8.GetString(buffer, 0, read);
string resp = $"Instance {id} Echo: {req}";
byte[] data = Encoding.UTF8.GetBytes(resp);
await server.WriteAsync(data, 0, data.Length);
await server.FlushAsync();
}
catch { /* log */ }
finally { server.Disconnect(); }
}
}
關鍵細節與避坑
| 問題 | 解決 |
| 訊息邊界 | 使用 `PipeTransmissionMode.Message` + `ReadAsync` 一次讀完整訊息;Byte 模式需自行定義長度前綴或分隔符 |
| 非同步效能 | 必須加 `PipeOptions.Asynchronous`,否則 `ReadAsync` 會同步阻塞執行緒集區 |
| 跨機器 | 用戶端建構函式第一參數改為伺服器主機名/IP (而非 `"."`),需開啟 SMB 連接埠 445、防火牆允許、雙方同網域/工作群組 |
| 權限/安全性 | 建構函式可傳 `PipeSecurity` 設定 ACL,限制特定使用者/群組連線 |
| 連線中斷偵測 | `ReadAsync` 回傳 0 表示用戶端關閉;捕獲 `IOException`/`ObjectDisposedException` |
| 大訊息 | 預設緩衝 4KB,大訊息需循環讀寫或增加 `inBufferSize`/`outBufferSize` 參數 |
替代方案比較
| 技術 | 優點 | 缺點 | 適用場景 |
| NamedPipe | 高效能、核心模式、安全、雙向、跨機器 | 僅限 Windows (CoreCLR 3.0+ 支援 Linux 但功能受限) | 同機/區域網高效能 IPC |
| MemoryMappedFile | 極高吞吐、共享記憶體 | 需自行同步 (Mutex/Semaphore)、無內建訊息框架 | 大資料共享、生產者消費者 |
| TCP Loopback | 跨平台、標準協定 | 網路堆疊開銷、需管理連接埠 | 微服務、容器間通訊 |
| gRPC / NamedPipe (Grpc.Net.NamedPipes) | Contract-first、IDL、多語言 | 引入依賴、序列化開銷 | 強型別 RPC、微服務 |
結語
.NET System.IO.Pipes` 讓命名管道程式化極為簡單:建立 Stream、非同步讀寫、處理連線生命週期。掌握 Message 模式、Asynchronous 選項、多實例伺服器模式、安全性設定 即可構建穩健高效的 IPC 通道。跨平台專案請改用 gRPC 或 TCP;Windows 專有高效能場景,NamedPipe 為首選。