[C#与C++交互] 跨进程通信NamedPipes

目录

1、前言

2、什么是命名管道?

3、实现步骤

4、示例代码

[4.1 C++ 服务器代码](#4.1 C++ 服务器代码)

[4.2 C# 客户端代码](# 客户端代码)

5、运行步骤

6、注意事项

7、应用场景

8、优缺点

9、总结


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"的管道,并写入一条文本消息到管道中:

cpp 复制代码
#include <windows.h>
#include <iostream>

int main() {
    // 创建命名管道
    HANDLE hPipe = CreateNamedPipe(TEXT("\\\\.\\pipe\\MyPipe"),
                                   PIPE_ACCESS_OUTBOUND,
                                   PIPE_TYPE_BYTE | PIPE_WAIT,
                                   1, 0, 0, 0, NULL);

    if (hPipe == INVALID_HANDLE_VALUE) {
        std::cerr << "Failed to create named pipe. Error: " << GetLastError() << std::endl;
        return 1;
    }

    // 等待客户端连接
    std::cout << "Waiting for client connection..." << std::endl;
    if (ConnectNamedPipe(hPipe, NULL)) {
        const char* message = "Hello from C++";
        DWORD bytesWritten;
        if (WriteFile(hPipe, message, strlen(message) + 1, &bytesWritten, NULL)) {
            std::cout << "Message sent to client." << std::endl;
        } else {
            std::cerr << "Failed to write to pipe. Error: " << GetLastError() << std::endl;
        }
    } else {
        std::cerr << "Failed to connect to named pipe. Error: " << GetLastError() << std::endl;
    }

    // 关闭管道句柄
    CloseHandle(hPipe);
    return 0;
}

代码解析:

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

4.2 C# 客户端代码

C# 客户端程序连接到同名的管道,并读取消息:

cs 复制代码
using System;
using System.IO;
using System.IO.Pipes;

class Program {
    static void Main() {
        // 连接到命名管道
        using (var pipeClient = new NamedPipeClientStream(".", "MyPipe", PipeDirection.In)) {
            pipeClient.Connect();

            // 读取数据
            using (var reader = new StreamReader(pipeClient)) {
                string message = reader.ReadToEnd();
                Console.WriteLine("Received from C++: " + message);
            }
        }
    }
}

代码解析:

  • 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) 进行跨进程通信,这种方法支持跨网络的数据传输,适用于分布式系统。

相关推荐
程序猿000001号几秒前
使用Python的Turtle库绘制图形:初学者指南
开发语言·python
carlcarl09032 分钟前
qt通过QAxObject操作word插入表格及数据,图片生成文档
开发语言·c#
萝诗粉4 分钟前
c语言在程序开发过程的各个阶段遇到的问题和知识总结
c语言·开发语言
快乐飒男13 分钟前
C语言基础13(内存管理)
c语言·开发语言·学习
西猫雷婶30 分钟前
python学opencv|读取图像(十一)彩色图像转灰度图的两种办法
开发语言·人工智能·python·opencv·计算机视觉
小憩-38 分钟前
【重生之我要苦学C语言】文件操作
c语言·开发语言
程序leo源39 分钟前
深入理解指针
android·c语言·开发语言·汇编·c++·青少年编程·c#
程序员黄同学40 分钟前
如何使用 Python 读取文本文件?
开发语言·python
因特麦克斯40 分钟前
C++ 中面向对象编程如何实现动态绑定?C++如何管理内存?
开发语言·c++