进程间通信详解 - 命名管道实现

C++命名管道实战:手把手教你用CreateNamedPipe实现进程间通信(附完整代码) 本文通过实战案例,手把手教你使用C++的CreateNamedPipe函数在Windows平台实现进程间通信。文章详细解析了命名管道的核心概念、优势以及服务器端与客户端的完整代码实现,帮助开发者快速掌握这一高效、可靠的本地IPC技术,并提供了处理多客户端、错误处理等进阶实践指导。 阅读详情
 

引子

好,到这里呢,就需要介绍实现进程间通信的第四种方式了,

也就是通过命名管道来实现,前面介绍的那三种方式呢,都是有缺陷或者说局限性太强,

而这里介绍的命名管道相对来说,在这方面就做得好很多了,

比如,剪贴板的话只能实现本机上进程之间的通信,

而邮槽的话虽然是可以实现跨网络之间的进程的通信,

但麻烦的是邮槽的服务端只能接收数据,邮槽的客户端只能发送数据,太悲剧了,

而对于匿名管道的话,其也只能实现本机上进程之间的通信,

你要是能够实现本机进程间的通信也就算了,

关键是它还只用来实现本地的父子进程之间的通信,也太局限了吧?

而这里介绍的这个命名管道的话,就和他们有些不同了,在功能上也就显得强大很多了,

至少其可以实现跨网络之间的进程的通信,同时其客户端既可以接收数据也可以发送数据,

服务端也是既可以接收数据,又可以发送数据的。

             

             

命名管道概述

命名管道是通过网络来完成进程之间的通信的,命名管道依赖于底层网络接口,

其中包括有 DNS 服务,TCP/IP 协议等等机制,但是其屏蔽了底层的网络协议细节,

对于匿名管道而言,其只能实现在父进程和子进程之间进行通信,而对于命名管道而言,

其不仅可以在本地机器上实现两个进程之间的通信,还可以跨越网络实现两个进程之间的通信。

命名管道使用了 Windows 安全机制,因而命名管道的服务端可以控制哪些客户有权与其建立连接,

而哪些客户端是不能够与这个命名管道建立连接的。

利用命名管道机制实现不同机器上的进程之间相互进行通信时,

可以将命名管道作为一种网络编程方案时,也就是看做是 Socket 就可以了,

它实际上是建立了一个客户机/服务器通信体系,并在其中可靠的传输数据。

命名管道的通信是以连接的方式来进行的,

服务器创建一个命名管道对象,然后在此对象上等待连接请求,

一旦客户连接过来,则两者都可以通过命名管道读或者写数据。

                

命名管道提供了两种通信模式:字节模式和消息模式。

在字节模式下,数据以一个连续的字节流的形式在客户机和服务器之间流动,

而在消息模式下,客户机和服务器则通过一系列的不连续的数据单位,进行数据的收发,

每次在管道上发出一个消息后,它必须作为一个完整的消息读入。

               

            

命名管道使用流程

服务端:

服务端进程调用 CreateNamedPipe 函数来创建一个有名称的命名管道,

在创建命名管道的时候必须指定一个本地的命名管道名称(不然就不叫命名管道了),

Windows 允许同一个本地的命名管道名称有多个命名管道实例,

所以,服务器进程在调用 CreateNamedPipe 函数时必须指定最大允许的实例数(0 -255),

如果 CreateNamedPipe 函数成功返回后,服务器进程得到一个指向一个命名管道实例的句柄,

然后,服务器进程就可以调用 ConnectNamedPipe 来等待客户的连接请求,

这个 ConnectNamedPipe 既支持同步形式,又支持异步形式,

若服务器进程以同步形式调用 ConnectNamedPipe 函数,

(同步方式也就是如果没有得到客户端的连接请求,则会一直等到)

那么,当该函数返回时,客户端与服务器之间的命名管道连接也就已经建立起来了。

在已经建立了连接的命名管道实例中,

服务端进程就会得到一个指向该管道实例的句柄,这个句柄称之为服务端句柄。

同时,服务端进程可以调用 DisconnectNamedPipe 函数,

将一个管道实例与当前建立连接的客户端进程断开,从而可以重新连接到新的客户进程。

当然在服务端也是可以调用 CloseHandle 来关闭一个已经建立连接的命名管道实例。

