管道实现进程间通讯 、WaitNamedPipe
一、管道实现进程间通讯
主要的理论知识
1.什么是管道以及分类
api,结果操作管道就和操作文件一样。即使你在不同的计算机之间用命名管道来通信,你也不必了解和自己去实现网络间通信的详细细节。
2.管道的使用
A.命名管道
命名管道是由server端的进程建立的,管道的命名必须遵循特定的命名方法,就是"//./pipe/管道名",当作为client的进程要使用时,使用"//计算机名//pipe/管道名"来打开使用,详细过程例如以下:
服务端通过函数CreateNamedPipe创建一个命名管道的实例并返回用于今后操作的句柄,或为已存在的管道创建新的实例。服务端侦听来自client的连接请求,该功能通过ConnectNamedPipe函数实现。
client通过函数WaitNamedPipe来等待管道的出现,假设在超时值变为零曾经,有一个管道能够使用,则WaitNamedPipe将返回
True,并通过调用CreateFile或CallNamedPipe来呼叫对服务端的连接。
此时服务端将接受client的连接请求,成功建立连接,服务端ConnectNamedPipe返回
True 建立连接之后,client与server端就可以通过ReadFile和WriteFile,利用得到的管道文件句柄,彼此间进行信息交换。当client与服务端的通信结束,client调用CloseFile,服务端接着调用DisconnectNamedPipe。最后调用函数CloseHandle来关闭该管道。
B.匿名管道
因为命名管道使用时作为client的程序必须知道管道的名称,所以很多其它的用在同一“作者”编写的server/工作站程序中,你不可能随便找出一个程序来要求它和你写的程序来通过命名管道通信。而匿名管道的使用则全然不同,它同意你和全然不相干的进程通信,条件是这个进程通过控制台“console”来输入输出,典型的样例是老的
Dos 应用程序,它们在执行时 Windows为它们开了个
Dos窗体,它们的输入输出就是 console方式的。另一些标准的 Win32程序也使用控制台输入输出,假设在
Win32编程中不想使用图形界面,你照样能够使用AllocConsole得到一个控制台,然后通过GetStdHandle得到输入或输出句柄,再通过WriteConsole或WriteFile把结果输出到控制台(一般是一个象
Dos窗体)的屏幕上。尽管这些程序看起来象 Dos程序,但它们是不折不扣的 Win32程序,假设你在纯
Dos下使用,就会显示“The program must run under Windows!”。
一个控制台有三个句柄:标准输入、标准输出和和标准错误句柄,标准输入、标准输出句柄是能够又一次定向的,你能够用匿名管道来取代它,这样一来,你能够在管道的还有一端用别的进程来接收或输入,而控制台一方并没有感到什么不同,就象
Dos下的 >或者 <能够又一次定向输出或输入一样。通常控制台程序的输入输出例如以下:
(控制台进程output)
write ----> 标准输出设备(通常是屏幕)
(控制台进程input)
read <---- 标准输入设备(通常是键盘)
write ----> 管道1 ----> read (父进程)
read <----> 管道2 <---- write (父进程)
使用匿名管道的过程例如以下:
hStdInput,第二个取代 hStdOutput、hStdError,即标准输入、输出、错误句柄
WriteFile写第一个管道来将输入写到子进程
管道使用的API函数集
|
|||||||
|
|||||||
|
|||||||
|
|||||||
|
|||||||
|
|||||||
|
|||||||
|
|||||||
|
|||||||
|
|||||||
|
二、
BOOL WaitNamedPipe( LPCTSTR lpNamedPipeName, DWORD nTimeOut );
lpNamedPipeName 要打开的管道名,格式\\servername\pipe\pipename,假设是本地管道则servername能够使用点“.”。
nTimeOut 等待命名管道的一个实例有效的超时时间,单位毫秒,也能够使用以下两个值中的一个:
NMPWAIT_USE_DEFAULT_WAIT 0x00000000,使用服务端CreateNamedPipe 创建管道时设置的超时时间。
NMPWAIT_WAIT_FOREVER 0xffffffff,一直等到一个命名管道的实例有效才返回。
返回值:
假设在超时时间前管道的一个实例有效,返回非0。
假设超时时间内没有一个有效的实例,返回0。
注意:
假设指定的命名管道没有实例存在,即没有服务端创建该命名管道(所以在确定server端创建了该命名管道时能够不调用此API),函数无视超时等待时间直接返回0。
假设函数运行成功返回TRUE,表示至少有一个命名管道的实例有效,接下来应该使用CreateFile函数打开命名管道的一个句柄,可是CreateFile可能会打开管道失败,由于该实例有可能被服务端关闭或被已经被其它client打开。
三、管道使用的伤痛所在
static inline BOOL
CTPipe_WriteNBytes(HANDLE hPipe, BYTE *buf, DWORD size, DWORD timeout, HANDLE stopEvent)
{
BOOL ret = FALSE;
BOOL writeRet;
OVERLAPPED ol;
BYTE *pos;
DWORD cbBytesWrite;
HANDLE hWriteEvent; memset( &ol, 0, sizeof(ol) );
ol.hEvent = hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if ( ol.hEvent == NULL )
{
return FALSE;
} pos = buf;
while ( size > 0 )
{
writeRet = WriteFile(hPipe,
pos,
size,
&cbBytesWrite,
&ol);
if ( writeRet )
{
pos += cbBytesWrite;
size -= cbBytesWrite;
ResetEvent(hWriteEvent);
}
else
{
if ( GetLastError() == ERROR_IO_PENDING )
{
DWORD waitRet;
HANDLE handles[2];
int numOfHandles = 1; handles[0] = hWriteEvent;
if ( stopEvent )
{
handles[1] = stopEvent;
numOfHandles++;
} waitRet = WaitForMultipleObjects(numOfHandles, handles, FALSE, timeout);
if ( waitRet == WAIT_OBJECT_0 )
{
writeRet = GetOverlappedResult(hPipe, &ol, &cbBytesWrite, TRUE );
if ( writeRet == FALSE )
{
goto EXIT;
}
pos += cbBytesWrite;
size -= cbBytesWrite;
ResetEvent(hWriteEvent);
}
else /* timeout, notify event or other */
{
/*
* Cancel request
*/
if ( CancelIo(hPipe) == FALSE )
{
L_ERROR(_T("IoCancel fail 0x%x, force close pipe\n"), GetLastError());
CloseHandle(hPipe);
}
else
{
/*
* Wait cannel finish
*/
GetOverlappedResult(hPipe, &ol, &cbBytesWrite, TRUE);
}
goto EXIT;
}
}
else
{
goto EXIT;
}
}
}
ret = TRUE; EXIT:
if ( hWriteEvent )
{
CloseHandle(hWriteEvent);
}
return ret;
}
在
waitRet = WaitForMultipleObjects(numOfHandles, handles, FALSE, timeout);
发生了堵塞,此管理是採用异步的,这里写的管道是作为服务端,问题是服务端的代码根本就没有变,倒是管道client的代码变了。
hPipe = CreateNamedPipe("Name",
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
0,
0,
0, /*XENHANCE_PIPE_TIMEOUT*/
&sa);
法一、在服务端的管道写时设置超时时间,这尽管能使用服务端管道的线程不卡死,但也可能该写的数据没有写进去。
1、
2、
3、
4、
5、
6、
7、
管道实现进程间通讯 、WaitNamedPipe的更多相关文章
- 【IPC进程间通讯之二】管道Pipe
IPC进程间通信+管道Pipe IPC(Inter-Process Communication.进程间通信). 管道用于进程间共享数据,事实上质是共享内存 ...
- [转]Windows 下的进程间通讯及数据共享
http://blog.codingnow.com/2005/10/interprocess_communications.html Windows 下有很多方法实现进程间通讯,比如用 socket, ...
- windows 进程间通讯方法
Windows平台为我们提供了多种进程间通信的机制,主要包括:注册表方式.共享文件方式.共享内存方式.共享数据段.映射文件方式.管道方式. 剪贴板方式.消息方式.其中注册表方式需要增加注册表表项,而注 ...
- C#进程间通讯技术-整理。
原文:C#进程间通讯技术-整理. 扩展阅读:http://www.cnblogs.com/joye-shen/archive/2012/06/16/2551864.html 一.进程间通讯的方式 1) ...
- C# 进程间通讯
扩展阅读:http://www.cnblogs.com/joye-shen/archive/2012/06/16/2551864.html 一.进程间通讯的方式 1)共享内存 包括:内存映射文件,共享 ...
- Python-互斥锁 进程间通讯
3.守护进程(**) 主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就终止 其二:守护进程内无法再开启子进程,否则抛出异常: AssertionError: daemonic proces ...
- Linux 进程间通讯
一.Linux 下进程间通讯方式 1)管道(Pipe)及有名管道(named pipe): 管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...
- 守护进程,进程安全,IPC进程间通讯,生产者消费者模型
1.守护进程(了解)2.进程安全(*****) 互斥锁 抢票案例3.IPC进程间通讯 manager queue(*****)4.生产者消费者模型 守护进程 指的也是一个进程,可以守护着另一个进程 一 ...
- 一篇文章了解相见恨晚的 Android Binder 进程间通讯机制【转】
本文转载自:https://blog.csdn.net/freekiteyu/article/details/70082302 Android-Binder进程间通讯机制 概述 最近在学习Binder ...
随机推荐
- SDCard助手类
package com.zyh.sdcardHelper; import java.io.BufferedInputStream; import java.io.BufferedOutputStrea ...
- android jsonarray
Json数组是子元素的有序集合,每个子元素都有一个下标,可以根据下标操纵Json数组的子元素.类JsonArray是bantouyan-json库对Json数组的抽象,提供操纵Json数组的各种方法. ...
- 08-IOSCore - App Store、国际化/本地化
App Store 1. 帐号身份 0. 有Xcode 写程序,在虚拟机上运行 1. 成为苹果使用者 appleid 验证邮箱 权限: 能下载应用程序 2. 成为苹果开发者 https://devel ...
- 新鲜出炉的Using Qt 3D to visualize music
http://blog.qt.io/blog/2016/01/27/using-qt-3d-visualize-music/
- docker学习笔记1:docke环境的查看
本文的操作是在ubuntu操作系统下的. 一.环境检查 当登录一个安装了docker的机器后,首先我们要检查下docker环境如何. 1.命令:docker -v 上述命令返回安装的docker的版本 ...
- Robot Framework与Web界面自动化测试学习笔记:如何判断单选框的选中状态
单选按钮是个常见的html元素,在网页中往往提供一组单选按钮来做选项. 这样在自动化测试用例中需要判断当前选中的按钮是否与预期的一直. 可以这样来操作: ${value} Get Element ...
- 基于visual Studio2013解决C语言竞赛题之0707月份输出
题目 解决代码及点评 /* 编一程序,打入月份号,输出该月的英文月名. 例如,输入"3",则输出"March",要求用指针数组处理. */ #includ ...
- OGR API Tutorial
This document is intended to document using the OGR C++ classes to read and write data from a file. ...
- Android 富文本框实现 RichEditText
Android系统自带控件没有富文本框控件,如果想写一封带格式的邮件基本上不可能,EdtiText只有默认一种格式,显示不能滿足要求,!!正好项目需要研究了一下,开发了此控件,现将一些源代码开放一下, ...
- linux: Ubuntu安装samba的问题
Ubuntu安装samba的问题 http://blog.csdn.net/jk110333/article/details/8920841 root@ubuntu:~# apt-get instal ...