zoukankan      html  css  js  c++  java
  • 进程间通信

    进程间通信

    1.剪贴板

    新建一个MFC基于单文档的应用程序,取名:Clipboard,然后编辑对话框资源,如下图:

    双击发送按钮,添加消息响应函数,编辑:

    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);//
    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); //
    给句柄加锁后,存到pBuf
                GlobalUnlock(hClip); //解锁
                SetDlgItemText(IDC_EDIT_RECV,pBuf); //
    将数据设置到pBuf
                CloseClipboard(); 
            } 
        }
     
    }

    2.匿名管道

    父进程:

    新建一个MFC的单文档应用程序,取名:Parent,编辑资源,如下图:

    并分别对这三个菜单添加命令消息响应函数,再在CParentView类上添加两个成员变量,

    private
        HANDLE hWrite; 
        HANDLE hRead;
     

    再在构造函数中初始化,在析构函数中关闭句柄,如下:

    CParentView::CParentView() 

        // TODO: add construction code here 
            hRead=NULL; 
            hWrite=NULL;
     

     
    CParentView::~CParentView() 

        if(hRead) 
            CloseHandle(hRead);//
    关闭读句柄 
        if(hWrite) 
            CloseHandle(hWrite);//
    关闭写句柄 
    }

    编辑三个菜单添加命令消息响应函数:

    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));//
    把结构体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.baidu.com"
        DWORD dwWrite; 
        if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL)) 
        { 
            MessageBox("
    写入数据失败!"); 
            return
        }
     
    }

    子进程:

    Workspace 'Parent'上点右键 -> Add New Project To Wordspace… ,新建一个MFC单文档应用程序,取名Child,编辑菜单资源,如下图:

    然后分别对这两个菜单项添加消息响应函数,并CChildView类上添加一个OnInitialUpdate虚函数,再添加两个成员变量:

    private
        HANDLE hRead; 
        HANDLE hWrite;
     

    在构造函数和析构函数中:

    CChildView::CChildView() 

        // TODO: add construction code here 
        hRead=NULL;  
        hWrite=NULL;
      

     
    CChildView::~CChildView() 

        if(hRead) 
            CloseHandle(hRead);//
    关闭读句柄 
        if(hWrite) 
            CloseHandle(hWrite);//
    关闭写句柄 
    }

    然后在ChildView.cpp中编辑:

    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.命名管道

    服务端:

    新建一个MFC的单文档应用程序,取名:NamedPipeSrv,编辑资源,如下图:

    并分别对这三个菜单添加命令消息响应函数,再在CNamedPipeSrvView类上添加一个成员变量:

    private
        HANDLE hPipe;

    在构造函数和析构函数中编辑:

    CNamedPipeSrvView::CNamedPipeSrvView() 

        hPipe=NULL; 

     
    CNamedPipeSrvView::~CNamedPipeSrvView() 

        if(hPipe) 
            CloseHandle(hPipe);//
    关闭这个句柄 
    }

    NamedPipeSrvView.cpp中编辑:

    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[]="
    匿名管道测试程序"
        DWORD dwWrite; 
        if(!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL)) 
        { 
            MessageBox("
    写入数据失败!"); 
            return;
     
        } 
    }

    客户端:

    Workspace 'NamedpipeSrv'上点右键 -> Add New Project To Wordspace… ,新建一个MFC单文档应用程序,取名NamedPipeClt,编辑菜单资源,如下图:

    然后分别对这两个菜单项添加消息响应函数,并CNamedPipeCltView类上添加一个成员变量:

    private
        HANDLE hPipe;
     

    并在构造函数和析构函数中编辑:

    CNamePipeCltView::CNamePipeCltView() 

        hPipe=NULL; 

     
    CNamePipeCltView::~CNamePipeCltView() 

        if(hPipe) 
        CloseHandle(hPipe);//
    关闭句柄  
    }

    编辑NamePipeCltView.cpp:

    void CNamePipeCltView::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 CNamePipeCltView::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 CNamePipeCltView::OnPipeWrite()  

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

    4.利用邮槽完成进程间通信

    服务器端:

    新建一个MFC单文档应用程序,取名:MailSlotSrv,编辑菜单资源,添加一个接收数据菜单项,并取消弹出菜单项,如下图:

    再给接收菜单添加命令消息响应,编辑:

    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);
     
    }

    客户端:

    Workspace 'MailSlotSrv'上点右键 -> Add New Project To Wordspace… ,新建一个MFC单文档应用程序,取名MailslotClt,编辑菜单资源,添加一个发送数据菜单项,并取消弹出菜单项,如下图:

    并这个菜单项添加命令消息响应函数,编辑:

    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[]="
    邮槽测试程序"
        DWORD dwWrite; 
        if(!WriteFile(hMailslot,buf,strlen(buf)+1,&dwWrite,NULL)) 
        { 
            MessageBox("
    写入数据失败!"); 
            CloseHandle(hMailslot); 
            return
        } 
        CloseHandle(hMailslot);
     
    }

    运行, OK !

     

  • 相关阅读:
    后台写js 并跳转
    visual studio 2010 js 调试
    网页搜索功能 多表搜索sql
    c# 取得扩展名
    ajaxFileUpload 注意!
    ajaxFileUpload js判断类型
    sortable items不让他拖,也不让他放。cancel不然他拖动
    json 多重嵌套反序列化和序列化
    C#串口操作类,包括串口读写操作
    C#操作Word的超详细总结
  • 原文地址:https://www.cnblogs.com/luowei010101/p/2030837.html
Copyright © 2011-2022 走看看