MFC 进程之间通讯之命名管道
命名管道(NamedPipe)是服务器进程和一个或多个客户进程之间通信的单向或双向管道。不同于匿名管道的是:命名管道可以在不相关的进程之间和不同计算机之间使用,服务器建立命名管道时给它指定一个名字,任何进程都可以通过该名字打开管道的另一端,根据给定的权限和服务器进程通信。命名管道提供了相对简单的编程接口,使通过网络传输数据并不比同一计算机上两进程之间通信更困难,不过如果要同时和多个进程通信它就力不从心了。
还是上讲的两个工程和进程(参看:内存映射文件)
在每个工程中分别添加namedpipe类的实现文件:
NamedPipe.h
#pragma once class CNamedPipe { HANDLE m_hHandleWritePipe; HANDLE m_hHandleReadPipe; public: CNamedPipe(void); ~CNamedPipe(void); BOOL Create(CString strPipeName); BOOL Delete(); BOOL WaitConnect(); BOOL OpenPipe(CString strPipeName); BOOL SendData(const char *pStr, DWORD dwSize); BOOL ReadData(char *DesStr, DWORD dwSize); };
NamedPipe.cpp
#include "StdAfx.h" #include "NamedPipe.h" CNamedPipe::CNamedPipe(void) { m_hHandleWritePipe = NULL; m_hHandleReadPipe = NULL; } CNamedPipe::~CNamedPipe(void) { Delete(); } /* Function: create named pipe PARAM: strPipeName[in] : pipe name RETURN: TRUE: create success FALSE: create failed */ BOOL CNamedPipe::Create(CString strPipeName) { m_hHandleWritePipe = ::CreateNamedPipe(CString("\\\\.\\pipe\\") + CString(strPipeName), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE|PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 0, 0, NMPWAIT_WAIT_FOREVER, NULL); if(NULL == m_hHandleWritePipe) { return FALSE; } return TRUE; } /* Function: delete handle and release memory Param: NULL return: TRUE: delete success FALSE: delete failed */ BOOL CNamedPipe::Delete() { if(NULL == m_hHandleWritePipe) { return TRUE; } else { if(!::DisconnectNamedPipe(m_hHandleWritePipe)) { return FALSE; } if(!::CloseHandle(m_hHandleWritePipe)) { return FALSE; } } if(NULL == m_hHandleReadPipe) { return TRUE; } else { if(!::CloseHandle(m_hHandleWritePipe)) { return FALSE; } } return TRUE; } /* Function: wait client connect Param: NULL return: TRUE: connect success FALSE: connect failed */ BOOL CNamedPipe::WaitConnect() { BOOL bResult = ::ConnectNamedPipe(m_hHandleWritePipe, NULL); int err = GetLastError(); return bResult; } /* Function: send data Param: pStr[in]: address dwSize[in]: buffer size return: TRUE: send success FALSE: send failed */ BOOL CNamedPipe::SendData(const char *pStr, DWORD dwSize) { BOOL bResult = TRUE; DWORD dwWrite; if (!WriteFile(m_hHandleWritePipe, pStr, dwSize, &dwWrite, NULL)) { AfxMessageBox("write pipe failed!"); bResult = FALSE; } return bResult; } /* Function: open exist pipe Param: strPipeName[in]: pipe name return: TRUE: open success FALSE: open failed */ BOOL CNamedPipe::OpenPipe(CString strPipeName) { if (WaitNamedPipe(CString("\\\\.\\Pipe\\")+ CString(strPipeName), NMPWAIT_WAIT_FOREVER) == FALSE) { int err = GetLastError(); return FALSE; } m_hHandleReadPipe = CreateFile(CString("\\\\.\\Pipe\\")+ CString(strPipeName), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if ((long)m_hHandleReadPipe == -1) return FALSE; return TRUE; } /* Function: read data from pipe Param: DesStr[out]: address dwSize[out]; buffer size return: TRUE: open success FALSE: open failed */ BOOL CNamedPipe::ReadData(char *DesStr, DWORD dwSize) { DWORD len = 0; BOOL bResult = ReadFile(m_hHandleReadPipe, DesStr, dwSize, &len, NULL); return bResult; }
在ShareMemoryTest工程中的按钮响应函数添加如下代码:
void CShareMemoryTestDlg::OnBnClickedOk() { // TODO: Add your control notification handler code here //CDialogEx::OnOK(); /*CString strShareMemory = "hello my first mapping file!\n"; CShareMemory ShareMemory; char *pShareMemory = ShareMemory.Create("D:\ShareMemoryTestFile.txt", strShareMemory.GetLength()); if(pShareMemory) { sprintf(pShareMemory, strShareMemory); AfxMessageBox("write over"); }*/ CNamedPipe namedPipe; namedPipe.Create("namedpipe"); if(namedPipe.WaitConnect()) { char data[32] = "test named pipe."; namedPipe.SendData(data, 32); } }
在ShareMemoryTest2工程中的按钮响应函数添加如下代码:
void CShareMemoryTest2Dlg::OnBnClickedOk() { // TODO: Add your control notification handler code here //CDialogEx::OnOK(); /*CShareMemory ShareMemory; char *pShareMemory = ShareMemory.Open("D:\ShareMemoryTestFile.txt"); if(pShareMemory) { AfxMessageBox(pShareMemory); }*/ CNamedPipe namedPipe; namedPipe.OpenPipe("namedpipe"); char data[32]; memset(data, 0, 32); namedPipe.ReadData(data, 32); AfxMessageBox(data); }
先运行第一个进程,后运行第二个进程,如下图所示: