管道实现进程间通讯 、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 ...
随机推荐
- 架构设计的UML图形思考
本篇紧接着上一篇 基本OOP知识 ,介绍高焕堂老师的第二讲. 架构设计的UML图形思考.本篇最重要的是三个词语:图形.思考.UML. 架构师的作用体现主要在项目开发前期.在整个项目还没有完毕的时 ...
- QSerialPort
(草稿) qt5提供QSerialPort类,封装了串口的api, 可以用这个类写串口通信程序.
- typedef 总结
其实在正儿八经学C语言的时候typedef用的不是很多,记得书上对它的介绍只是一笔带过.的确它的用法是很简单,但这不代表在使用的过程中不会出错,今天来个彻底的总结. 作用:用来建立新的数据类型名.(注 ...
- 自定义的Server
自定义的Server 我们在上面对ASP.NET Core默认提供的具有跨平台能力的KestrelServer进行了详细介绍(<聊聊ASP.NET Core默认提供的这个跨平台的服务器——Kes ...
- 分享非常有用的Java程序 (关键代码) (一)
原文:分享非常有用的Java程序 (关键代码) (一) 分享一些非常有用的Java程序 (关键代码) ,希望对你有所帮助. 1. 得到当前方法的名字 String methodName = Th ...
- Windows8下通过IPv4地址访问Tomcat
最近在做Android开发,手机客户端需要通过IPv4地址访问电脑启动的Web应用服务. 在Windows 7不需要做什么设置,localhost,127.0.0.1或者192.168.0.100都可 ...
- mysql tcp 4层负载
-bash-4.1# cat /etc/haproxy/haproxy.cfg global log 127.0.0.1 local3 maxconn 65535 chroot /usr/local/ ...
- Java 使用JDBC、DBCP、C3P0访问数据库
JDBC: Connection conn = null; Statement stmt = null; ResultSet rs = null; // 1.加载驱动 try { Class.forN ...
- UVa 二分图匹配 Biginners
UVa 1045 - The Great Wall Game 最小权匹配 题意:给你一个n*n的棋盘,上面有n个棋子,要求通过移动各个棋子使得棋子在同一行或者同一列或者对角线上,求最小移动次数. 思路 ...
- 查询SystemFeature的方法
查询SystemFeature的方法可以在adb shell下敲如下的命令: dumpsys package 然后搜feature关键字. 例如,我的平台的SystemFeature,如下所示: Fe ...