孙鑫: 第十七讲 进程间通信四种方式

 详细讲解进程间通讯的四种方式:剪贴板、匿名管道、命名管道和邮槽。
    并比较分析这几种进程间通信的优点和缺点。
比较:
    剪贴板和匿名管道只能在本机进程间通讯;
    命名管道和邮槽都可以网络进程通讯;
    命名管道只能是点对点的通讯;
    邮槽可以一对多的单向通讯,但是数据量小;
1.剪贴板
void CClipboardDlg::OnBtnSend()
{
// TODO: Add your control notification handler code here
if(OpenClipboard())
{
    CString str;
    HANDLE hClip;
    char *pBuf;
    EmptyClipboard();
    GetDlgItemText(IDC_EDIT_SEND,str);
    hClip=GlobalAlloc(GMEM_MOVEABLE,str.GetLength()+1);
    pBuf=(char*)GlobalLock(hClip);
    strcpy(pBuf,str);
    GlobalUnlock(hClip);
    SetClipboardData(CF_TEXT,hClip);
    CloseClipboard();
}
}

void CClipboardDlg::OnBtnRecv()
{
// TODO: Add your control notification handler code here
if(OpenClipboard())
{
   if(IsClipboardFormatAvailable(CF_TEXT))
   {
    HANDLE hClip;
    char *pBuf;
    hClip=GetClipboardData(CF_TEXT);
    pBuf=(char*)GlobalLock(hClip);
    GlobalUnlock(hClip);
    SetDlgItemText(IDC_EDIT_RECV,pBuf);
    CloseClipboard();
   }
}
}
2.利用匿名管道
父进程:
在view的里添加2个成员变量hRead,hWrite;初始化,在析构函数里判断,如果不为NUILL,就析构
void CParentView::OnPipeCreate()
{
// TODO: Add your command handler code here
SECURITY_ATTRIBUTES sa;
sa.bInheritHandle=TRUE;
sa.lpSecurityDescriptor=NULL;
sa.nLength=sizeof(SECURITY_ATTRIBUTES);
if(!CreatePipe(&hRead,&hWrite,&sa,0))
{
   MessageBox("创建匿名管道失败!");
   return;
}
STARTUPINFO sui;
PROCESS_INFORMATION pi;
ZeroMemory(&sui,sizeof(STARTUPINFO));
sui.cb=sizeof(STARTUPINFO);
sui.dwFlags=STARTF_USESTDHANDLES;
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;
   MessageBox("创建子进程失败!");
   return;
}
else
{
   CloseHandle(pi.hProcess);
   CloseHandle(pi.hThread);
}
}

void CParentView::OnPipeRead()
{
// TODO: Add your command handler code here
char buf[100];
DWORD dwRead;
if(!ReadFile(hRead,buf,100,&dwRead,NULL))
{
   MessageBox("读取数据失败!");
   return;
}
MessageBox(buf);
}

void CParentView::OnPipeWrite()
{
// TODO: Add your command handler code here
char buf[]="
http://www.sunxin.org";
DWORD dwWrite;
if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))
{
   MessageBox("写入数据失败!");
   return;
}
}
子进程:
void CChildView::OnPipeRead()
{
// TODO: Add your command handler code here
char buf[100];
DWORD dwRead;
if(!ReadFile(hRead,buf,100,&dwRead,NULL))
{
   MessageBox("读取数据失败!");
   return;
}
MessageBox(buf);
}

void CChildView::OnPipeWrite()
{
// TODO: Add your command handler code here
char buf[]="匿名管道测试程序";
DWORD dwWrite;
if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))
{
   MessageBox("写入数据失败!");
   return;
}
}

