C#与C++交互开辟系列(十八):跨历程通讯之命名管道(Named Pipes) ...

  金牌会员 | 2024-11-3 05:20:12 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 868|帖子 868|积分 2604


1、前言

在 C# 和 C++ 应用程序之间进行数据互换时,命名管道(Named Pipes)是一种简单高效的历程间通讯(IPC)方式。命名管道提供了可靠的双向通讯通道,适合用于同一台呆板上的跨历程通讯。本文将深入介绍如安在 C# 和 C++ 程序中利用命名管道进行数据传输,包罗详细的示例代码,帮助读者在实践中利用并调试这一技能。
2、什么是命名管道?

命名管道是 Windows 提供的一种 IPC 机制,支持双向数据流。与匿名管道不同,命名管道可以跨历程、跨用户访问。管道是由一个唯一的名称标识的,因此不同程序可以通过名称找到并利用相同的管道。命名管道适合中小规模的数据互换,对数据实时性和可靠性要求高的场景。
3、实现步调


  • C++ 端:创建命名管道并写入数据

    • 利用 Windows API CreateNamedPipe 创建管道。
    • 通过 WriteFile 写入数据到管道。
    • 调用 CloseHandle 关闭管道。

  • C# 端:连接到命名管道并读取数据

    • 利用 NamedPipeClientStream 连接受道。
    • 通过 StreamReader 读取数据。
    • 关闭连接。

4、示例代码

下面的代码展示了一个完整的跨历程通讯实例。C++ 程序作为管道服务器,创建命名管道并发送消息;C# 程序作为客户端,从管道读取数据。
4.1 C++ 服务器代码

首先,我们创建一个名为“MyPipe”的管道,并写入一条文本消息到管道中:
  1. #include <windows.h>
  2. #include <iostream>
  3. int main() {
  4.     // 创建命名管道
  5.     HANDLE hPipe = CreateNamedPipe(TEXT("\\\\.\\pipe\\MyPipe"),
  6.                                    PIPE_ACCESS_OUTBOUND,
  7.                                    PIPE_TYPE_BYTE | PIPE_WAIT,
  8.                                    1, 0, 0, 0, NULL);
  9.     if (hPipe == INVALID_HANDLE_VALUE) {
  10.         std::cerr << "Failed to create named pipe. Error: " << GetLastError() << std::endl;
  11.         return 1;
  12.     }
  13.     // 等待客户端连接
  14.     std::cout << "Waiting for client connection..." << std::endl;
  15.     if (ConnectNamedPipe(hPipe, NULL)) {
  16.         const char* message = "Hello from C++";
  17.         DWORD bytesWritten;
  18.         if (WriteFile(hPipe, message, strlen(message) + 1, &bytesWritten, NULL)) {
  19.             std::cout << "Message sent to client." << std::endl;
  20.         } else {
  21.             std::cerr << "Failed to write to pipe. Error: " << GetLastError() << std::endl;
  22.         }
  23.     } else {
  24.         std::cerr << "Failed to connect to named pipe. Error: " << GetLastError() << std::endl;
  25.     }
  26.     // 关闭管道句柄
  27.     CloseHandle(hPipe);
  28.     return 0;
  29. }
复制代码
  代码分析
  

  • CreateNamedPipe:创建一个名为“MyPipe”的命名管道,指定为字节流类型(PIPE_TYPE_BYTE)。
  • ConnectNamedPipe:期待客户端连接。
  • WriteFile:将文本消息写入管道中。
  4.2 C# 客户端代码

C# 客户端程序连接到同名的管道,并读取消息:
  1. using System;
  2. using System.IO;
  3. using System.IO.Pipes;
  4. class Program {
  5.     static void Main() {
  6.         // 连接到命名管道
  7.         using (var pipeClient = new NamedPipeClientStream(".", "MyPipe", PipeDirection.In)) {
  8.             pipeClient.Connect();
  9.             // 读取数据
  10.             using (var reader = new StreamReader(pipeClient)) {
  11.                 string message = reader.ReadToEnd();
  12.                 Console.WriteLine("Received from C++: " + message);
  13.             }
  14.         }
  15.     }
  16. }
复制代码
  代码分析
  

  • NamedPipeClientStream:创建命名管道客户端,连接到“MyPipe”管道。
  • StreamReader:用于从管道中读取数据,直到读取完毕。
  5、运行步调


  • 编译并运行 C++ 服务器程序,期待客户端连接。
  • 运行 C# 客户端程序,连接到管道并读取消息。
在运行过程中,C++ 服务器程序会输出“Waiting for client connection...”,当客户端连接后,客户端会显示从管道中接收到的消息“Received from C++: Hello from C++”。

6、留意事项


  • 命名管道名称:管道的名称在服务器和客户端之间必须一致。通常采用 \\.\pipe\PipeName 的格式,其中 PipeName 为自界说名称。
  • 双向通讯:可以通过设置 PIPE_ACCESS_DUPLEX 实现双向通讯,此时需要在服务器和客户端都调用 ReadFile 和 WriteFile。
  • 非常处理:在生产情况中,建议加入更多的非常处理,确保管道连接停止时可以大概正确地开释资源。
7、应用场景

命名管道非常适合用于以下场景:


  • 单机多历程数据互换:例如监控和控制体系,其中一个历程负责采集数据,另一个历程负责数据处理。
  • 实时数据传输:如实时日志记录,将数据从一个程序实时传输到另一个程序中进行存储或分析。
8、优缺点



  • 优点

    • 支持双向通讯。
    • 简单易用,无需复杂的网络配置。
    • 支持多客户端连接同一个命名管道。

  • 缺点

    • 仅适合同一台计算机上的历程间通讯。
    • 传输速率相对较慢,不适合大规模数据传输。

9、总结

命名管道是一种高效、可靠的 IPC 方式,在需要简单、双向的本地通讯场景中非常适用。通过利用 C# 和 C++ 两种语言编写的示例程序,展示了怎样创建和利用命名管道实现跨历程的数据传输。在现实应用中,可以根据业务需求调解管道名称、数据流向和非常处理,使其更好地服务于体系需求。
在下一篇文章中,我们将讨论怎样利用 套接字(Sockets) 进行跨历程通讯,这种方法支持跨网络的数据传输,适用于分布式体系。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表