C# 的进程间通信(IPC,Inter-Process Communication)

🧭 一、IPC 是什么?

IPC(Inter-Process Communication) 是指:

在同一台计算机上,不同进程之间传递数据、信号或消息的机制。

常见用途:

  • C# 主程序与后台服务通信

  • GUI 应用与命令行程序交互、

  • 前端与后端(不同进程)传输 JSON

  • 与 C++、Python、Java 等跨语言进程通信


🧩 二、C# 支持的 IPC 方式总览

|-------------------------------------------|---------------------|------|-------|------------------|
| IPC方式 | 平台 | 性能 | 是否跨平台 | 特点 |
| Named Pipe(命名管道) | Windows/Linux/macOS | ⭐⭐⭐⭐ | ✅ | 速度快,操作系统原生支持 |
| Memory-Mapped File(内存映射文件) | Windows/Linux | ⭐⭐⭐⭐ | ✅ | 共享大块数据最快方式 |
| Socket(TCP/UDP) | 所有平台 | ⭐⭐⭐ | ✅ | 通用性最强,可跨机器 |
| gRPC / HTTP / REST | 所有平台 | ⭐⭐ | ✅ | 最易用,跨语言;性能较低 |
| MessageQueue / ZeroMQ / RabbitMQ | 所有平台 | ⭐⭐⭐ | ✅ | 异步、高并发;复杂度高 |
| WCF(Windows Communication Foundation) | Windows | ⭐⭐⭐ | ❌ | 功能强,但已不推荐用于新项目 |
| SignalR / WebSocket | 所有平台 | ⭐⭐⭐ | ✅ | 实时通信、配合 Web 应用常用 |


⚙️ 三、常用实现方式详解 + 示例


① Named Pipe(命名管道)

📦 适用场景: 同一台机器上两个进程通信

📈 优点: 速度快、无需网络栈、支持字符串与二进制

🧩 跨平台: ✅(.NET 5+)

▶ Server(服务端)
复制代码
using System.IO.Pipes;
using System.Text;

class PipeServer
{
    static void Main()
    {
        using var server = new NamedPipeServerStream("MyPipe", PipeDirection.InOut, 1);
        Console.WriteLine("等待客户端连接...");
        server.WaitForConnection();

        using var reader = new StreamReader(server, Encoding.UTF8);
        using var writer = new StreamWriter(server, Encoding.UTF8) { AutoFlush = true };

        Console.WriteLine("客户端已连接");
        while (true)
        {
            string? msg = reader.ReadLine();
            if (msg == null || msg == "exit") break;
            Console.WriteLine($"收到: {msg}");
            writer.WriteLine($"服务器收到: {msg}");
        }
    }
}
▶ Client(客户端)
复制代码
using System.IO.Pipes;
using System.Text;

class PipeClient
{
    static void Main()
    {
        using var client = new NamedPipeClientStream(".", "MyPipe", PipeDirection.InOut);
        client.Connect();

        using var reader = new StreamReader(client, Encoding.UTF8);
        using var writer = new StreamWriter(client, Encoding.UTF8) { AutoFlush = true };

        for (int i = 0; i < 3; i++)
        {
            writer.WriteLine($"消息 {i}");
            Console.WriteLine(reader.ReadLine());
        }

        writer.WriteLine("exit");
    }
}

✅ 特点:

  • 多个客户端可连接同一个管道(指定 maxNumberOfServerInstances)
  • 支持异步版本:WaitForConnectionAsync()、ReadAsync()
  • 适合进程间命令传递或 JSON 消息传输

② Memory-Mapped File(内存映射文件)

📦 适用场景: 需要共享大块数据(如图像、缓存)

📈 优点: 读写极快

📉 缺点: 需要同步机制防止并发问题

▶ 写入进程
复制代码
using System.IO.MemoryMappedFiles;
using System.Text;

class Writer
{
    static void Main()
    {
        using var mmf = MemoryMappedFile.CreateOrOpen("SharedMemory", 1024);
        using var accessor = mmf.CreateViewAccessor();

        string message = "Hello from Process A";
        byte[] bytes = Encoding.UTF8.GetBytes(message);
        accessor.WriteArray(0, bytes, 0, bytes.Length);

        Console.WriteLine("写入完成");
        Console.ReadLine();
    }
}
▶ 读取进程
复制代码
using System.IO.MemoryMappedFiles;
using System.Text;

class Reader
{
    static void Main()
    {
        using var mmf = MemoryMappedFile.OpenExisting("SharedMemory");
        using var accessor = mmf.CreateViewAccessor();

        byte[] buffer = new byte[1024];
        accessor.ReadArray(0, buffer, 0, buffer.Length);

        Console.WriteLine("读取内容: " + Encoding.UTF8.GetString(buffer).TrimEnd('\0'));
    }
}

