正文

第17课 进程间通信2007-05-01 15:39:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/bclz/25444.html

分享到:

有四种方法1.剪贴板  a.创建个ClipBoard的对话框应用程序,加两EditBox和两个Button发送接收。  b.具体代码:    发送端代码: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();}     接收端代码: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.匿名管道:只能在父子进程之间进行通信  a.先建一个Parent的单文档应用程序,增加“创建管道”“读取数据”“写入数据”三个菜单  b.增加成员变量HANDLE类型的hRead,hWrite,初始化变量,并在析构函数中释放句柄  c.响应菜单代码:void CParentView::OnPipeCreate() 菜单“创建管道”代码{// TOD Add your command handler code hereSECURITY_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));将数据清0!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);关闭句柄,将内核对象的使用计数减少1,这样当操作系统发现内核对象的使用计数为0时,将清除内核对象。  hRead=NULL;  hWrite=NULL;  MessageBox("创建子进程失败!");  return;}else{  CloseHandle(pi.hProcess);  CloseHandle(pi.hThread);}} void CParentView::OnPipeRead() 菜单“读取数据”代码{// TOD Add your command handler code herechar buf[100];DWORD dwRead;if(!ReadFile(hRead,buf,100,&dwRead,NULL)){  MessageBox("读取数据失败!");  return;}MessageBox(buf);} void CParentView::OnPipeWrite() 菜单“写入数据”代码{// TOD Add your command handler code herechar buf[]="http://www.sunxin.org";DWORD dwWrite;if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL)){  MessageBox("写入数据失败!");  return;}}     d.再建一个Child的单文档,在View中增加两个成员hRead和hWrite.在OnInitialUpdate()中得到句柄的值。void CChildView::OnInitialUpdate() {CView::OnInitialUpdate();// TOD Add your specialized code here and/or call the base classhRead=GetStdHandle(STD_INPUT_HANDLE);注意这句代码!hWrite=GetStdHandle(STD_OUTPUT_HANDLE);}      e.加菜单“读取数据”“写入数据”其代码如下:void CChildView::OnPipeRead() {// TOD Add your command handler code herechar buf[100];DWORD dwRead;if(!ReadFile(hRead,buf,100,&dwRead,NULL)){  MessageBox("读取数据失败!");  return;}MessageBox(buf);} void CChildView::OnPipeWrite() {// TOD Add your command handler code herechar buf[]="匿名管道测试程序";DWORD dwWrite;if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL)){  MessageBox("写入数据失败!");  return;}} 3.命名管道:还可以跨网络通信,服务器只能在win2000和NT下运行!而客户端可以在95下运行。关键函数CreateNamedPipe  a.先建一个NamedPipeSRV单文档应用程序,加菜单“创建管道”“读取数据”“写入数据”  b.在View中增加Handle变量hPipe,注意在析构函数中释放它!  c.响应菜单,创建命名管道void CNamedPipeSrvView::OnPipeCreate() {// TOD Add your command handler code herehPipe=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() {// TOD Add your command handler code herechar buf[100];DWORD dwRead;if(!ReadFile(hPipe,buf,100,&dwRead,NULL)){  MessageBox("读取数据失败!");  return;}MessageBox(buf);} void CNamedPipeSrvView::OnPipeWrite() {// TOD Add your command handler code herechar buf[]="http://www.sunxin.org";DWORD dwWrite;if(!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL)){  MessageBox("写入数据失败!");  return;}}       d.再建一个NamedPipeCLT单文档工程,加菜单“连接管道”“读取数据”“写入数据”,当然别忘记成员变量hPipe的定义和初始化      e.响应菜单代码void CNamedPipeCltView::OnPipeConnect() 连接管道{// TOD Add your command handler code hereif(!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() 读取数据{// TOD Add your command handler code herechar buf[100];DWORD dwRead;if(!ReadFile(hPipe,buf,100,&dwRead,NULL)){  MessageBox("读取数据失败!");  return;}MessageBox(buf);} void CNamedPipeCltView::OnPipeWrite() 写入数据{// TOD Add your command handler code herechar buf[]="命名管道测试程序";DWORD dwWrite;if(!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL)){  MessageBox("写入数据失败!");  return;}} 4.邮槽,使用时应将消息长度限制在424字节以下,关键函数CreateMailSlot()  a.先建一个MailSlotSRV工程,加菜单“接收数据”  b.消息响应代码:void CMailslotSrvView::OnMailslotRecv() 菜单“接收数据”的代码{// TOD Add your command handler code hereHANDLE 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);}    c.加工程MailSlotCLT,加菜单“发送数据”    d.加消息响应,添加代码,客户端也比较简单。void CMailslotCltView::OnMailslotSend() 菜单“发送数据”的代码{// TOD Add your command handler code hereHANDLE 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);} 5.以上4种方法各有优缺点:剪贴板比较简单。邮槽是基于广播的,可以一对多发送。但只能一个发送,一个接收,要想同时发送接收,须写两次代码。命名管道和邮槽可以进行网络通信。

阅读(2137) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册