开发者社区> andyro1984> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

使用命名管道实现进程间通信

简介: 使用命名管道实现进程间通信 在Win32下提供的进程间通信方式有以下几种: Ø         剪贴板Clipboard:在16位时代常使用的方式,CWnd类中提供了支持。
+关注继续查看

使用命名管道实现进程间通信

Win32下提供的进程间通信方式有以下几种:

Ø         剪贴板Clipboard:在16位时代常使用的方式,CWnd类中提供了支持。

Ø          COM/DCOM:通过COM系统的代理存根方式进行进程间数据交换,但只能够表现在对接口函数的调用时传送数据,通过DCOM可以在不同主机间传送数据。 Dynamic Data Exchange (DDE):在16位时代常使用的方式。

Ø         File Mapping:文件映射,在32位系统中提供的新方法,可用来共享内存。

Ø         Mailslots:邮件槽,在32位系统中提供的新方法,可在不同主机间交换数据,分为服务器方和客户方,双方可以通过其进行数据交换,在Win9X下只支持邮件槽客户。

Ø         Pipes:管道,分为无名管道:在父子进程间交换数据;有名管道:可在不同主机间交换数据,分为服务器方和客户方,在Win9X下只支持有名管道客户。

Ø         RPC:远程过程调用,很少使用,原因有两个:复杂而且与UNIX系统的RCP并不完全兼容。但COM/DCOM的调用是建立在RPC的基础上的。

Ø         Windows Sockets:网络套接口,可在不同主机间交换数据,分为服务器方和客户方。

Ø         WM_COPYDATA:通过发送WM_COPYDATA消息并将数据放在参数中来传递数据给其他进程。

下面主要介绍一下命名管道的用法,命名管道是一个有名字,单向或双向的通信管道。管道的名称有两部分组成:计算机名和管道名,例如//[host_name]/pipe/[pipe_name]/(括号内为参数)。对于同一主机来讲允许有多个同一命名管道的实例并且可以由不同的进程打开,但是不同的管道都有属于自己的管道缓冲区而且有自己的通讯环境互不影响,并且命名管道可以支持多个客户端连接一个服务器端。命名管道客户端不但可以与本机上的服务器通讯也可以同其他主机上的服务器通讯。

命名管道的连接和通讯采用如下方式:

在服务器端第一次创建命名管道后等待连接,当客户端连接成功后服务器端的命名管道就用作通讯用途。如果需要再次等待连接,服务器端就需要再次打开命名管道(创建一个命名管道的实例)并等待连接。

对于客户端每次打开命名管道后建立与服务器间的连接,然后就可以利用命名管道进行通信,如果需要建立第二个连接则需要再次打开管道和再次建立连接。
创建命名管道时需要指定一个主机名和管道名,对于客户端来说可以是如下格式://[host_name]/pipe/[pipe_name]/也可以是//./pipe/pipe_name/其中.表示本机。而服务器端只能够在指定本机作为主机名,即只能使用下面的格式://./pipe_name/。此外需要记住,在同一主机上管道名称是唯一的,一个命名管道一旦被创建就不允许相同名称的管道再被创建。

服务器方通过:

HANDLE CreateNamedPipe(
  LPCTSTR lpName,                             // pipe name
  DWORD dwOpenMode,                           // pipe open mode
  DWORD dwPipeMode,                           // pipe-specific modes
  DWORD nMaxInstances,                        // maximum number of instances
  DWORD nOutBufferSize,                       // output buffer size
  DWORD nInBufferSize,                        // input buffer size
  DWORD nDefaultTimeOut,                      // time-out interval
  LPSECURITY_ATTRIBUTES lpSecurityAttributes  // SD
);

Ø         创建命名管道和打开已经存在的命名管道,其中lpName为管道名称,dwOpenMode为创建方式,可以是下面值的组合: PIPE_ACCESS_INBOUND:管道只能用作接收数据。 PIPE_ACCESS_OUTBOUND:管道只能用作发送数据。 PIPE_ACCESS_DUPLEX:管道既可以发送也可以接收数据。(上面这三个值只能够取其中一个)

Ø         FILE_FLAG_WRITE_THROUGH:管道用于同步发送和接收数据,只有在数据被发送到目标地址时发送函数才会返回,如果不设置这个参数那么在系统内部对于命名管道的处理上可能会因为减少网络附和而在数据积累到一定量时才发送,并且对于发送函数的调用会马上返回。

Ø         FILE_FLAG_OVERLAPPED:管道可以用于异步输入和输出,异步读写的有关方法和文件异步读写是相同的。

