zoukankan      html  css  js  c++  java
  • VC++学习(17):进程间通信

    有四种方法

    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[]="http://www.sunxin.org";

    DWORD dwWrite;

    if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))

    {

     MessageBox("写入数据失败!");

     return;

    }

    }

     

         d.再建一个Child的单文档,在View中增加两个成员hReadhWrite.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.命名管道:还可以跨网络通信,服务器只能在win2000NT下运行!而客户端可以在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[]="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 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[]="http://www.sunxin.org";

    DWORD dwWrite;

    if(!WriteFile(hMailslot,buf,strlen(buf)+1,&dwWrite,NULL))

    {

     MessageBox("写入数据失败!");

     CloseHandle(hMailslot);

     return;

    }

    CloseHandle(hMailslot);

    }

    5.以上4种方法各有优缺点:剪贴板比较简单。邮槽是基于广播的,可以一对多发送。但只能一个发送,一个接收,要想同时发送接收,须写两次代码。

    命名管道和邮槽可以进行网络通信。

     

     

  • 相关阅读:
    HDU 2095 find your present (2) (异或)
    UESTC 486 Good Morning (水题+坑!)
    UVa 111 History Grading (简单DP,LIS或LCS)
    UVa 11292 Dragon of Loowater (水题,排序)
    HDU 1503 Advanced Fruits (LCS+DP+递归)
    UVa 10881 Piotr's Ants (等价变换)
    UVa 11178 Morley's Theorem (几何问题)
    HDU 1285 确定比赛名次(拓扑排序)
    .net Core的例子
    TCP与UDP的区别
  • 原文地址:https://www.cnblogs.com/forlina/p/2119788.html
Copyright © 2011-2022 走看看