在 C# 中实现进程间通信(IPC,Inter-Process Communication)有多种方式,适用于不同场景。以下是常见 IPC 方法的实现方案、代码示例及适用场景对比:
1. 命名管道(Named Pipes)
特点:适用于同一台机器上的进程通信,支持双向流式传输,性能较高。
服务端(.NET Framework 或 .NET Core)
cs
using System.IO.Pipes;
// 服务端代码
var server = new NamedPipeServerStream("MyPipe", PipeDirection.InOut);
server.WaitForConnection(); // 等待客户端连接
// 写入数据到管道
using (var writer = new StreamWriter(server))
{
writer.WriteLine("Hello from Server!");
writer.Flush();
}
// 读取客户端数据
using (var reader = new StreamReader(server))
{
string message = reader.ReadLine();
Console.WriteLine($"Received: {message}");
}
server.Close();
客户端(.NET Framework 或 .NET Core)
csharp
cs
using System.IO.Pipes;
var client = new NamedPipeClientStream(".", "MyPipe", PipeDirection.InOut);
client.Connect(); // 连接服务端
// 读取服务端数据
using (var reader = new StreamReader(client))
{
string message = reader.ReadLine();
Console.WriteLine($"Received: {message}");
}
// 向服务端发送数据
using (var writer = new StreamWriter(client))
{
writer.WriteLine("Hello from Client!");
writer.Flush();
}
client.Close();
2. 内存映射文件(Memory-Mapped Files)
特点:适合大量数据共享,支持跨进程内存直接访问。
写入数据(进程 A)
csharp
cs
using System.IO.MemoryMappedFiles;
// 创建内存映射文件
using (var mmf = MemoryMappedFile.CreateOrOpen("MySharedMemory", 1024))
using (var accessor = mmf.CreateViewAccessor())
{
// 写入字符串
accessor.Write(0, 123); // 写入整数
accessor.Write(4, (byte)1); // 写入字节
accessor.WriteArray(5, Encoding.UTF8.GetBytes("Hello from Process A"), 0, 20);
}
读取数据(进程 B)
csharp
cs
using System.IO.MemoryMappedFiles;
using (var mmf = MemoryMappedFile.OpenExisting("MySharedMemory"))
using (var accessor = mmf.CreateViewAccessor())
{
int number = accessor.ReadInt32(0);
byte flag = accessor.ReadByte(4);
byte[] buffer = new byte[20];
accessor.ReadArray(5, buffer, 0, 20);
string text = Encoding.UTF8.GetString(buffer).TrimEnd('\0');
Console.WriteLine($"{number}, {flag}, {text}");
}
3. 套接字(TCP/UDP Sockets)
特点:支持跨机器通信,灵活性高。
服务端(TCP)
csharp
cs
using System.Net;
using System.Net.Sockets;
var listener = new TcpListener(IPAddress.Any, 8080);
listener.Start();
var client = listener.AcceptTcpClient();
using (var stream = client.GetStream())
using (var writer = new StreamWriter(stream))
using (var reader = new StreamReader(stream))
{
writer.WriteLine("Hello from Server!");
writer.Flush();
string response = reader.ReadLine();
Console.WriteLine($"Received: {response}");
}
listener.Stop();
客户端(TCP)
csharp
cs
using (var client = new TcpClient("localhost", 8080))
using (var stream = client.GetStream())
using (var reader = new StreamReader(stream))
using (var writer = new StreamWriter(stream))
{
string message = reader.ReadLine();
Console.WriteLine($"Received: {message}");
writer.WriteLine("Hello from Client!");
writer.Flush();
}
4. gRPC(跨平台 RPC 框架)
特点:高性能、跨语言、支持 HTTP/2,适合分布式系统。
定义 Proto 文件(greet.proto
)
protobuf
cs
syntax = "proto3";
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
服务端(.NET Core)
cs
using Grpc.Core;
public class GreeterService : Greeter.GreeterBase
{
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
return Task.FromResult(new HelloReply { Message = $"Hello {request.Name}" });
}
}
var server = new Server
{
Services = { Greeter.BindService(new GreeterService()) },
Ports = { new ServerPort("localhost", 50051, ServerCredentials.Insecure) }
};
server.Start();
Console.WriteLine("Server running...");
Console.ReadLine();
server.ShutdownAsync().Wait();
客户端(.NET Framework 或 .NET Core)
cs
using Grpc.Core;
var channel = new Channel("localhost:50051", ChannelCredentials.Insecure);
var client = new Greeter.GreeterClient(channel);
var reply = client.SayHello(new HelloRequest { Name = "World" });
Console.WriteLine(reply.Message);
channel.ShutdownAsync().Wait();
5. 消息队列(例如 RabbitMQ)
特点:异步、解耦,适合分布式系统。
生产者
cs
using RabbitMQ.Client;
var factory = new ConnectionFactory() { HostName = "localhost" };
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{
channel.QueueDeclare(queue: "hello", durable: false, exclusive: false, autoDelete: false, arguments: null);
string message = "Hello from Producer!";
var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(exchange: "", routingKey: "hello", basicProperties: null, body: body);
}
消费者
cs
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
var factory = new ConnectionFactory() { HostName = "localhost" };
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{
channel.QueueDeclare(queue: "hello", durable: false, exclusive: false, autoDelete: false, arguments: null);
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
var body = ea.Body.ToArray();
var message = Encoding.UTF8.GetString(body);
Console.WriteLine($"Received: {message}");
};
channel.BasicConsume(queue: "hello", autoAck: true, consumer: consumer);
Console.ReadLine();
}
6. WCF(仅限 Windows,.NET Framework)
特点:支持多种协议(HTTP、TCP、Named Pipes),但需在 .NET Core 中使用替代方案(如 CoreWCF)。
服务端(.NET Framework)
cs
[ServiceContract]
public interface IGreeter
{
[OperationContract]
string SayHello(string name);
}
public class GreeterService : IGreeter
{
public string SayHello(string name) => $"Hello {name}";
}
// 宿主代码
var baseAddress = new Uri("http://localhost:8000/");
using (var host = new ServiceHost(typeof(GreeterService), baseAddress))
{
host.AddServiceEndpoint(typeof(IGreeter), new BasicHttpBinding(), "");
host.Open();
Console.WriteLine("Server running...");
Console.ReadLine();
host.Close();
}
客户端(.NET Framework)
cs
var binding = new BasicHttpBinding();
var endpoint = new EndpointAddress("http://localhost:8000/");
var channelFactory = new ChannelFactory<IGreeter>(binding, endpoint);
var greeter = channelFactory.CreateChannel();
Console.WriteLine(greeter.SayHello("World"));
IPC 方法对比
方法 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
命名管道 | 同一机器上的高速双向通信 | 低延迟,简单易用 | 仅限同一机器,Windows 支持更成熟 |
内存映射文件 | 共享大量数据(如图像、日志) | 高性能,直接内存访问 | 需手动处理同步机制 |
套接字(TCP) | 跨机器通信或复杂网络场景 | 跨平台,灵活性强 | 需处理网络协议和序列化 |
gRPC | 跨语言、跨平台的高性能 RPC | 自动代码生成,支持流式通信 | 需定义 Proto 文件,依赖 HTTP/2 |
消息队列 | 异步解耦的分布式系统 | 高可靠性,支持负载均衡 | 需中间件(如 RabbitMQ) |
WCF/CoreWCF | 企业级复杂通信(Windows 为主) | 统一多种协议,安全性高 | .NET Core 支持有限,配置复杂 |
选择建议
-
同一机器 :优先使用 命名管道 (简单高效)或 内存映射文件(大数据共享)。
-
跨机器/跨平台 :选择 gRPC (高性能 RPC)或 TCP 套接字(灵活性高)。
-
异步解耦 :使用 消息队列(如 RabbitMQ)实现可靠的消息传递。
-
遗留系统整合 :若必须使用 WCF,可在 .NET Core 中尝试 CoreWCF。