28-进程间通信:匿名管道

进程间通信:匿名管道

匿名管道是一个没有命名的单向管道,本质上就是一个共享的内存区域。通常用来在父进程和子进程之间通信。

注:只能实现本地两个进程之间的通信。不能实现网络通信。

1.创建匿名管道函数

CreatePipe(
_Out_ PHANDLE hReadPipe, //该变量接收管道的读取句柄
_Out_ PHANDLE hWritePipe, // 该变量接收管道的写句柄
_In_opt_ LPSECURITY_ATTRIBUTES lpPipeAttributes,//NULL
_In_ DWORD nSize //管道缓冲区的大小 0 :默认缓冲区大小
);

2.父进程程序

使用时修改子进程名称,其余一致

HANDLE hReadPipe;						//创建在该进程下,能够读取和写入管道的全局句柄
HANDLE hWritePipe;
void CChildView::OnPipeCreate() //对应创建子进程的按钮
{
// TODO: 在此添加命令处理程序代码
//创建匿名管道
SECURITY_ATTRIBUTES sa;
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, 0))
{
MessageBox(_T("匿名管道创建失败"));
return;
}
//创建子进程
STARTUPINFO strStartupInfo; //用来指定新进程窗口如何显示
memset(&strStartupInfo, 0, sizeof(strStartupInfo));
strStartupInfo.cb = sizeof(strStartupInfo);
strStartupInfo.dwFlags = STARTF_USESTDHANDLES;
strStartupInfo.hStdInput = hReadPipe;
strStartupInfo.hStdOutput = hWritePipe;
strStartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
PROCESS_INFORMATION szProcessInformation;
memset(&szProcessInformation, 0, sizeof(szProcessInformation));
//准备工作完成,开始创建
int iRet = CreateProcess(
_T("MailSlotClient.exe"), //子进程名称
NULL,
NULL,
NULL,
TRUE,
0,
NULL,
NULL,
&strStartupInfo,
&szProcessInformation
);
if (iRet)
{
//创建成功
CloseHandle(szProcessInformation.hProcess);
CloseHandle(szProcessInformation.hThread);
szProcessInformation.dwProcessId = 0;
szProcessInformation.dwThreadId = 0;
szProcessInformation.hThread = NULL;
szProcessInformation.hProcess = NULL;
}
else
{
CloseHandle(hReadPipe);
CloseHandle(hWritePipe);
hReadPipe = NULL;
hWritePipe = NULL;
MessageBox(_T("创建子进程失败"));
return;
}
}
void CChildView::OnPipeRead() //对应接收按钮
{
char szBuf[100] = { 0 };
DWORD dwRead;
TRACE("Begin ReadFile");
if (!ReadFile(hReadPipe, szBuf, 100, &dwRead, NULL))
{
MessageBox(_T("读取数据失败"));
return;
}
TRACE("End PipeReadFile");
MessageBox((CStringW)szBuf);
}
void CChildView::OnPipeWrite() //对应发送按钮
{
//写入数据
char szBuf[] = "Bingo hen shuai";
DWORD dwWrite;
if (!WriteFile(hWritePipe, szBuf, strlen(szBuf) + 1, &dwWrite, NULL))
{
MessageBox(_T("写入数据失败"));
return;
}
}

3.子进程程序

该进程由于是父进程打开的,因此能使用GetStdHandle(STD_INPUT_HANDLE)来共享父进程传递来的句柄

void CChildView::OnCliPipeRead()
{
HANDLE hReadCliPipe =GetStdHandle(STD_INPUT_HANDLE);
char szBuf[100] = { 0 };
DWORD dwRead;
TRACE("Begin ReadFile"); //查找所有引用shift + alt + F
if (!ReadFile(hReadCliPipe, szBuf, 100, &dwRead, NULL))
{
MessageBox(_T("读取数据失败"));
return;
}
TRACE("End PipeReadFile");
MessageBox((CStringW)szBuf);
}
void CChildView::OnCliPipeWrite()
{
HANDLE hWriteCliPipe = GetStdHandle(STD_OUTPUT_HANDLE);
char szBuf[] = "Bingo Bingo";
DWORD dwWrite;
if (!WriteFile(hWriteCliPipe, szBuf, strlen(szBuf) + 1, &dwWrite, NULL))
{
MessageBox(_T("写入数据失败"));
CloseHandle(hWriteCliPipe);
return;
}
CloseHandle(hWriteCliPipe);
}