管道实现进程间通讯 、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 ...
随机推荐
- Adobe Acrobat Ⅺ Pro安装激活
1.注意一定要断网安装,如果你有防火墙拦截亦可(注意:系统自带那防火墙不行). 2.将AcrobatPro_11_Web_WWMUI.exe解压到一个目录下,找到目录下的setup.exe安装,安装时 ...
- 快速傅里叶变换应用之二 hdu 4609 3-idiots
快速傅里叶变化有不同的应用场景,hdu4609就比较有意思.题目要求是给n个线段,随机从中选取三个,组成三角形的概率. 初始实在没发现这个怎么和FFT联系起来,后来看了下别人的题解才突然想起来:组合计 ...
- [ASP.NET]利用itextsharp将GridView汇出PDF档
原文 [ASP.NET]利用itextsharp将GridView汇出PDF档 最近在讨论区看到有人说itextsharp可以把网页变成PDF 小弟就去抓一下itextsharp来玩玩,先教大家最实用 ...
- 基于visual Studio2013解决C语言竞赛题之1008整除数
题目 解决代码及点评 /************************************************************************/ ...
- Codeforces Round #189 (Div. 2)
题目地址:http://codeforces.com/contest/320 第一题:基本题,判断mod 1000,mod 100.,mod 10是不是等于144.14.1,直到为0 代码如下: #i ...
- (step6.1.5)hdu 1233(还是畅通工程——最小生成树)
题目大意:输入一个整数n,表示有n个村庄,在接下来的n*(n-1)/2中,每行有3个整数beigin.end.weight,分别表示路的起始村庄,结束村庄和村庄之间的距离. 求索要修的路的最短距离 解 ...
- System.gc
Java中的内存分配是随着new一个新的对象来实现的,这个很简单,而且也还是有一些可以“改进”内存回收的机制的,其中最显眼的就是这个System.gc()函数. 乍一看这个函数似乎是可以进行垃圾回收的 ...
- encode_json 会对给定的Perl的数据结构转换为一个UTF-8 encoded, binary string.
use JSON qw/encode_json decode_json/ ; use Encode; my $data = [ { 'name' => 'Ken' , 'age' => 1 ...
- ASC(22)H(大数+推公式)
High Speed Trains Time Limit: 4000/2000MS (Java/Others)Memory Limit: 128000/64000KB (Java/Others) Su ...
- Silverlight技术调查(3)——国际化
原文 Silverlight技术调查(3)——国际化 网上有很多关于Silverlight国际化的说明,包括MSDN的示例,都没有强调一点,下面以红色标示,基础国际化知识请先参考MSDN相关章节,关键 ...