前段时间,因新项目是的 x64
的,而老项目是 x86
的,新老项目又有一个共用的底层库是 x86
的,本来我新项目编译为any CPU
时在调用公共底层库也是没问题的,但是还有一个用于连接仪器的外部 c++
库文件是 x64
,此时 any cpu
的新项目, x86
底层库,加一个 x64
的外部 c++
库,此时这个 c++
库文件就无法使用了,为了糅合这种情况,也为了把公共底层库剥离出来(因为后续新项目仍然会用该库),想办法采用进程间通讯的方式,来解决这一问题
注意
以下内容来自AI
命名管道(Named Pipe)是一种用于进程间通信(IPC,Inter-Process Communication) 的机制,主要作用是实现同一台计算机上不同进程之间(或网络中不同计算机的进程之间)的数据传输和交互。它是操作系统提供的一种高级IPC方式,相比其他通信方式(如信号、共享内存等)。
本地进程间通信
最常见的用途是在同一台计算机上的不同进程之间传递数据。例如:
跨网络通信
命名管道支持网络通信(如Windows的"命名管道网络协议"),允许不同计算机上的进程通过网络进行数据交互。例如:
双向通信支持
命名管道可以配置为双向通信模式(PipeDirection.InOut
),允许通信双方既发送数据又接收数据,适合需要交互对话的场景(如客户端与服务端的命令交互)。
可靠的数据传输
命名管道提供基于"流"或"消息"的传输模式,确保数据按顺序、完整地传递,避免数据丢失或错乱。例如:
PipeTransmissionMode.Message
模式时,接收方可以按消息边界准确拆分数据,无需手动处理分包。安全性控制
支持通过权限设置(如PipeSecurity
)限制访问者,确保只有授权进程能连接或读写数据,适合传输敏感信息。
总之,命名管道是一种平衡了易用性、安全性和效率的IPC机制,尤其在Windows环境下被广泛用于进程间的数据交互。
代码如下:
csharpusing System;
using System.IO;
using System.IO.Pipes;
using System.Text;
using System.Threading.Tasks;
class PipeClient
{
static void Main(string[] args)
{
Console.WriteLine("命名管道客户端已启动...");
Console.WriteLine("尝试连接到服务端...");
// 创建命名管道客户端流,连接到本地计算机上的管道
var clientStream = new NamedPipeClientStream(
".", // 服务器名称,"." 表示本地计算机
"MyNamedPipe", // 管道名称,必须与服务端一致
PipeDirection.InOut, // 双向通信
PipeOptions.Asynchronous);
try
{
// 连接到服务端,超时时间设置为5秒
clientStream.Connect(5000);
Console.WriteLine("已成功连接到服务端!");
// 使用StreamReader和StreamWriter简化读写操作
var reader = new StreamReader(clientStream, Encoding.UTF8);
var writer = new StreamWriter(clientStream, Encoding.UTF8);
string serverMessage;
// 循环发送消息到服务端
while (true)
{
Console.Write("请输入要发送给服务端的消息(输入exit退出): ");
string clientMessage = Console.ReadLine();
// 发送消息到服务端
writer.WriteLine(clientMessage);
writer.Flush();
// 如果客户端发送"exit",则退出通信
if (clientMessage.Equals("exit", StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("客户端请求断开连接...");
break;
}
// 等待服务端回应
serverMessage = reader.ReadLine();
if (serverMessage == null)
{
Console.WriteLine("服务端已断开连接");
break;
}
Console.WriteLine($"收到服务端消息: {serverMessage}");
// 如果服务端发送"exit",则退出通信
if (serverMessage.Equals("exit", StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("服务端请求断开连接...");
break;
}
}
}
catch (TimeoutException)
{
Console.WriteLine("连接超时,无法连接到服务端");
}
catch (IOException ex)
{
Console.WriteLine($"通信错误: {ex.Message}");
}
Console.WriteLine("客户端已停止,按任意键退出...");
Console.ReadKey();
}
}
代码如下:
csharpusing System;
using System.IO;
using System.IO.Pipes;
using System.Text;
using System.Threading.Tasks;
class PipeServer
{
static void Main(string[] args)
{
Console.WriteLine("命名管道服务端已启动...");
Console.WriteLine("等待客户端连接...");
// 创建命名管道服务器流,使用 "." 表示本地计算机
var serverStream = new NamedPipeServerStream(
"MyNamedPipe", // 管道名称
PipeDirection.InOut, // 双向通信
NamedPipeServerStream.MaxAllowedServerInstances,
PipeTransmissionMode.Message,
PipeOptions.Asynchronous);
// 等待客户端连接
serverStream.WaitForConnection();
Console.WriteLine("客户端已连接!");
// 使用StreamReader和StreamWriter简化读写操作
var reader = new StreamReader(serverStream, Encoding.UTF8);
var writer = new StreamWriter(serverStream, Encoding.UTF8);
try
{
string clientMessage;
// 循环接收客户端消息
while (true)
{
clientMessage = reader.ReadLine();
Console.WriteLine($"收到客户端消息: {clientMessage}");
// 如果客户端发送"exit",则退出通信
if (clientMessage.Equals("exit", StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("客户端请求断开连接...");
break;
}
// 向客户端发送回应
Console.Write("请输入要发送给客户端的消息: ");
string serverMessage = Console.ReadLine();
writer.WriteLine(serverMessage);
writer.Flush();
// 如果服务端发送"exit",则退出通信
if (serverMessage.Equals("exit", StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("服务端请求断开连接...");
break;
}
}
}
catch (IOException ex)
{
Console.WriteLine($"通信错误: {ex.Message}");
}
Console.WriteLine("连接已关闭");
Console.WriteLine("服务端已停止,按任意键退出...");
Console.ReadKey();
}
}
将上述两个控制台程序编译后,直接运行两个程序后,会自动连接,如下图:
在开发和测试过程中,也发现一些问题:
所以,重点关注第二节中命名管道的核心作用描述中的场景,仅在这些场景下,推荐使用命名管道进行进程间通讯。
本文作者:Peter.Pan
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!