Ø         dwPipeMode指定管道类型,可以是下面值的组合:
PIPE_TYPE_BYTE
:数据在通过管道发送时作为字节流发送,不能与PIPE_READMODE_MESSAGE共用。
PIPE_TYPE_MESSAGE
:数据在通过管道发送时作为消息发送,不能与PIPE_READMODE_BYTE共用。
PIPE_READMODE_BYTE
:在接收数据时接收字节流。
PIPE_READMODE_MESSAGE
:在接收数据时接收消息。
PIPE_WAIT
:使用等待模式,在读,写和建立连接时都需要管道的另一方完成相应动作后才会返回。

Ø         PIPE_NOWAIT:使用非等待模式,在读,写和建立连接时不需要管道的另一方完成相应动作后就会立即返回。

Ø         nMaxInstances为管道的的最大数量,在第一次建立服务器方管道时这个参数表明该管道可以同时存在的数量。PIPE_UNLIMITED_INSTANCES表明不对数量进行限制。nOutBufferSizenInBufferSize表示缓冲区的大小。nDefaultTimeOut表示在等待连接时最长的等待时间(以毫秒为单位),如果在创建时设置为NMPWAIT_USE_DEFAULT_WAIT表明无限制的等待,而以后服务器方的其他管道实例也需要设置相同的值。lpSecurityAttributes为安全属性,一般设置为NULL。如果创建或打开失败则返回INVALID_HANDLE_VALUE。可以通过GetLastError得到错误。

客户方通过:

HANDLE CreateFile(
  LPCTSTR lpFileName,                         // file name
  DWORD dwDesiredAccess,                      // access mode
  DWORD dwShareMode,                          // share mode
  LPSECURITY_ATTRIBUTES lpSecurityAttributes, // SD
  DWORD dwCreationDisposition,                // how to create
  DWORD dwFlagsAndAttributes,                 // file attributes
  HANDLE hTemplateFile                        // handle to template file
);

Ø         创建客户端命名管道,CreateFile可以有很多用途,可以用来创建文件,管道,邮件槽,目录等,这里介绍用CreateFile来打开客户端命名管道。lpFileName用来指明管道名称。dwDesiredAccess用来表明使用方式,可以使用下面的值: GENERIC_READ:打开一个只用于读的管道。GENERIC_WRITE:打开一个只用于写的管道。GENERIC_READ | GENERIC_WRITE:打开一个用于读和写的管道。 dwShareMode指定共享方式,一般指定为0lpSecurityAttributes为安全属性,一般设置为NULLdwCreationDisposition设置为OPEN_EXISTINGdwFlagsAndAttributes设置为FILE_ATTRIBUTE_NORMAL,此外可以还设置为FILE_FLAG_OVERLAPPED来进行异步通讯,hTemplateFile设置为NULL。如果打开失败则返回INVALID_HANDLE_VALUE。可以通过GetLastError得到错误。

此外客户方可以利用:

BOOL CallNamedPipe(

  LPCTSTR lpNamedPipeName,  // pipe name

  LPVOID lpInBuffer,        // write buffer

  DWORD nInBufferSize,      // size of write buffer

  LPVOID lpOutBuffer,       // read buffer

  DWORD nOutBufferSize,     // size of read buffer

  LPDWORD lpBytesRead,      // number of bytes read

  DWORD nTimeOut            // time-out value

);

        来创建一个发送消息的管道。 管道的连接管理,客户方在调用CreateFile后立即就能够建立服务器的连接,而服务器方一旦管道打开或创建后可以用

BOOL ConnectNamedPipe(

  HANDLE hNamedPipe,          // handle to named pipe

  LPOVERLAPPED lpOverlapped   // overlapped structure

);

    来等待客户端的连接建立。如果希望在服务器方检测是否有连接到达,可以调用

 BOOL WaitNamedPipe(

  LPCTSTR lpNamedPipeName,  // pipe name

  DWORD nTimeOut            // time-out interval

);

 这里的lpNamePipeName直接使用创建管道时的名称,如果在服务器方希望关闭连接则调用
    BOOL DisconnectNamedPipe(
      HANDLE hNamedPipe   // handle to named pipe
    );

一旦连接被关闭,服务器方可以再次调用ConnectNamedPipe来建立连接。如果要关闭管道则直接调用CloseHandle。请注意这里提到的关闭管道和关闭连接是不同的意思,在同一个管道上可以依次反复建立连接,而且可以减小系统的负荷。而且如果指定了管道最大数量限制那么在打开的管道达到最大限制后如果不关闭旧管道就无法打开新管道。

对于客户方则无法关闭连接,而只能直接调用CloseHandle关闭管道。

数据的发送,不论是服务器还是客户方都可以通过ReadFileWriteFile进行管道读写来达到通讯的目的。

下面是一个例子,服务器方创建或打开一个管道并读入对方发送的数据,将小写字母转换成大写字母后返回,而客户发创建一个到服务器的连接并发送一个字符串并读回经过转换的数据:

在使用这个例子时,运行三个服务端进程,而运行第四个时会因为达到管道数量限制而打开管道失败。

//服务方

void CNamed_pipeDlg::OnCreateP()

{

DWORD dwTO = NMPWAIT_USE_DEFAULT_WAIT;//设置连接等待时间             

HANDLE hSvr=

         CreateNamedPipe("////.//pipe//test_pipe//",

                           PIPE_ACCESS_DUPLEX,

                           PIPE_TYPE_BYTE,3,256,256,dwTO,NULL);

    if( INVALID_HANDLE_VALUE == hSvr)

    {

        AfxMessageBox("Error create/open pipe");

    }

    else

    {

        if (ConnectNamedPipe(hSvr,NULL))

        {

            BYTE bRead;

            DWORD dwRead,dwWritten;

            while (ReadFile(hSvr,&bRead,1,&dwRead,NULL))

            {

                if(bRead >= 'a' && bRead $lt;='z')

                    bRead = 'A'+ (bRead-'a');

                WriteFile(hSvr,&bRead,1,&dwWritten,NULL);

            }

        }

        else

        {

            AfxMessageBox("error when waiting connected");

        }

        CloseHandle(hSvr);

    }

}

//客户端

void CNamed_pipe_cDlg::OnConn()

{

  HANDLE hClient = CreateFile("////.//pipe//test_pipe//",GENERIC_WRITE |GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

    if(hClient == INVALID_HANDLE_VALUE)

    {

        AfxMessageBox("Error open pipe");

    }

    else

    {

        DWORD dwRead,dwWritten;

        char szSend[10]="send...";

        char szRecv[10];

        for(int i=0;i<strlen(szSend)+1;i++)

        {

            WriteFile(hClient,szSend+i,1,&dwWritten,NULL);

            ReadFile(hClient,szRecv+i,1,&dwRead,NULL);

        }

        CloseHandle(hClient);//close pipe

        AfxMessageBox(szRecv);

    }

}

 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
进程间通信---匿名管道
进程间通信---匿名管道
36 0
进程间通信和线程间通信
进程间通信: # 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。# 命名管道 (named pipe/FIFO) : 命名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
1499 0
进程间通信
1.无名管道  int pipe(int pipefd[2]); 参数: @pipefd 获得操作管道的文件描述符  返回值: 成功返回0, 失败返回-1  特点: .
637 0
进程间通信
在用户应用程序在经常用到C库的进程间通信函数,实际上,这些进程间通信函数在内核中是通过系统调用好文件系统的机制实现的。 1 管道 管道是只用于连接读进程和写进程,以实现它们之间通信的共享文件。因而它又称共享文件。
834 0
Linux进程间通信——使用匿名管道
在前面,介绍了一种进程间的通信方式:使用信号,我们创建通知事件,并通过它引起响应,但传递的信息只是一个信号值。这里将介绍另一种进程间通信的方式——匿名管道,通过它进程间可以交换更多有用的数据。   一、什么是管道 如果你使用过Linux的命令,那么对于管道这个名词你一定不会感觉到陌生,因为我们通常通过符号“|"来使用管道,但是管理的真正定义是什么呢?管道是一个进程连接数据流到另一个进程的通道,它通常是用作把一个进程的输出通过管道连接到另一个进程的输入。
948 0
进程间通信之管道
      管道是linux的一种通信方式,一种两个进程间进行单向通信的机制,它提供了简单的流控制机制,系统提供了pipe生成一个管道并返回两个描述符,一 个用来读管道,一个用来写管道,因此它们可以共享访问文件,这样每个管道就可以有很多个读进程和写进程,然而实际上进程不知道它正在读或写的是一个管道...
875 0
进程及进程间通信
基础知识 1.进程:具有独立功能的程序在一个数据集合上一次动态的执行过程。通俗点讲就是“一个正在运行的程序” 2.程序:静态的程序以文件的形式保存在磁盘上。 3.操作系统的进程管理: 每一个正在运行的程序都对应着一个独立的进程,当这些程序装入内存开始执行时,操作系统会为每个进程创建好相关的数据结构。
1120 0
8、进程通信-匿名管道
匿名管道 一个单向,未命名的管道,通常用来在一个父进程和一个子进程间传输数据。只能实现本地机器上两个进程间的通信,而不能实现跨网络的通信。 BOOL CreatePipe(   PHANDLE hReadPipe,                       // read handle ...
745 0
+关注
andyro1984
本团队有11年以上的解决方案端到端开发经验,涉及的行业有云计算、应用软件(包括WEB)、嵌入式、分布式、大型服务程序(Windows/Linux)、操作系统等。
211
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载