客户端

客户端进程调用 CreateFile 函数连接到一个正在等待连接的命名管道上,

在这里客户端需要指定将要连接的命名管道的名称,

当 CreateFile 成功返回后,客户进程就得到了一个指向已经建立连接的命名管道实例的句柄,

到这里,服务器进程的 ConnectNamedPipe 也就完成了其建立连接的任务。

客户端进程除了调用 CreateFile 函数来建立管道连接以外,

还可以调用 WaitNamedPipe 函数来测试指定名称的管道实例是否可用。

在已经建立了连接的命名管道实例中,客户端进程就会得到一个指向该管道实例的句柄,

这个句柄称之为客户端句柄。

在客户端可以调用 CloseHandle 来关闭一个已经建立连接的命名管道实例。

          

             

服务端创建命名管道

HANDLE  WINAPI   CreateNamedPipe(
   __in    LPCTSTR lpName,
  __in    DWORD dwOpenMode,
  __in    DWORD dwPipeMode,
  __in    DWORD nMaxInstances,
   __in    DWORD nOutBufferSize,
  __in    DWORD nInBufferSize,
   __in    DWORD nDefaultTimeOut,
  __in    LPSECURITY_ATTRIBUTES lpSecurityAttributes
               );

该函数用来创建一个命名管道的实例,并返回这个命名管道的句柄,

一个命名管道的服务器进程使用该函数创建命名管道的第一个实例,

并建立它的基本属性,或者创建一个现有的命名管道的新实例。

如果需要创建一个命名管道的多个实例,就需要多次调用 CreateNamedPipe 函数。

参数 lpName 为一个字符串,其格式必须为 \\.\pipe\pipeName ,其中圆点 ”.” 表示的是本地机器,

如果想要与远程的服务器建立连接,那么这个圆点位置处应指定这个远程服务器的名称,

而其中的 “pipe” 这个是个固定的字符串,也就是说不能进行改变的,

最后的 “pipename” 则代表的是我将要创建的命名管道的名称了。

参数 dwOpenMode 用来指定管道的访问方式,重叠方式,写直通方式,还有管道句柄的安全访问方式。

同一个命名管道的每一个实例都必须具有相同的类型。

如果该参数设置为 0 ,则默认将使用字节类型方式,即通过这个参数可指定创建的是字节模式还是消息流模式。

对于管道句柄的读取方式来说,同一个管道的不同实例可以指定不同的读取方式。

如果该值为 0 ,则默认将使用字节读方式。

而对于管道句柄的等待方式,则同一个管道的不同实例可以取不同的等待方式。

如果该值设置为 0 ,则默认为阻塞方式。

命名管道的访问方式如下表所列:

值

解释

PIPE_ACCESS_DUPLEX

双向模式。

服务器进程和客户端进程都可以从管道读取数据和向管道中写入数据。

PIPE_ACCESS_INBOUND

服务器端就只能读取数据,而客户端就只能向管道中写入数据。

PIPE_ACCESS_OUTBOUND

服务器端就只能写入数据,而客户端就只能从管道中读取数据。

命名管道的写直通方式和重叠方式:

值

解释

FILE_FLAG_WRITE_THROUGH

写直通方式(可以简单的看做是同步操作)。

该方式只影响对字节类型管道的写入操作。

且只有当客户端与服务端进程位于不同的计算机上时才有效。

该方式只有等到欲写入命名管道的数据通过网络传送出去,

并且放置到了远程计算机的管道缓冲区以后,

写数据的函数才会成功返回。

FILE_FLAG_OVERLAPPED

重叠模式(可以简单的看做是异步操作)。

实现前台线程执行其他操作,而耗时操作可在后台进行。

命名管道的安全访问方式:

值

解释

WRITE_DAC

调用者对命名管道的任意访问控制列表都可以进行写入。

WRITE_OWNER

调用者对命名管道的所有者可以进行写入访问。

ACCESS_SYSTEM_SECURITY

调用者对命名管道的安全访问控制列表都可以写入。

参数 dwPipeMode 用来指定管道句柄的类型,读取和等待方式。

命名管道句柄的类型:

值

解释

PIPE_TYPE_BYTE

数据以字节流的形式写入管道。

