命名管道通过网络来完成进程间通信,它屏蔽了底层的网络协议细节。
采用命名管道完成进程通信的过程为:
1.在服务器端调用CreateNamedPipe创建命名管道之后,调用ConnectNamedPipe函数让服务器进程等待客户端进程连接到该命名管道的实例上。
2.在客户端,首先调用WaitNamedPipe函数判断当前是否有可以利用的命名管道实例,如果有就调用CreateFile函数打开该命名管道的实例,并建立一个连接。
之后就可以通过ReadFile、WriteFile进行通信。
服务端
void CNamedPipeSrcView::OnPipeCreate() { //创建命名管道 m_hPipe = CreateNamedPipe("\\\\.\\pipe\\MyPipe", PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED, 0, 1, 1024, 1024, 0, NULL); if (INVALID_HANDLE_VALUE == m_hPipe) { MessageBox("创建命名管道失败!"); m_hPipe = NULL; return; } //创建匿名的人工重置事件对象 HANDLE hEvent; hEvent = CreateEvent(NULL, TRUE, FALSE,NULL); if (!hEvent) { MessageBox("创建事件对象失败"); CloseHandle(m_hPipe); m_hPipe = NULL; return; } OVERLAPPED ovlap; ZeroMemory(&ovlap, sizeof(OVERLAPPED)); ovlap.hEvent = hEvent; //等待客户端请求的到来 if (!ConnectNamedPipe(m_hPipe, &ovlap)) { if (ERROR_IO_PENDING != GetLastError()) { MessageBox("等待客户端连接失败!"); CloseHandle(m_hPipe); CloseHandle(hEvent); m_hPipe = NULL; return; } } if (WAIT_FAILED == WaitForSingleObject(hEvent, INFINITE)) { MessageBox("等待事件对象失败!"); CloseHandle(m_hPipe); CloseHandle(hEvent); m_hPipe = NULL; return; } CloseHandle(hEvent);//执行到这一步,说明已经有客户端连上命名管道实例,不再需要该事件对象句柄 } void CNamedPipeSrcView::OnPipeRead() { char buf[100]; DWORD dwRead; if (!ReadFile(m_hPipe, buf, 100, &dwRead, NULL)) { MessageBox("读取数据失败!"); return; } MessageBox(buf); } void CNamedPipeSrcView::OnPipeWrite() { char buf[]="dadadadakai"; DWORD dwWrite; if (!WriteFile(m_hPipe, buf, strlen(buf)+1, &dwWrite, NULL)) { MessageBox("写入数据失败!"); return; } }
客户端
void CNamedPipeClientView::OnPipeConnect() { //判断是否有可以利用的命名管道 if (!WaitNamedPipe("\\\\.\\pipe\\MyPipe", //如果是跨网络通信,则在圆点处指定服务器端程序所在的主机名 NMPWAIT_USE_DEFAULT_WAIT)) { MessageBox("当前没有可以利用的命名管道实例!"); return; } //打开可用的命名管道,并与服务器端进程进行通信 m_hPipe = CreateFile("\\\\.\\pipe\\MyPipe", GENERIC_READ|GENERIC_WRITE, 0,NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == m_hPipe) { MessageBox("打开命名管道失败!"); m_hPipe = NULL; return; } } void CNamedPipeClientView::OnPipeRead() { char buf[100]; DWORD dwRead; if (!ReadFile(m_hPipe,buf,100,&dwRead,NULL))//利用命名管道读取数据 { MessageBox("读取数据失败!"); return; } else { MessageBox(buf); } } void CNamedPipeClientView::OnPipeWrite() { char buf[]="yyyyyyyxue"; DWORD dwWrite; if (!WriteFile(m_hPipe,buf,strlen(buf)+1, &dwWrite, NULL))//利用命名管道写入数据 { MessageBox("写入数据失败!"); return; } }
收藏的用户(0) X
正在加载信息~
推荐阅读
最新回复 (0)
站点信息
- 文章2303
- 用户1336
- 访客11157317
每日一句
There is always a better way.
总有更好的办法。
总有更好的办法。
IntelliJ IDEA2018~2019.1激活码-注册码
C++实现NAT检测程序
Google Play商城将85款恶意App下架
打开显示interface.png 或者显示interface.swf
【黑苹果安装】——如何在windows下操作EFI分区
Android简单树状实现
Android 8.0应用图标适配
Android Studio3.4.1更新及槽点
C/C++通过WMI和系统API函数获取系统硬件配置信息
DuiLib编译出错:成员声明中不允许限定名
Java中的(耦合)控制反转
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is
#ifdef _DEBUG失效问题
新会员