进程间通信方法

来源:互联网 发布:pptv网络电视机 编辑:程序博客网 时间:2024/05/01 05:44

一种机制,操作系统进程和线程通过它交换数据和消息。IPC 包括本地机制(如 Windows 共享内存)或网络机制(如 Windows 套接字)。
  进程间通讯
  一、说明进程间通讯的必要性及困难性
  二、Socket的方法,对于不同机器上且数据量很的情况会有很大的帮助,但对于同一台机器之间的不同进程之间的通讯就不方便了 (代码量太多)
  三、进程间通讯的剪切板方法
  a、对于发送端:
  CString str;
  GetDlgItemText(IDC_EDIT1,str);
  HANDLE hGlobal;
  if(this->OpenClipboard())//获取剪切板的资源所有权
  {
  EmptyClipboard();//将剪切板的内容清空
  hGlobal=GlobalAlloc(GMEM_MOVEABLE,str.GetLength()+1);//在堆上分配一块用于存放数据的空间,程序返回一个内存句柄
  char* pBuf=(char*)GlobalLock(hGlobal);//将内存块句柄转化成一个指针,并将相应的引用计数器加一
  strcpy(pBuf,str.GetBuffer(str.GetLength()));//将字符串拷入指定的内存块中
  GlobalUnlock(hGlobal);//将引用计数器数字减一
  ::SetClipboardData(CF_TEXT,hGlobal);//将存放有数据的内存块放入剪切板的资源管理中
  ::CloseClipboard();//释放剪切板的资源占用权
  }
  b、对于客户端
  if(this->OpenClipboard())//获取剪切板的资源所有权
  {
  HANDLE hGlobal=::GetClipboardData(CF_TEXT);从剪切板中取出一个内存的句柄
  char* pBuf=(char*)GlobalLock(hGlobal);//将内存句柄值转化为一个指针,并将内存块的引用计数器加一
  SetDlgItemText(IDC_EDIT2,pBuf);
  GlobalUnlock(hGlobal);//将内存块的引用计数器减一
  CloseClipboard();//释放剪切板资源的占用权
  }
  四、内存映射文件方法
  1、 服务器端代码:
  HANDLE hMapFile;
  hMapFile= CreateFileMapping(NULL,NULL,PAGE_READWRITE,0,10,"YuanMap");
  if (hMapFile == NULL)
  {
  AfxMessageBox("CreateFileMapping出错!");
  return;
  }
  LPVOID pFile;
  pFile= MapViewOfFile(hMapFile,FILE_MAP_WRITE|FILE_MAP_READ,0,0,0);
  if (pFile == NULL)
  {
  AfxMessageBox("MapViewOfFile出错!");
  return;
  }
  CString str;
  GetDlgItemText(IDC_EDIT1,str);
  strcpy((char*)pFile,str.GetBuffer(str.GetLength()));
  //CloseHandle(hMapFile); //不能加,否则客户端收不到,所以一般会将这个句柄作为一个全局变量
  2、 客户机端代码:
  HANDLE hMap;
  hMap= OpenFileMapping(FILE_MAP_READ|FILE_MAP_WRITE,
  TRUE,
  "YuanMap");
  LPVOID pVoid;
  pVoid=::MapViewOfFile(hMap,FILE_MAP_READ,0,0,0);
  CString str=(char*)pVoid;
  SetDlgItemText(IDC_EDIT1,str);
  UnmapViewOfFile(pVoid);
  CloseHandle(hMap);
  五、进程间通讯的邮槽方法
  1、 邮槽采用的是一种广播机制。
  2、 邮槽采用的是一种直接基于文件系统开发而成,所以它不依赖于某种具体的网络协议。
  3、 邮槽每次传送的消息长度不能长于422字节。
  4、 发送端代码如下:(客户端)
  HANDLE hslot;
  hslot=CreateFile("////.//mailslot//myslot",GENERIC_WRITE,
  FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,
  NULL);
  if(!hslot)
  {
  MessageBox("打开邮槽失败!");
  return;
  }
  char *pBuf="专业的编程语言培训";
  DWORD dwWrite;
  WriteFile(hslot,pBuf,strlen(pBuf)+1,&dwWrite,NULL);
  CloseHandle(hslot);
  5、 接收端代码如下:(服务器端)
  HANDLE hMail;
  hMail=CreateMailslot("////.//mailslot//myslot",0,
  MAILSLOT_WAIT_FOREVER,NULL);
  if(INVALID_HANDLE_VALUE==hMail)
  {
  MessageBox("创建邮槽失败!");
  return;
  }
  HANDLE hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
  OVERLAPPED ovlap;
  ZeroMemory(&ovlap,sizeof(ovlap));
  ovlap.hEvent=hEvent;
  char buf[200];
  DWORD dwRead;
  if(FALSE==ReadFile(hMail,buf,200,&dwRead,&ovlap))
  {
  if(ERROR_IO_PENDING!=GetLastError())
  {
  MessageBox("读取操作失败!");
  CloseHandle(hMail);
  return;
  }
  }
  WaitForSingleObject(hEvent,INFINITE);
  MessageBox(buf);
  ResetEvent(hEvent);
  CloseHandle(hMail);
  六、进程间通讯的命令管道方法
  A、对于发送端代码如下:
  HANDLE handle;
  handle=CreateNamedPipe("////.//pipe//MyPipe",
  PIPE_ACCESS_DUPLEX,PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
  1,0,0,1000,NULL);//创建一个命名管道连结
  ConnectNamedPipe(handle,NULL);//在命名管道实例上监听客户机连结请求
  char buf[200]="http://www.it315.org";
  DWORD dwWrite;
  WriteFile(handle,buf,strlen(buf)+1,&dwWrite,NULL);//往管道里写数据
  CloseHandle(handle);//关闭管道
  B、对于接收端代码如下:
  HANDLE hNamedPipe;
  WaitNamedPipe("////.//pipe//MyPipe",NMPWAIT_WAIT_FOREVER);//等候一个命名管道实例可供自己使用
  hNamedPipe=CreateFile("////.//pipe//MyPipe",GENERIC_READ,FILE_SHARE_READ,
  NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);//建立与命名管道的连结
  char buf[200];
  DWORD dwRead;
  ReadFile(hNamedPipe,buf,200,&dwRead,NULL);//从命名管道中读取数据
  MessageBox(buf);
  CloseHandle(hNamedPipe);//关闭与命名管道服务器的连结
  七、进程间通讯的匿名管道方法
  父进程:
  A、对于父进程中创建一个管道代码如下:
  SECURITY_ATTRIBUTES sa;
  sa.nLength=sizeof(sa);
  sa.bInheritHandle=TRUE;
  sa.lpSecurityDescriptor=NULL;
  if(FALSE==CreatePipe(&hRead,&hWrite,&sa,0))//创建一个匿名的管道,得到一个用于从管道读取的句柄,一个用于向管道写数据用的句柄
  {
  MessageBox("Create pipe failed!");
  return;
  }
  STARTUPINFO sui;
  ZeroMemory(&sui,sizeof(sui));
  sui.cb=sizeof(sui);
  sui.dwFlags=STARTF_USESTDHANDLES;
  sui.hStdInput=hRead;
  sui.hStdOutput=hWrite;
  sui.hStdError=GetStdHandle(STD_ERROR_HANDLE);
  PROCESS_INFORMATION pi;
  CreateProcess("..//PipeCli//Debug//PipeCli.exe",NULL,
  NULL,NULL,TRUE,CREATE_DEFAULT_ERROR_MODE,/*0*/
  NULL,NULL,&sui,&pi);//创建一个新的子进程,并将准备好的句柄信息传给子进程
  CloseHandle(pi.hProcess);
  CloseHandle(pi.hThread);
  B、父进程中从管道读取代码如下:
  char buf[200];
  DWORD dwRead;
  ReadFile(hRead,buf,200,&dwRead,NULL);
  MessageBox(buf);
  C、父进程中往管道写入代码如下:
  char buf[200]="专业的编程语言培训";
  DWORD dwWrite;
  WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL);
  子进程:
  首先得到用于管道读取与写入用的句柄值(最好是放在视图的初始化更新函数里)
  hRead=GetStdHandle(STD_INPUT_HANDLE);
  hWrite=GetStdHandle(STD_OUTPUT_HANDLE);
  读取部分代码:
  char buf[200];
  DWORD dwRead;
  ReadFile(hRead,buf,200,&dwRead,NULL);
  MessageBox(buf);
  写入部分代码:
  char buf[200]="http://www.it315.org";
  DWORD dwWrite;
  WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL); 

原创粉丝点击