该方式不能在 PIPE_READMODE_MESSAGE 读方式下使用。

PIPE_TYPE_MESSAGE

数据以消息流的形式写入管道。

命名管道句柄的读取方式:

值

解释

PIPE_READMODE_BYTE

以字节流的方式从管道中发读取数据。

PIPE_READMODE_MESSAGE

以消息流的方式从管道读取数据。

该方式只有在 PIPE_TYPE_MESSAGE 类型下才可以使用。

命名管道句柄的等待方式:

值

解释

PIPE_WAIT

允许阻塞方式也就是同步方式。

ReadFile,WriteFile,ConnectNamedPipe 函数,

必须等到读取到数据或写入新数据或有一个客户连接来才能返回。

PIPE_NOWAIT

允许非阻塞方式也就是异步方式。

ReadFile,WriteFile,ConnectNamedPipe 函数总是立即返回。

参数 nMaxInstance 指定命名管道能够创建的实例的最大数目。

该参数的取值可以从 0 – 255 ,这里说的最大实例数目是指对同一个命名管道最多能创建的实例数目,

如果希望同时连接 5 个客户端,那么则必须调用 5 次 CreateNamedPipe 函数创建 5 个命名管道实例,

然后才能同时接收到 5 个客户端连接请求的到来,

对于同一个命名管道的实例来说,在某一个时刻,它只能和一个客户端进行通信。

参数 nOutBufferSize 用来指定将要为输出缓冲区所保留的字节数。

参数 nInBufferSize 用来指定将要为输入缓冲区所保留的字节数。

参数 nDefaultTimeOut 用来指定默认的超时值,以毫秒为单位,同一个管道的不同实例必须指定同样的超时值。

参数 lpSecurityAttributes 用来设置该命名管道的安全性,

一般设置为 NULL ,也就是采用 Windows 提供的默认安全性。

         

           

服务端等待客户端连接请求

BOOL  WINAPI  ConnectNamedPipe(
          __in    HANDLE hNamedPipe,
          __in    LPOVERLAPPED lpOverlapped
          );

该函数的作用是让服务器等待客户端的连接请求的到来。

参数  hNamedPipe 指向一个命名管道实例的服务器的句柄。

该句柄由 CreateNamedPipe 函数返回。

参数 lpOverlapped 指向一个 OVERLAPPED 结构的指针,

如果 hNamedPipe 所标识的命名管道是用 FILE_FLAG_OVERLAPPED ,

(也就是重叠模式或者说异步方式)标记打开的,则这个参数不能为 NULL ,

必须是一个有效的指向一个 OVERLAPPED 结构的指针,否则该函数可能会错误的执行。

              

                

客户端连接命名管道

BOOL  WINAPI  WaitNamedPipe(
        __in    LPCTSTR lpNamedPipeName,
         __in    DWORD nTimeOut
          );

客户端在连接服务端程序创建的命名管道之前,

首先应该判断一下,是否有可以利用的命名管道,

通过调用该函数可以用来实现这一点,该函数会一直等到,

直到等待的时间间隔已过,或者指定的命名管道的实例可以用来连接了,

也就是说该管道的服务器进程有正在等待被连接的的 ConnectNamedPipe 操作。

参数 lpNamedPipeName 用来指定命名管道的名称,

这个名称必须包括创建该命名管道的服务器进程所在的机器的名称,

格式为:\\.\pipe\pipeName ,如果是在同一个机器上编写的命名管道的服务器端程序和客户端程序,

则当指定这个名称时,在开始的两个反斜杠后可以设置一个圆点来表示服务器进程在本地机器上运行,

如果是跨网络通信,则在这个圆点位置处应该设置为服务器端所在的主机的名称。

参数 nTimeOut 用来指定超时间隔。

值

解释

NMPWAIT_USE_DEFAULT_WAIT

超时间隔即为服务器端创建该命名管道时指定的超时间隔。

NMPWAIT_WAIT_FOREVER

一直等待,直到出现一个可用的命名管道的实例。

           

               

示例:命名管道实现进程间通信

服务端实现:(简单 Console 程序)

项目结构:

image

NamedPipeServer.h

#ifndef NAMED_PIPE_SERVER_H
#define NAMED_PIPE_SERVER_H
 
#include <Windows.h>
#include <iostream>
 