void CChildView::OnInitialUpdate()
{
CView::OnInitialUpdate();

// TODO: Add your specialized code here and/or call the base class
hRead=GetStdHandle(STD_INPUT_HANDLE);
hWrite=GetStdHandle(STD_OUTPUT_HANDLE);
}
注意:必须要父进程启动子进程才具有父子关系
3.命名管道(可以跨网络实现进程间的通信)
2种基本通信模式:字节模式和消息模式
服务器:
在view类里添加HANDLE hPipe;初始化;析构
void CNamedPipeSrvView::OnPipeCreate()
{
// TODO: Add your command handler code here
hPipe=CreateNamedPipe("
\\\\.\\pipe\\MyPipe",
   PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
   0,1,1024,1024,0,NULL);
if(INVALID_HANDLE_VALUE==hPipe)
{
   MessageBox("创建命名管道失败!");
   hPipe=NULL;
   return;
}
HANDLE hEvent;
hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
if(!hEvent)
{
   MessageBox("创建事件对象失败!");
   CloseHandle(hPipe);
   hPipe=NULL;
   return;
}
OVERLAPPED ovlap;
ZeroMemory(&ovlap,sizeof(OVERLAPPED));
ovlap.hEvent=hEvent;
if(!ConnectNamedPipe(hPipe,&ovlap))
{
   if(ERROR_IO_PENDING!=GetLastError())
   {
    MessageBox("等待客户端连接失败!");
    CloseHandle(hPipe);
    CloseHandle(hEvent);
    hPipe=NULL;
    return;
   }
}
if(WAIT_FAILED==WaitForSingleObject(hEvent,INFINITE))
{
   MessageBox("等待对象失败!");
   CloseHandle(hPipe);
   CloseHandle(hEvent);
   hPipe=NULL;
   return;
}
CloseHandle(hEvent);
}

void CNamedPipeSrvView::OnPipeRead()
{
// TODO: Add your command handler code here
char buf[100];
DWORD dwRead;
if(!ReadFile(hPipe,buf,100,&dwRead,NULL))
{
   MessageBox("读取数据失败!");
   return;
}
MessageBox(buf);
}

void CNamedPipeSrvView::OnPipeWrite()
{
// TODO: Add your command handler code here
char buf[]="
http://www.sunxin.org";
DWORD dwWrite;
if(!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL))
{
   MessageBox("写入数据失败!");
   return;
}
}
客户端:
void CNamedPipeCltView::OnPipeConnect()
{
// TODO: Add your command handler code here
if(!WaitNamedPipe("
\\\\.\\pipe\\MyPipe",NMPWAIT_WAIT_FOREVER))
{
   MessageBox("当前没有可利用的命名管道实例!");
   return;
}
hPipe=CreateFile("
\\\\.\\pipe\\MyPipe",GENERIC_READ | GENERIC_WRITE,
   0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(INVALID_HANDLE_VALUE==hPipe)
{
   MessageBox("打开命名管道失败!");
   hPipe=NULL;
   return;
}
}

void CNamedPipeCltView::OnPipeRead()
{
// TODO: Add your command handler code here
char buf[100];
DWORD dwRead;
if(!ReadFile(hPipe,buf,100,&dwRead,NULL))
{
   MessageBox("读取数据失败!");
   return;
}
MessageBox(buf);
}

void CNamedPipeCltView::OnPipeWrite()
{
// TODO: Add your command handler code here
char buf[]="命名管道测试程序";
DWORD dwWrite;
if(!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL))
{
   MessageBox("写入数据失败!");
   return;
}
}
4.邮槽(无连接,不可靠,单向;广播(实现一对多的通信);创建邮槽的服务器读取数据,客户端写入数据)
服务端:
void CMailslotSrvView::OnMailslotRecv()
{
// TODO: Add your command handler code here
HANDLE hMailslot;
hMailslot=CreateMailslot("
\\\\.\\mailslot\\MyMailslot",0,
   MAILSLOT_WAIT_FOREVER,NULL);
if(INVALID_HANDLE_VALUE==hMailslot)
{
   MessageBox("创建油槽失败!");
   return;
}
char buf[100];
DWORD dwRead;
if(!ReadFile(hMailslot,buf,100,&dwRead,NULL))
{
   MessageBox("读取数据失败!");
   CloseHandle(hMailslot);
   return;
}
MessageBox(buf);
CloseHandle(hMailslot);
}
客户端:
void CMailslotCltView::OnMailslotSend()
{
// TODO: Add your command handler code here
HANDLE hMailslot;
hMailslot=CreateFile("
\\\\.\\mailslot\\MyMailslot",GENERIC_WRITE,
   FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(INVALID_HANDLE_VALUE==hMailslot)
{
   MessageBox("打开油槽失败!");
   return;
}
char buf[]="
http://www.sunxin.org";
DWORD dwWrite;
if(!WriteFile(hMailslot,buf,strlen(buf)+1,&dwWrite,NULL))
{
   MessageBox("写入数据失败!");
   CloseHandle(hMailslot);
   return;
}
CloseHandle(hMailslot);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值