匿名管道
匿名管道是一个未命名、单向管道,通常用来在一个父进程和一个子进程之间传输数据。匿名管道只能实现在本地机器上两个进程间的通信,而不能实现跨越网络的通信。
主要函数
CreatePipe();--创建一个匿名管道、返回该匿名管道的读写句柄。
CreateProcess();--创建一个进程
GetStdHandle();--该函数可以获得标准输入、标准输出、或者一个标准错误输出句柄
ReadFile();--可以实现对管道的读取操作
WriteFile();--可以实现对管道的写入操作
主要代码
1)Parent部分
void CParentView::OnPipeCreate()
{
// TODO: 在此添加命令处理程序代码
SECURITY_ATTRIBUTES sa;
sa.bInheritHandle=TRUE; //子进程可以继承父进程创建的匿名管道的读写句柄
sa.lpSecurityDescriptor=NULL;
sa.nLength=sizeof(SECURITY_ATTRIBUTES);
if(!CreatePipe(&hRead,&hWrite,&sa,0))
{
AfxMessageBox("创建匿名管道失败!");
return;
}
STARTUPINFO sui;
PROCESS_INFORMATION pi;
ZeroMemory(&sui,sizeof(STARTUPINFO));
sui.cb=sizeof(STARTUPINFO);
sui.dwFlags=STARTF_USESTDHANDLES; //表示当前STARTUPINFO这个结构体变量中的标准输入、标准输出和标准错误句柄三个成员是有用的
sui.hStdInput=hRead; //这里将子进程的标准输入和标准输出句柄分别设置为管道的读写句柄
sui.hStdOutput=hWrite;
sui.hStdError=GetStdHandle(STD_ERROR_HANDLE);
if(!CreateProcess("..\\Child\\Debug\\Child.exe",NULL,NULL,NULL,TRUE,0,NULL,NULL,&sui,&pi))
{
CloseHandle(hRead);
CloseHandle(hWrite);
hRead=NULL;
hWrite=NULL;
AfxMessageBox("创建子进程失败!");
return;
}
else
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
}
{
// TODO: 在此添加命令处理程序代码
SECURITY_ATTRIBUTES sa;
sa.bInheritHandle=TRUE; //子进程可以继承父进程创建的匿名管道的读写句柄
sa.lpSecurityDescriptor=NULL;
sa.nLength=sizeof(SECURITY_ATTRIBUTES);
if(!CreatePipe(&hRead,&hWrite,&sa,0))
{
AfxMessageBox("创建匿名管道失败!");
return;
}
STARTUPINFO sui;
PROCESS_INFORMATION pi;
ZeroMemory(&sui,sizeof(STARTUPINFO));
sui.cb=sizeof(STARTUPINFO);
sui.dwFlags=STARTF_USESTDHANDLES; //表示当前STARTUPINFO这个结构体变量中的标准输入、标准输出和标准错误句柄三个成员是有用的
sui.hStdInput=hRead; //这里将子进程的标准输入和标准输出句柄分别设置为管道的读写句柄
sui.hStdOutput=hWrite;
sui.hStdError=GetStdHandle(STD_ERROR_HANDLE);
if(!CreateProcess("..\\Child\\Debug\\Child.exe",NULL,NULL,NULL,TRUE,0,NULL,NULL,&sui,&pi))
{
CloseHandle(hRead);
CloseHandle(hWrite);
hRead=NULL;
hWrite=NULL;
AfxMessageBox("创建子进程失败!");
return;
}
else
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
}
void CParentView::OnPipeRead()
{
// TODO: 在此添加命令处理程序代码
char buf[100]={0};
DWORD dwRead;
if(!ReadFile(hRead,buf,100,&dwRead,NULL))
{
AfxMessageBox("读取数据失败!");
return;
}
AfxMessageBox(buf);
}
void CParentView::OnPipeWrite()
{
// TODO: 在此添加命令处理程序代码
char buf[]="www.baidu.com";
DWORD dwWrite;
if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))
{
AfxMessageBox("写入数据失败!");
return;
}
}
2)Child部分
void CChildView::OnInitialUpdate() //这个函数是窗口成功创建之后,第一个调用的函数
{
CView::OnInitialUpdate();
// TODO: 在此添加专用代码和/或调用基类
hRead=GetStdHandle(STD_INPUT_HANDLE);
hWrite=GetStdHandle(STD_OUTPUT_HANDLE);
}
void CChildView::OnPipeRead()
{
// TODO: 在此添加命令处理程序代码
char buf[100]={0};
DWORD dwRead;
if(!ReadFile(hRead,buf,100,&dwRead,NULL))
{
AfxMessageBox("读取数据失败!");
return;
}
AfxMessageBox(buf);
}
void CChildView::OnPipeWrite()
{
// TODO: 在此添加命令处理程序代码
char buf[]="匿名管道测试程序";
DWORD dwWrite;
if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))
{
AfxMessageBox("写入数据失败!");
return;
}
}
{
CView::OnInitialUpdate();
// TODO: 在此添加专用代码和/或调用基类
hRead=GetStdHandle(STD_INPUT_HANDLE);
hWrite=GetStdHandle(STD_OUTPUT_HANDLE);
}
void CChildView::OnPipeRead()
{
// TODO: 在此添加命令处理程序代码
char buf[100]={0};
DWORD dwRead;
if(!ReadFile(hRead,buf,100,&dwRead,NULL))
{
AfxMessageBox("读取数据失败!");
return;
}
AfxMessageBox(buf);
}
void CChildView::OnPipeWrite()
{
// TODO: 在此添加命令处理程序代码
char buf[]="匿名管道测试程序";
DWORD dwWrite;
if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))
{
AfxMessageBox("写入数据失败!");
return;
}
}
对于匿名管道来说,它只能在父子进程间进行通信。两个进程如果想要具有父子关系,必须由父进程通过调用CreateProcee函数启动子进程。