using namespace std;
 
//服务端用来保存创建的命名管道句柄
HANDLE            hNamedPipe;
 
const char *    pStr        = "Zachary";
const char *    pPipeName    = "\\\\.\\pipe\\ZacharyPipe";
 
//创建命名管道
void CreateNamedPipeInServer();
 
//从命名管道中读取数据
void NamedPipeReadInServer();
 
//往命名管道中写入数据
void NamedPipeWriteInServer();
 
#endif
         
NamedPipeServer.cpp
#include "NamedPipeServer.h"
 
int main(int argc, char * argv)
{
    CreateNamedPipeInServer();
 
    //在服务端往管道中写入数据
    NamedPipeWriteInServer();
 
    //接收客户端发来的数据
    NamedPipeReadInServer();
 
    system("pause");
}
 
 
void CreateNamedPipeInServer()
{
    HANDLE                    hEvent;
    OVERLAPPED                ovlpd;
 
    //首先需要创建命名管道
    //这里创建的是双向模式且使用重叠模式的命名管道
    hNamedPipe = CreateNamedPipe(pPipeName, 
        PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, 
        0, 1, 1024, 1024, 0, NULL);
 
    if(INVALID_HANDLE_VALUE == hNamedPipe)
    {
        hNamedPipe = NULL;
        cout<<"创建命名管道失败 ..."<<endl<<endl;
        return;
    }
 
    //添加事件以等待客户端连接命名管道
    //该事件为手动重置事件,且初始化状态为无信号状态
    hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if(!hEvent)
    {
        cout<<"创建事件失败 ..."<<endl<<endl;
        return;
    }
 
    memset(&ovlpd, 0, sizeof(OVERLAPPED));
 
    //将手动重置事件传递给 ovlap 参数
    ovlpd.hEvent = hEvent;
 
    //等待客户端连接
    if(!ConnectNamedPipe(hNamedPipe, &ovlpd))
    {
        if(ERROR_IO_PENDING != GetLastError())
        {
            CloseHandle(hNamedPipe);
            CloseHandle(hEvent);
 
            cout<<"等待客户端连接失败 ..."<<endl<<endl;
            return;
        }
    }
 
    //等待事件 hEvent 失败
    if(WAIT_FAILED == WaitForSingleObject(hEvent, INFINITE))
    {
        CloseHandle(hNamedPipe);
        CloseHandle(hEvent);
 
        cout<<"等待对象失败 ..."<<endl<<endl;
        return;
    }
 
    CloseHandle(hEvent);
}
 
 
void NamedPipeReadInServer()
{
    char *            pReadBuf;
    DWORD            dwRead;
 
    pReadBuf = new char[strlen(pStr) + 1];
    memset(pReadBuf, 0, strlen(pStr) + 1);
 
    //从命名管道中读取数据
    if(!ReadFile(hNamedPipe, pReadBuf, strlen(pStr), &dwRead, NULL))
    {
        delete []pReadBuf;
 
        cout<<"读取数据失败 ..."<<endl<<endl;
        return;
    }
    cout<<"读取数据成功:    "<<pReadBuf<<endl<<endl;
}
 
 
void NamedPipeWriteInServer()
{
    DWORD            dwWrite;
 
    //向命名管道中写入数据
    if(!WriteFile(hNamedPipe, pStr, strlen(pStr), &dwWrite, NULL))
    {
        cout<<"写入数据失败 ..."<<endl<<endl;
        return;
    }
    cout<<"写入数据成功:    "<<pStr<<endl<<endl;
}

客户端实现:(简单 Console 程序)

项目结构:

image

NamedPipeClient.h

#ifndef NAMED_PIPE_CLIENT_H
#define NAMED_PIPE_CLIENT_H
 
#include <Windows.h>
#include <iostream>
 
using namespace std;
 
//用来保存在客户端通过 CreateFile 打开的命名管道句柄
HANDLE            hNamedPipe;
 
const char * pStr        = "Zachary";
const char * pPipeName    = "\\\\.\\pipe\\ZacharyPipe";
 
//打开命名管道
void OpenNamedPipeInClient();
 
//客户端从命名管道中读取数据
void NamedPipeReadInClient();
 
//客户端往命名管道中写入数据
void NamedPipeWriteInClient();
 
