如何:使用命名管道进行网络进程的管道通信间通信

命名管道编程的原理及实现(4)-windows下进程间通信
2. 匿名管道(Pipe)
现在大多数都是基于管道通信的,因为每两个进程都可以共享一个管道来进行单独的对话,就象打电话单独占用一条线路一样,而不必担心像剪贴板一样会有串音,
匿名管道是一种只能在本地机器上实现两个进程间通信的管道,它只能用来实现一个父进程和一个子进程之间实现数据传输.其实它是非常有用的,我做过一个实际
的项目就是利用匿名管道,项目就是让我写一个Ping程序来监测网络的通信状况,并且要把统计结果和执行过程显示在我们的软件里,
windows有一个自带的ping程序,而且有执行过程和统计,所以我没必要再发明一个(重复发明就等于犯罪----程序员要牢记阿),
只是windows的那个Ping程序的执行结果都显示在了CMD的界面上了,我需要把它提取出来显示在我们的软件界面上,于是我就利用了匿名管道实现了
这个程序,
当我们的软件要启动Ping任务时,我就先CreatePipe创建匿名管道,再CreateProcess启动了windows下面的Ping程序(它
作为我们软件的子进程),当然要把管道的读写句柄一起传给子进程,这样我就可以轻松的把Ping的执行结果了写入到我的Buffer里了,是不是很
CreatePipe(PHANDLE hReadPipe, PHANDLE hWritePipe,
LPSECURITY_ATTRIBUTES lpPipeAttributes, DWORD nSize)
这个API函数是有用来创建匿名管道的,它返回管道的读写句柄(hReadPipe,hWritePipe),
记住lpPipeAttributes不能为NULL,因为这意味着函数的返回句柄不能被子进程所继承,你要知道匿名管道可是实现父子进程通信的阿,只有
当一个子进程从其父进程中继承了匿名管道句柄后,这两个进程才可以通信,lpPipeAttributes不为NULL还远不够,
LPSECURITY_ATTRIBUTES这个结构体的内容去查MSDN吧,我只告诉你其中的BOOL
bInheritHandle这个成员变量要赋值为TRUE,
这样才真正实现了子进程可以从父进程中继承匿名管道.
CreateProcess(...)&&&
这个系统API函数是用来在你的进程中启动一个子进程用的,它的参数实在太多了,你还是去查MSDN吧,别怪我太懒惰,我只说几个关键的地方,不想说的太详细.
下面我就在写一个程序利用匿名管道来通信
父进程的实现:
&&& HANDLE
&&& HANDLE
CParent::onCreatePipe()
SECURITY_ATTRIBUTES&& //
父进程传递给子进程的一些信息
sa.bInheritHandle = TRUE; //
还记得我上面的提醒吧,这个来允许子进程继承父进程的管道句柄
sa.lpSecurityDescriptor = NULL
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
(!CreatePipe(&m_hRead, &m_hWrite, &sa, 0)
&&& STARTUPINFO
PROCESS_INFOMATION& //
保存了所创建子进程的信息
ZeroMemory(&sui, sizeof(STARTUPINFO)); //
对一个内存区清零,最好用ZeroMemory, 它的速度要快于memset
&&& sui.cb =
sizeof(STARTUPINFO);
&&& sui.dwFlags
= STARTF_USESTDHANDLES;
sui.hStdInput = m_hR
sui.hstdOutput = m_hW
以上两行也许大家要有些疑问,为什么把管道读句柄(m_hRead)赋值给了hStdInput,
因为管道是双向的,对于父进程写的一端正好是子进程读的一端,而m_hRead就是父进程中对管道读的一端,
自然要把这个句柄给子进程让它来写数据了(sui是父进程传给子进程的数据结构,里面包含了一些父进程要告诉子进程的一些信息),反之一样×/
&&&&&&&&&&&&&&&
sui.hStdError = GetStdHandle(STD_ERROR_HANDLE);
(!CreateProcess("Child.exe", NULL, NULL, NULL, TRUE, 0, NULL, NULL,
&sui, &pi))
CloseHandle(m_hRead);
CLoseHandle(m_hWrite);
CloseHandle(pi.hProcess); // 子进程的进程句柄
Closehandle(pi.hThread);& //
子进程的线程句柄,windows中进程就是一个线程的容器,每个进程至少有一个线程在执行
void CPraent::OnPiepRead()
(!ReadFile(hRead, buf, 100, &dwRead, NULL))//
从管道中读取数据
Messagebox(buf)
CParent::onPipeWrite(char *pBuf)
&&& ASSERT(pBuf
!= NULL); // 这个很重要
(!WriteFile(hWrite, pBuf, strlen(pBuf) + 1, &dwWrite, NULL))//
向管道中写数据
子进程的实现:
&&& ......
&&& HANDLE
&&& HANDLE
&&& void CChild
:: CChild()
&&& m_hRead =
GetStdHandle(STD_INPUT_HANDLE);
&&& m_hWrite =
GetStdhandle(STD_OUTPUT_HANDLE);
GetStdhandle获得标准输入输出句柄,如果你希望你的程序也能跟其他父进程通信的话最好也这么作,并不是所有的程序被创建了后都能跟父进程通信
我用过很多老外写的小程序,它们都提供了标准的对外通信接口,这样很便于你的使用特别对程序员×/
void CChild::OnReadPipe()
CChild::OnWritePipe()
匿名管道由于是匿名的方式所以它不能实现两个同级的进程进行通信,因为一个进程创建了一个管道后,另一个线程并不知道如何找到这个管道,所以它只能通过父
进程直接把管道读写柄直接传递给子进程的方式进行进程通信,至于为什么有了命名管道还要保留匿名管道的问题,
我想主要是因为父子进程通信的方式已然被广泛的采用,而这种方式无疑要比命名管道消耗的资源更少,效率更高,就像自己自己写的进程调用了自己写的一个函数
3. 命名管道(Pipe)
命名管道不仅可以在本机上实现两个进程间的通信,还可以跨网络实现两个进程间的通信,就像我现在正使用MSN跟我远方的同学聊天一样!其实如果你用过
Socket编写网络程序的话,你就会明白所谓的命名管道之间的通信就相当于把计算机低层网络网络通信部分给封装了起来,使用户使用起来不必了解那么多网
络通信的知识,总之一句话就是用起来简单,其实我们在为别人提供函数库的时候都应该遵循这个规律,把低层烦琐,复杂,抽象的都封装起来,对高层提供统一的
在Windows2000/NT以后,都可以在创建管道时指定据有访问权限的用户使用管道,进一步保证了安全性,而如果你要是自己使用Socket实现这
个功能的话就太麻烦了,当然很多程序员已然会自己实现它,他们的理由很可能是因为windows都不安全.命名管道实现进程间的通信也跟网络通信一样是
C/S结构的,服务器进程负责创建命名管道及接受客户机的连接请求,就象socket中Server部分要实现bind、linstening和
accept一样, 而客户端只负责连接,对应于socket中的connect一样.
命名管道提供了两种基本通信模式:字节模式和消息模式,在字节模式下,数据以一个连续的字节流的形式在server于client之间流动,而消息模式
下,客户机和服务器则通过一系列不连续的数据单位进行数据收发,每次管道上发出了一条消息后,它必须作为一条完整的消息读入,是不是很像TCP和UDP.
&&& HANDLE
CreateNamePipe(....)
创建命名管道的API,
我依然不想解释它的具体参数含义,我只解释它的第一个参数LPCTSTR
lpName,它的字符串格式是"\\\\.\\pipe\\pipename"
为 什么这么多\,
其实一共就4个,可你看到有8个是因为C/C++中字符串中如果包含一个'\'就必须"\\"才能表达它的意思,你还记得吗?它的实际格式是"\\.\
pipe\pipename",它的'.'表示的是本机地址,如果是要与远程服务器连接,就在这个'.'处指定服务器的名称,接下来的pipe是固定的不
要改,pipename就是你要命名的管道名字.
ConnectNamedPipe(HANDLE hNamePipe, LPOVERLAPPED lpOverlapped)
初看这个函数的名字你一定认为这个是客户端用来连接服务器管道的,事物的表面总是欺骗我们,恰恰相反它是服务器用来等待远程连接的,类似于socket中的listen.
WaitNamedPipe(LPCTSTR lpNamedPipeName, DWORD nTimeOut)
有了上面那个函数的教训,如果我问题这个函数是作什么的你一定不会立即回答,是的,它是在客户端来判断是否有可以利用的命名管道的,每个客户端最开始都应该使用它判断一些,就像socket中的connect要判断一下server是否已经启动了.
下面是服务器代码:
CNamePipeServer
&&& HANDLE
CNamePipeServer::NamePipeCreated()
&&& m_hPipe =
CreateNamedPipe("\\\\.\\pipe\\MyPipe", PIPE_ACCESS_DUPLEX |
FILE_FLAG_OVERLAPPED,
&&& 0, 1, 1024,
1024, 0, NULL);
(INVALID_HANDLE_VALUE == m_hPipe)
&&& HANDLE
&&& hEvent =
CreateEvent(NULL, TRUE, FALSE, NULL); // 创建一个事件
(INVALID_HANDLE_VALUE == hEvent)
&&& OVERLAPPED
ZeroMemory(&ovlap, sizeof(OVERLAPPED));
ovlap。hEvent = hE
(!ConnectNamePipe(hPipe, &ovlap))
(ERROR_IO_PENDING != GetLastError())
(WAIT_FAILED == WaitForSingleObject(hEvent, INFINTE))
CloseHandle(hEvent);
void CNamePipeServer::OnReadPipe()
CNamePipeServer::OnWritePipe()
命名管道读写的方式与匿名管道的相同, 不再冗述。
客户端实现:
CNamePipeClient
&&& HANDLE
CNamePipeClient::OnPipeConnect()
(!WaitNamedPipe("\\\\.\\pipe\\MyPipe", NMPWAIT_WAIT_FOREVER))
&&& m_hPipe =
CreateFile("\\\\.\\pipe\\MyPipe", GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
(INVALID_HANDLE_VALUE == m_hPipe)
CNamePipeClient::OnReadPipe()
CNamePipeClient::OnWritePipe()
命名管道我没有在实际中使用过,所以对它的一些特点理解的并不是很透彻,不能为大家提供更多的建议了.
4. 邮槽(Mailslot)
邮槽是基于广播通信设计出来的,采用不可靠的数据传输,它是一种单向通信机制,创建邮槽的服务器进程读取数据,打开邮槽的客户端进程写入数据,据说邮槽广泛的应用于网络会议系统.
服务器进程
MailslotRecv()
&&& HANDLE
&&& hMailslot =
Createmailslot("\\\\.\\mailsolt\\MyMailslot", 0,
MAILSLOT_WAIT_FOREVER, NULL);
(INVALID_HANDLE_VALUE
== hMailslot)
(!ReadFile(hMailslot, buf, 100, &dwRead, NULL))
MessageBox(buf);
CloseHandle(hMailslot);
客户端进程:
MailslotSnd(char *pBuf)
&&& ASERRT(pBuf
&&& HANDLE
&&& hMailslot =
CreateFile("\\\\.\\mailslot\\MyMailslot", ENERIC_READ |
GENERIC_WRITE, 0, NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
(INVALID_HANDLE_VALUE == hMailslot)
(!WriteFile(hMailslot, pBuf, strlen(pBuf) + 1, &dwWrite,
CloseHandle(hMailslot);
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。您的位置: &
一种网络进程间通信的方式——管道
优质期刊推荐您的访问出错了(404错误)
很抱歉,您要访问的页面不存在。
1、请检查您输入的地址是否正确。
进行查找。
3、感谢您使用本站,3秒后自动跳转至网站首页2015年9月 VC/MFC大版内专家分月排行榜第二2015年7月 硬件/嵌入开发大版内专家分月排行榜第二2014年5月 VC/MFC大版内专家分月排行榜第二2014年3月 VC/MFC大版内专家分月排行榜第二2013年10月 VB大版内专家分月排行榜第二2013年7月 VB大版内专家分月排行榜第二2012年5月 VB大版内专家分月排行榜第二2012年4月 VB大版内专家分月排行榜第二2012年2月 VB大版内专家分月排行榜第二2011年11月 VB大版内专家分月排行榜第二
2015年11月 VC/MFC大版内专家分月排行榜第三2015年6月 VC/MFC大版内专家分月排行榜第三2015年2月 VC/MFC大版内专家分月排行榜第三2014年1月 VC/MFC大版内专家分月排行榜第三2012年3月 VB大版内专家分月排行榜第三2011年12月 VB大版内专家分月排行榜第三2011年10月 VB大版内专家分月排行榜第三
2015年9月 VC/MFC大版内专家分月排行榜第二2015年7月 硬件/嵌入开发大版内专家分月排行榜第二2014年5月 VC/MFC大版内专家分月排行榜第二2014年3月 VC/MFC大版内专家分月排行榜第二2013年10月 VB大版内专家分月排行榜第二2013年7月 VB大版内专家分月排行榜第二2012年5月 VB大版内专家分月排行榜第二2012年4月 VB大版内专家分月排行榜第二2012年2月 VB大版内专家分月排行榜第二2011年11月 VB大版内专家分月排行榜第二
2015年11月 VC/MFC大版内专家分月排行榜第三2015年6月 VC/MFC大版内专家分月排行榜第三2015年2月 VC/MFC大版内专家分月排行榜第三2014年1月 VC/MFC大版内专家分月排行榜第三2012年3月 VB大版内专家分月排行榜第三2011年12月 VB大版内专家分月排行榜第三2011年10月 VB大版内专家分月排行榜第三
2016年2月 C/C++大版内专家分月排行榜第三2016年1月 C/C++大版内专家分月排行榜第三
本帖子已过去太久远了,不再提供回复功能。拒绝访问 | www. | 百度云加速
请打开cookies.
此网站 (www.) 的管理员禁止了您的访问。原因是您的访问包含了非浏览器特征(3b438e-ua98).
重新安装浏览器,或使用别的浏览器

我要回帖

更多关于 进程的管道通信实验 的文章

 

随机推荐