③ Socket(TCP)

📦 适用场景: 不仅限于本机,可跨网络通信

📈 优点: 通用性最强

📉 缺点: 需要管理连接、心跳、序列化等

▶ Server
复制代码
using System.Net;
using System.Net.Sockets;
using System.Text;

class TcpServer
{
    static async Task Main()
    {
        var listener = new TcpListener(IPAddress.Loopback, 5000);
        listener.Start();
        Console.WriteLine("等待客户端...");
        var client = await listener.AcceptTcpClientAsync();

        using var stream = client.GetStream();
        byte[] buffer = new byte[1024];
        int len = await stream.ReadAsync(buffer);
        Console.WriteLine("收到: " + Encoding.UTF8.GetString(buffer, 0, len));
    }
}
▶ Client
复制代码
using System.Net.Sockets;
using System.Text;

class TcpClientDemo
{
    static async Task Main()
    {
        var client = new TcpClient();
        await client.ConnectAsync("127.0.0.1", 5000);

        using var stream = client.GetStream();
        byte[] data = Encoding.UTF8.GetBytes("Hello Server");
        await stream.WriteAsync(data);
    }
}

④ gRPC / HTTP / SignalR

📦 适用场景: 跨平台、跨语言通信(如 C# ↔ Python)

🧩 实现: 使用 ASP.NET Core Web API 或 gRPC 服务

📈 优点: 简单直观、兼容多语言

📉 缺点: 性能不如管道 / 内存映射


🧠 四、选型建议(按场景)

|----------------|-----------------------------------|---------|
| 场景 | 推荐方式 | 说明 |
| 同机 C# ↔ C# 通信 | Named Pipe | 简单高效 |
| 同机 C# ↔ C++ 通信 | Named Pipe 或 MemoryMappedFile | 跨语言易实现 |
| 多机通信 | Socket / gRPC | 通用 |
| GUI ↔ 后台守护进程 | Named Pipe + JSON 消息 | 稳定、方便调试 |
| 高速数据共享(如图像帧) | Memory-Mapped File | 低延迟 |


🧰 五、调试与编码注意点

  1. 统一编码
    使用 Encoding.UTF8,避免乱码。

  2. 结构化数据
    使用 JSON(System.Text.Json)序列化传输结构体。

    var json = JsonSerializer.Serialize(obj);

  3. 错误处理
    IPC 通常易出问题,要加超时、断线重连、异常捕获。

  4. 异步通信
    推荐使用 ReadAsync() / WriteAsync(),避免阻塞主线程。


🧩 六、JSON 通信模板(推荐现代做法)

Server:

复制代码
var server = new NamedPipeServerStream("MyPipe");
await server.WaitForConnectionAsync();

using var reader = new StreamReader(server);
using var writer = new StreamWriter(server) { AutoFlush = true };

while (true)
{
    var line = await reader.ReadLineAsync();
    if (line == null) break;

    var msg = JsonSerializer.Deserialize<Message>(line);
    Console.WriteLine($"收到指令: {msg.Command}");

    var reply = new Message { Command = "ACK", Data = "OK" };
    await writer.WriteLineAsync(JsonSerializer.Serialize(reply));
}

record Message { public string Command { get; set; } public string Data { get; set; } }
相关推荐
夏幻灵2 小时前
JavaScript this 面试:五种绑定规则、优先级与常见面试陷阱
开发语言·javascript·面试
程序猿编码2 小时前
榨干 RTX5090 算力!Qwen3 专用单卡推理引擎,手写C++/CUDA 算子实现 MTP 推测解码
开发语言·c++·大模型推理·qwen3·多模态推理
曹牧3 小时前
C#:未被引用的函数
c#
bkspiderx3 小时前
Qt 插件机制:动态扩展应用功能的核心框架
开发语言·qt·元数据·qt 插件·qpluginloader
程序员老陆3 小时前
深入理解 C++ thread_local:线程私有存储的正确打开方式
开发语言·c++·程序设计
沐晓时光4 小时前
C语言入门,深入理解指针(3)
c语言·开发语言
码云数智-园园4 小时前
unique_ptr 还是 shared_ptr?C++ 智能指针选型与内存泄漏实战分析
java·开发语言
禾小西5 小时前
07丨Redis 哨兵机制:主库故障后,如何恢复服务?
java·开发语言·redis
我不是阵雨5 小时前
JDK 21虚拟线程Pinning陷阱:一文拔钉解困
java·开发语言
徐小黑ACG5 小时前
Golang 基础05 结构体struct
开发语言·算法·golang