#endif
              

NamedPipeClient.cpp

#include "NamedPipeClient.h"
 
int main(int argc, char * argv)
{
    OpenNamedPipeInClient();
 
    //接收服务端发来的数据
    NamedPipeReadInClient();
 
    //往命名管道中写入数据
    NamedPipeWriteInClient();
 
    system("pause");
}
 
 
void OpenNamedPipeInClient()
{
    //等待连接命名管道
    if(!WaitNamedPipe(pPipeName, NMPWAIT_WAIT_FOREVER))
    {
        cout<<"命名管道实例不存在 ..."<<endl<<endl;
        return;
    }
 
    //打开命名管道
    hNamedPipe = CreateFile(pPipeName, GENERIC_READ | GENERIC_WRITE, 
        0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if(INVALID_HANDLE_VALUE == hNamedPipe)
    {
        cout<<"打开命名管道失败 ..."<<endl<<endl;
        return;
    }
}
 
 
void NamedPipeReadInClient()
{
    char *                pReadBuf;
    DWORD                dwRead;
 
    pReadBuf = new char[strlen(pStr) + 1];
    memset(pReadBuf, 0, strlen(pStr) + 1);
 
    //从命名管道中读取数据
    if(!ReadFile(hNamedPipe, pReadBuf, strlen(pStr), &dwRead, NULL))
    {
        delete []pReadBuf;
 
        cout<<"读取数据失败 ..."<<endl<<endl;
        return;
    }
    cout<<"读取数据成功:    "<<pReadBuf<<endl<<endl;
}
 
 
void NamedPipeWriteInClient()
{
    DWORD                dwWrite;
 
    //向命名管道中写入数据
    if(!WriteFile(hNamedPipe, pStr, strlen(pStr), &dwWrite, NULL))
    {
        cout<<"写入数据失败 ..."<<endl<<endl;
        return;
    }
    cout<<"写入数据成功:    "<<pStr<<endl<<endl;
}

效果展示:

首先启动服务端进程(可以看到服务端进程正在等待客户端进程来连接命名管道):

image

然后启动客户端进程,可以看到客户端进程已经读取到了来自服务端进程发送到命名管道中的数据,

同时客户端进程也成功将数据写入到了命名管道中,从而这些数据可以被服务端进程获取到:

image

此时再来看服务端进程,可以发现服务端进程已经结束了等待,也就是已经成功和客户端进程建立了连接,

同时,服务端进程也成功将数据写入到了命名管道中,并且也成功获取到了客户端写入到命名管道中的数据。

image

                          

             

结束语

对于命名管道来说的话,简单理解的话,其实是可以将其看做是一种 Socket 的,

而对于命名管道也就是那几个 API 在使用,对于一些不常用的 API ,

感兴趣的也可以从 MSDN 中获取到这部分信息。

对于进程间的通信的话,其实也就可以利用介绍的这四种方式来实现了,

第一种是利用剪贴板实现本机进程间的通信。

第二种是利用邮槽实现本机或跨网络进程间的通信。

第三种是利用匿名管道实现本机父子进程之间的通信。

第四种是利用命名管道实现本机或跨网络进程间的通信。

然后的话,我还打算介绍一种比较偏门的实现进程间通信的手段,

当然,这要到下一篇博文中才会作出介绍。

最后的话,就是在前面的一篇博文中有一位朋友说可以利用 WCF 来实现进程之间的通信,

这个呢理论上是可以实现的,但是本人也没有做过这方面的 Demo ,

所以估计得看以后有时间的话,也可以拿过来写写文章的。

一个命名管道通信示例,包含客户端和服务器端 命名管道可以用于本机的进程间或网络上不同机器进程间通信。这是一个运用命名管道进行通信的例子。包含客户端和服务器端。 立即下载

相关推荐

医学图像处理入门:如何用Python将CT灰度图转换为伪彩色图像(附代码)

本文详细介绍了如何使用Python将CT灰度图转换为伪彩色图像,提升医学图像的可读性和诊断效率。通过OpenCV和Matplotlib等工具,实现灰度值到彩色空间的映射,特别适用于突出显示特定组织密度差异。文章包含完整代码示例和临床实用技巧,适合医学影像分析初学者和Python开发者。

gitlab7runner的博客 326

使用命名管道的OVERLAPPED方式实现非阻塞模式编程

命令管道是进程间通讯的一种常用方式,对于命令管道的介绍可以参考别的资料和书籍,这里推荐一个《VC++下命名管道编程的原理及实现》这篇博文,写得比较清楚。但是都是介绍了阻塞模式的编程,我这里主要是介绍利用命令管道OVERLAPPED方式使用非阻塞模式编程。注:文中使用的方法就是函数的意思。 参考MSDN,服务器端创建命令管道(使用CreateNamedPipe方法),不使用FILE_FLAG_OV

jiangdf的专栏 1万+

从OpenClaw到Hermes Agent:AI Agent实战部署与自动化工作流构建

AI Agent(智能体)作为大语言模型(LLM)的能力延伸,其核心原理在于通过工具调用(Tool Calling)与环境交互,使模型从“对话”走向“执行”。这一技术价值在于将自然语言指令转化为具体操作,实现业务流程自动化,从而提升开发与运维效率。在应用场景上,AI Agent广泛适用于自动化运维、智能客服、数据报告生成等重复性任务处理。本文聚焦于两大热门开源框架OpenClaw与Hermes Agent,深入探讨其部署配置、技能扩展及实战联调。通过结合OpenClaw的模块化扩展能力与Hermes Age

weixin_34122810的博客 503

管道

举个例子,就是两个进程共享信号量sv,一旦其中一个进程执行了P(sv)操作,它将得到信号量,并可以进入临界区,使sv减1。而第二个进程将被阻止进入临界区,因为当它试图执行P(sv)时,sv为0,它会被挂起以等待第一个进程离开临界区域并执行V(sv)释放信号量,这时第二个进程就可以恢复执行。 我们知道管道包括三种: 1):普通管道PIPE,通常有很多限制,一是半双工,

