• 进程间通信有四种方法


    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 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));//将数据清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 here
    char buf[100];
    DWORD dwRead;
    if(!ReadFile(hRead,buf,100,&dwRead,NULL))
    {
      MessageBox("读取数据失败!");
      return;
    }
    MessageBox(buf);
    }
    void CParentView::OnPipeWrite() //菜单“写入数据”代码
    {
    // TOD Add your command handler code here
    char buf[]="www.msn.com";
    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 class
    hRead=GetStdHandle(STD_INPUT_HANDLE);注意这句代码!
    hWrite=GetStdHandle(STD_OUTPUT_HANDLE);
    }
      e.加菜单“读取数据”“写入数据”其代码如下:
    void CChildView::OnPipeRead()
    {
    // TOD 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()
    {
    // TOD Add your command handler code here
    char 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 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()
    {
    // TOD 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()
    {
    // TOD Add your command handler code here
    char buf[]="www.msn.com";
    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 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() 读取数据
    {
    // TOD 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() 写入数据
    {
    // TOD Add your command handler code here
    char 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 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);
    }
      c.加工程MailSlotCLT,加菜单“发送数据”
      d.加消息响应,添加代码,客户端也比较简单。
    void CMailslotCltView::OnMailslotSend() //菜单“发送数据”的代码
    {
    // TOD 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[]="www.msn.com.";
    DWORD dwWrite;
    if(!WriteFile(hMailslot,buf,strlen(buf)+1,&dwWrite,NULL))
    {
      MessageBox("写入数据失败!");
      CloseHandle(hMailslot);
      return;
    }
    CloseHandle(hMailslot);
    }
    5.以上4种方法各有优缺点:剪贴板比较简单。邮槽是基于广播的,可以一对多发送。但只能一个发送,一个接收,要想同时发送接收,须写服
    务端和客户端代码。命名管道和邮槽可以进行网络通信。
  • 相关阅读:
    中关村的那些黑暗的事——北漂18年(17)
    TRS OM error
    The user specified as a definer ('root'@'%') does not exist
    Spring 配置标签——util标签
    关于spring中<util:/>的配置
    Spring配置文件中指定init-method属性的作用
    spring
    could not insert: [com.trs.om.bean.UserLog] The user specified as a definer ('root'@'127.0.0.1') does not exist
    org.hibernate.PropertyAccessException: Null value was assigned to a property of primitive type setter of com.trs.om.bean.User.retryCount
    U盘安装win7 raid设置
  • 原文地址:https://www.cnblogs.com/lzmfywz/p/2649137.html
Copyright © 2020-2023  润新知