VC++下实现匿名管道

2016-02-19 12:58 90 1 收藏

在这个颜值当道,屌丝闪边的时代,拼不过颜值拼内涵,只有知识丰富才能提升一个人的内在气质和修养,所谓人丑就要多学习,今天图老师给大家分享VC++下实现匿名管道,希望可以对大家能有小小的帮助。

【 tulaoshi.com - 编程语言 】

概述

  管道(Pipe)实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机。一个进程在向管道写入数据后,另一进程就可以从管道的另一端将其读取出来。匿名管道(Anonymous Pipes)是在父进程和子进程间单向传输数据的一种未命名的管道,只能在本地计算机中使用,而不可用于网络间的通信。

  匿名管道实施细则

  匿名管道由CreatePipe()函数创建,该函数在创建匿名管道的同时返回两个句柄:管道读句柄和管道写句柄。CreatePipe()的函数原型为:  

  BOOL CreatePipe(PHANDLE hReadPipe, // 指向读句柄的指针

   PHANDLE hWritePipe, // 指向写句柄的指针

   LPSECURITY_ATTRIBUTES lpPipeAttributes, // 指向安全属性的指针

   DWORD nSize // 管道大小

  );

  通过hReadPipe和hWritePipe所指向的句柄可分别以只读、只写的方式去访问管道。在使用匿名管道通信时,服务器进程必须将其中的一个句柄传送给客户机进程。句柄的传递多通过继承来完成,服务器进程也允许这些句柄为子进程所继承。除此之外,进程也可以通过诸如DDE或共享内存等形式的进程间通信将句柄发送给与其不相关联的进程。

  在调用CreatePipe()函数时,如果管道服务器将lpPipeAttributes 指向的SECURITY_ATTRIBUTES数据结构的数据成员bInheritHandle设置为TRUE,那么CreatePipe()创建的管道读、写句柄将会被继承。管道服务器可调用DuplicateHandle()函数改变管道句柄的继承。管道服务器可以为一个可继承的管道句柄创建一个不可继承的副本或是为一个不可继承的管道句柄创建一个可继承的副本。CreateProcess()函数还可以使管道服务器有能力决定子进程对其可继承句柄是全部继承还是不继承。

  在生成子进程之前,父进程首先调用Win32 API SetStdHandle()使子进程、父进程可共用标准输入、标准输出和标准错误句柄。当父进程向子进程发送数据时,用SetStdHandle()将管道的读句柄赋予标准输入句柄;在从子进程接收数据时,则用SetStdHandle()将管道的写句柄赋予标准输出(或标准错误)句柄。然后,父进程可以调用进程创建函数CreateProcess()生成子进程。如果父进程要发送数据到子进程,父进程可调用WriteFile()将数据写入到管道(传递管道写句柄给函数),子进程则调用GetStdHandle()取得管道的读句柄,将该句柄传入ReadFile()后从管道读取数据。

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  如果是父进程从子进程读取数据,那么由子进程调用GetStdHandle()取得管道的写入句柄,并调用WriteFile()将数据写入到管道。然后,父进程调用ReadFile()从管道读取出数据(传递管道读句柄给函数)。

  在用WriteFile()函数向管道写入数据时,只有在向管道写完指定字节的数据后或是在有错误发生时函数才会返回。如管道缓冲已满而数据还没有写完,WriteFile()将要等到另一进程对管道中数据读取以释放出更多可用空间后才能够返回。管道服务器在调用CreatePipe()创建管道时以参数nSize对管道的缓冲大小作了设定。

  匿名管道并不支持异步读、写操作,这也就意味着不能在匿名管道中使用ReadFileEx()和WriteFileEx(),而且ReadFile()和WriteFile()中的lpOverLapped参数也将被忽略。匿名管道将在读、写句柄都被关闭后退出,也可以在进程中调用CloseHandle()函数来关闭此句柄。
  总的来说,匿名管道程序是比较简单的。在下面将要给出的程序示例中,将由父进程(管道服务器)创建一个子进程(管道客户机),子进程回见个其全部的标准输出发送到匿名管道中,父进程再从管道读取数据,一直到子进程关闭管道的写句柄。其中,匿名管道服务器程序的实现清单如下:  

  STARTUPINFO si;

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  PROCESS_INFORMATION pi;

  char ReadBuf[100];

  DWORD ReadNum;

  HANDLE hRead; // 管道读句柄

  HANDLE hWrite; // 管道写句柄

  BOOL bRet = CreatePipe(&hRead, &hWrite, NULL, 0); // 创建匿名管道

  if (bRet == TRUE)

   printf("成功创建匿名管道! ");

  else

   printf("创建匿名管道失败,错误代码:%d ", GetLastError());

   // 得到本进程的当前标准输出

   HANDLE hTemp = GetStdHandle(STD_OUTPUT_HANDLE);

   // 设置标准输出到匿名管道

   SetStdHandle(STD_OUTPUT_HANDLE, hWrite);

   GetStartupInfo(&si); // 获取本进程的STARTUPINFO结构信息

   bRet = CreateProcess(NULL, "Client.exe", NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi); // 创建子进程

   SetStdHandle(STD_OUTPUT_HANDLE, hTemp); // 恢复本进程的标准输出

   if (bRet == TRUE) // 输入信息

    printf("成功创建子进程! ");

   else

    printf("创建子进程失败,错误代码:%d ", GetLastError());

    CloseHandle(hWrite); // 关闭写句柄

    // 读管道直至管道关闭

    while (ReadFile(hRead, ReadBuf, 100, &ReadNum, NULL))

    {

     ReadBuf[ReadNum] = '

来源:http://www.tulaoshi.com/n/20160219/1602643.html

延伸阅读
一、函数调用捆绑   1、定义 捆绑:把函数体与函数调用相联系称为捆绑。当捆绑在程序运行之前(由编译器和连接器)完成时,称为早捆绑。(C编译只有一种函数调用,就是早捆绑)如果捆绑发生在运行时,则称为晚捆绑(或动态捆绑、运行时捆绑。 虚函数:如果我们在定义基类时在函数前加关键字virtual,则会告诉编译器对于此函数...
一、 引言 我们在上网浏览时,有时访问到某些网站的网页时会自动弹出一些广告窗口,甚至有不少个人主页为了利用网络广告来赚钱一下同时弹出几个甚至十几个广告窗口。这些窗口一个一个的关掉十分麻烦,而且如果不关的话又会占用大量的系统资源,所以不少人对此深恶痛绝,作为程序员可以利用自身技术优势根据自己的实际需要编制一些很适合...
工作中经常碰到一些程序,它们在系统启动的过程中,自动打开并运行,以便实现对系统的监控或者病毒的检测等特定的目的,典型的例子就是常用的一些杀毒软件如:KV300及瑞星杀毒软件等。笔者在此,以自己的编程实践为基础,说明这些程序自动启动的原理和方法,同时对一些典型程序代码进行分析,以便读者在今后的编程过程中使用。 一、 ...
[文章信息]作者:中国电波传播研究所青岛分所郎锐时间:2003-06-16出处:yesky责任编辑:方舟[文章导读]本文给出了一种在Visual C++下用原始套接字来捕捉并分析在网络上传输的数据包的简单方法 引言 从事网络安全的技术人员和相当一部分准黑客(指那些使用现成的黑客软件进行攻击而不是根据需要去自己编写代码的人)都一定不会对网络嗅探器(sn...
一、闲聊 今天要谈的话题是COM,稍微深入一点,不知道大家用过C++Test或者Visual Assistant之类的软件没有,它们都有个非常引人注目的功能,那就是把它们自身嵌入到VC开发环境中去。这个功能让我痴迷不已,原因只有一个:我想做一个可以嵌入VC开发环境的VC工程解析器,这样用户在VC开发环境中就可以直接对当前或所有工程进行各种分析,统...

经验教程

480

收藏

41
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部