lusic01的专栏 539

使用循环神经网络预测温度

简介 本文以天气时间序列数据集为例,讨论如何使用深度学习模型预测未来天气温度。 使用的是由德国耶拿马克思普朗克生物地球化学研究所的气象站记录。 数据每10分钟记录一次,共记录14种不同的量,如气温、气压、湿度、风向等,原始数据可追溯到2003年,本例只使用2009-2016年的数据。 数据 下载并解压数据略。 加载数据: data_dir = r'E:\practice\tf2\temperature' fname = os.path.join(data_dir, 'jena_climate_2009_

guotianqing的博客 5282

LightGBM参数调优实战:从基础到高级技巧

本文深入探讨了LightGBM参数调优的实战技巧。文章从理解其Leaf-wise生长策略的核心逻辑出发,系统性地介绍了分层调参策略:首先调整控制模型结构的参数(如num_leaves),其次优化学习能力参数(如learning_rate),最后通过正则化与随机化参数提升泛化能力。文中还提供了从建立基线到最终微调的完整实战流程与高级避坑指南,帮助读者高效提升模型性能。

i8j9k0l1的博客 262

进程间通信 - 命名管道实现

引子 好,到这里呢,就需要介绍实现进程间通信的第四种方式了, 也就是通过命名管道来实现,前面介绍的那三种方式呢,都是有缺陷或者说局限性太强, 而这里介绍的命名管道相对来说,在这方面就做得好很多了, 比如,剪贴板的话只能实现本机上进程之间的通信, 而邮槽的话虽然是可以实现跨网络之间的进程的通信, 但麻烦的是邮槽的服务端只能接收数据,邮槽的客户端只能发送数据,太悲剧了, 而对于匿名管道的...

weixin_33966095的博客 575

光模块数字诊断监控(DDM)功能

DDM(Digital Diagnostic Monitoring)数字诊断监控,由行业组织SFF Committee制定,遵循SFF-8472多源协议定义的标准参数而工作,规范了光模块和网络设备的软硬件所需遵循的标准数值或范围,确保了网络设备供应商和光模块供应商之间所提供产品的互操作性不同。:通过监测激光器的偏置电流来预测激光器的劣化,从而确保在故障发生之前将业务切换到备用链路上或替换有可能故障的光模块,因此起到了预测光模块寿命的作用。光模块DDM信息可以通过SNMP读取光模块的接收光功率和发射光功率。.

光模块的博客 2300

c++程序与c#程序通过命名管道通信

最近做的项目需要在两个程序间进行通信,server端是c++(qt)写的程序,client是c#写的程序。之前使用QProcess通信已经测试通过了,不过是server和client都是用qt做的模拟,实际在c#中没办法接收到消息,现在重新用管道通信来实现。server:#include "mainwindow.h" #include "ui_mainwindow.h" HANDLE MainW...

壁立千仞无欲则刚的博客 3496

从零到一:QT for OpenHarmony 开发环境实战搭建与踩坑指南

本文是一份详尽的QT for OpenHarmony开发环境搭建实战指南。文章手把手教你如何在Windows和macOS系统上,从环境准备、核心工具(DevEco Studio与社区版QT SDK)安装配置,到创建首个QT Quick项目、解决构建部署中的常见问题,最终实现应用在OpenHarmony设备上运行。内容涵盖关键配置修改、资源管理及深度踩坑经验,旨在帮助开发者高效开启跨平台开发之旅。

weixin_29190573的博客 325

模组 RG500Q入网问题分析

- [ ] 不同于公网,在5G专网环境中, 通常使用很多非标准的网络配置,如PLMN/APN等。因此,5G模组在专网环境下通常要做一些专门的配置才能正常入网,本文分析一例在专网环境, 5G终端无法入网问题的定位过程。 - [ ] 具体涉及到以下模组操作: 恢复出厂、SA only、锁BAND、配置MBN等

十年通信老兵的技术修炼之路——从3G到5G,从地面基站到卫星通信。 935

进程间通信-windows命名管道详解以及完整代码实现

命名管道具有简单易用、跨平台兼容性、双向通信、安全性和可靠性等优点。然而,它也受到单机通信限制、性能瓶颈、同步问题、复杂性增加和依赖性等缺点的制约。命名管道通常只适用于同一台计算机上的进程间通信。虽然有些操作系统(如Windows)可能支持跨网络的命名管道通信,但这种方式通常不如套接字(Sockets)等网络通信机制灵活和高效。因此,在选择IPC机制时,应根据实际需求考虑数据传输的速度、大小、方向以及进程间的亲缘关系等因素。

红军不怕远征难,万水千山只等闲 2972

18、探索隐私工程技术的前沿:从理论到实践

本文深入探讨了隐私工程技术的核心概念、关键技术及其应用场景,分析了加密技术、访问控制和用户界面设计等在隐私保护中的作用,并结合数据库保护、物联网设备等实际场景进行阐述。同时,文章还讨论了隐私工程技术面临的挑战与未来发展趋势,提出了数据最小化原则、差分隐私、隐私增强技术等优化策略以及隐私设计、隐私影响评估等最佳实践,最后展望了新兴技术对隐私保护的影响及法规推动下的发展方向。

weixin_35307279的博客 373

【从浅学到熟知Linux】进程间通信之命名管道(含mkfifo命令及函数调用示例、读写阻塞及ONOBLOCK详解、匿名与命名管道区别、命名管道实现Client&Server)

🏠关于专栏:Linux的浅学到熟知专栏用于记录Linux系统编程、网络编程等内容。🎯每天努力一点点,技术变化看得见。

Jammingpro 1231

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

【Linux实践系列】:进程间通信:万字详解命名管道实现通信

万字详解命名管道,从多个维度带你认识命名管道,想学会命名管道,看这篇文章就够了!

努力努力再努力wz的博客 4557

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

博文进程间通信详解 - 命名管道实现(转)中 NamedPipeServer.cpp文件总结

对http://blog.youkuaiyun.com/daofengdeba/article/details/7782381中的NamedPipeServer.cpp终于看懂了,留了注释以做笔记 NamedPipeServer.cpp #include "NamedPipeServer.h" int main(int argc, char * argv) {    CreateNamedPipeI

daofengdeba 4616

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

进程间通信【Linux】

匿名管道在系统中没有实名,它只是进程的一种资源,会随着进程的结束而被系统清除。它的通信范围是存在父子关系的进程。因为管道没有实体,也就是没有管道文件,只能通过 fork 来复制父进程fd文件描述符,来达到通信的目的。所以,刚才说的父子进程看到的同一份资源,就是管道本身。虽然共享内存是最快的进程间通信的方式,但是它也是有缺点的。临界资源:多个进程(执行流)看到的公共资源就是临界资源;临界区:进程中访问临界资源的代码段。

Man9o 1832

【Linux】零基础学习命名管道-共享内存

命名管道和共享内存是两种进程间通信方式。命名管道通过文件系统中的管道文件实现无关进程通信,数据存储在内存缓冲区而非磁盘。共享内存直接在物理内存开辟区域供多进程访问,具有最高通信效率但需自行处理同步问题。文中演示了命令行创建管道、mkfifo函数实现通信,以及共享内存的创建、关联和控制方法,并指出共享内存生命周期随内核持续,需要手动释放。两种方式各有特点:命名管道适合简单通信,共享内存适合高性能场景但需额外同步机制。

2403_87165176的博客 1647

【Linux系统编程】深入理解命名管道(Named Pipe):从原理到实战的完整指南

本文深入解析Linux命名管道(Named Pipe/FIFO)机制,从底层原理到实战应用全面覆盖。内容包括:命名管道的创建与使用、与匿名管道的核心区别、跨进程通信的实现原理,以及基于mkfifo/open/read/write API的完整文件拷贝和双进程通信实例。通过图解+源码的方式,帮助读者掌握这一重要的进程间通信技术,为后续学习Socket、共享内存等高级IPC机制打下坚实基础。

Miun123的博客 4360

Linux(十三) 进程通信完全指南:匿名管道、进程池与命名管道

本文深入解析了Linux管道机制,从内核实现到应用实践。管道作为最基础的进程间通信(IPC)方式,完全复用VFS文件系统接口,体现了Linux"一切皆文件"的设计思想。文章首先概述了IPC的本质和分类,重点分析了匿名管道和命名管道的特性与使用场景。通过代码示例详细演示了父子进程通过管道通信的标准流程,包括文件描述符的关闭顺序、数据流向控制等关键细节。特别剖析了管道的核心特性:半双工单向性、字节流无边界、四种读写行为以及写入原子性(PIPE_BUF)问题。最后指出SIGPIPE信号是管道和网络编程中的常见陷阱

A_humble_scholar的博客 464

Linux下 进程间通信详解(一)管道、进程池详解

本次学习围绕 Linux 进程间通信展开,先是系统介绍进程间通信相关基础知识,接着掌握匿名管道与命名管道的原理及实操方法,最后学习编写进程池,同时可借助命名管道完成简易 Linux 进程间聊天室的开发,依托命名管道能突破匿名管道仅亲缘进程通信的限制,实现无关进程间的数据收发,搭建起多进程聊天交互程序。

Fcy648的博客 322

进程间通信管道信号量与共享内存

管道是Unix/Linux中最古老的IPC形式,分为匿名管道和命名管道。匿名管道仅用于父子进程通信,通过`pipe()`系统调用创建,数据以字节流形式单向传输。但管道容量有限(通常4KB),且不支持多向通信,适合简单的线性数据传递。共享内存直接将同一物理内存映射到多个进程的虚拟地址空间,省去了数据复制的开销,速度最快。管道、信号量与共享内存作为经典机制,分别以不同的方式解决数据传递、同步与高效共享的难题。各自适用于哪些场景?实际开发中,可组合使用:用共享内存传输数据,信号量保障安全,管道通知事件。

swqwch_346的博客 37

初步了解Linux中的命名管道及简单应用和简单日志

命名管道和匿名管道的原理是类似的,他们都是在内核里面有一块不同进程之间可以看到的公共“资源”。而我们所说的命名管道就是这个资源,命名管道是对于不具有血缘关系的进程之间进行进程间通信的一种方式,既然不具有血缘关系,那么就说明了我们不会像父子进程一样,自动的拥有一块相同的资源,我们需要自己创建我们的资源。这个“资源”本质上就是以文件,叫做通道文件,在Linux中一切皆文件,他拥有文件的特性,知道这一点,,一个进程以写方式打开,另一个进程以读方式打开,这样我们就拥有了所谓的同一份“资源”.

wiketsy的博客 943
上一篇: 进程间通信详解 - 匿名管道实现
下一篇: 进程间通信详解 - 邮槽实现
雪岢奇
博客等级 码龄17年 310粉丝 60原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值