zoukankan      html  css  js  c++  java
  • VC-进程间通信(InterProcess Communication,IPC)

    邮槽

    创建邮槽的进程是邮槽服务器,得到邮槽句柄,只有通过邮槽句柄才可以读数据。ReadFile(...)

    邮槽创建时,邮槽名称必须是如下形式:\.mailslot[path]name

    例子:

    // MailslotServer.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include <Windows.h>
    #include <atlstr.h>
    #include <iostream>
    #define BUF_SIZE 512
    int _tmain(int argc, _TCHAR* argv[])
    {
        const TCHAR* name = _T("\\.\mailslot\slotTest");
        HANDLE hSlot = CreateMailslot(name, 0, MAILSLOT_WAIT_FOREVER, NULL);
        if (INVALID_HANDLE_VALUE == hSlot)
        {
            printf("创建邮槽失败。错误代码:%d
    ", GetLastError());
            return -1;
        }
        TCHAR buffer[BUF_SIZE] = { 0 };
        DWORD nReadBytes;
        if (ReadFile(hSlot, buffer, BUF_SIZE-1, &nReadBytes, NULL))
        {
            std::wcout.imbue(std::locale("chs"));
            std::wcout << (wchar_t*)buffer << std::endl;
        }
        return 0;
    }
    
    //////////////////////////////////////////////////
    // MailslotClient.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include <Windows.h>
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        const TCHAR* name = _T("\\.\mailslot\slotTest");
        HANDLE hSlot = CreateFile(name, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if (INVALID_HANDLE_VALUE == hSlot)
        {
            printf("创建客户端邮槽失败。错误代码=%d
    ", GetLastError());
            return -1;
        }
        TCHAR content[] = _T("我是客户端邮槽,向服务器发送测试数据。");
        DWORD nBytesWritten;
        if (!WriteFile(hSlot, content, sizeof(content), &nBytesWritten, NULL))
        {
            printf("向邮槽写入数据失败,错误代码:%d
    ", GetLastError());
            return -1;
        }
        printf("向邮槽写入了%d个字节的数据。
    ", nBytesWritten);
        CloseHandle(hSlot);
        return 0;
    }
    View Code

    匿名管道

    父子进程通信,可以双向传输,本地进程通信,CreateProcess()中设置可继承句柄 bInheritHandles为TRUE

    例子

    //// 父进程
    void CPipeServerSampleDlg::OnBnClickedButton1()
    {
        // 创建匿名管道,创建子进程
        SECURITY_ATTRIBUTES sa = {sizeof(sa), NULL, TRUE};
        HANDLE hRead, hWrite;
        if (!CreatePipe(&hRead, &hWrite, &sa, 0))
        {
            //"创建匿名管道失败"
            return;
        }
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
        si.cb = sizeof(si);
        GetStartupInfo(&si);
        si.hStdError = hWrite;
        si.hStdOutput = hWrite;//将子进程的标准输入输出重定向为管道的读写句柄
        si.hStdInput = hRead;
        si.wShowWindow = SW_HIDE;//隐藏窗口运行
        si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;//开关打开,否则上面是设置无效
        TCHAR szCmdLine[] = _T("PipeClientSample.exe");
        if (!CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi))
        {
            //"创建子进程失败"
            return;
        }
        CloseHandle(hWrite);
    
        CStringA log;
        DWORD fileSize = GetFileSize(hRead, NULL);//获取管道中的内容大小
        void* buffer = new BYTE[fileSize + 1]();
        DWORD dwByteReads;
        if (!ReadFile(hRead, buffer, fileSize, &dwByteReads, NULL))
            return;//读取失败
        log += (char*)buffer;
        delete[] buffer;
        SetDlgItemTextA(this->GetSafeHwnd(), IDC_EDIT1, log);
    
        CloseHandle(hRead);
    }
    
    //// 子进程
    // PipeClientSample.cpp : 定义控制台应用程序的入口点。
    
    #include <iostream>
    int main(int argc, char* argv[])
    {
        std::cout << "这是PipeClientSample的标准输出std::cout" << std::endl;
        std::cerr << "这是PipeClientSample的错误输出std::cerr" << std::endl;
        return 0;
    }
    View Code

     命名管道

    支持网络进程间通信

    // NamedPipeServer.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include <Windows.h>
    #include <iostream>
    using std::cout;
    using std::endl;
    int _tmain(int argc, _TCHAR* argv[])
    {
        const char* szName = "\\.\pipe\aaa\bbb\myPipe";
        //创建命名管道
        HANDLE hPipe = CreateNamedPipeA(szName, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE, 1, 1024, 1024, 0, NULL);
        if (INVALID_HANDLE_VALUE == hPipe)
        {
            return -1;
        }
        //等待客户端连接
        BOOL bRet = ConnectNamedPipe(hPipe, NULL);
        //读数据
        int nLen = GetFileSize(hPipe, NULL);
        char* buf = new char[nLen+1]();//
        DWORD dwBytes;
        ReadFile(hPipe, buf, nLen, &dwBytes, NULL);
        cout << "读到的数据:" << buf << endl << "buf's length : " << nLen << "  dwBytes : " << dwBytes << endl;
        delete[] buf;
        //写数据
        char buf2[] = "PipeServer写的数据。";
        DWORD dwBytesWritten;
        WriteFile(hPipe, buf2, sizeof(buf2), &dwBytesWritten, NULL);
        cout << "写入数据:" << dwBytesWritten << "Bytes" << endl;
    
        getchar();
        return 0;
    }
    
    
    //------------------------------------------
    
    // NamedPipeClient.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include <Windows.h>
    #include <iostream>
    using std::cout;
    using std::endl;
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        const char* szName = "\\.\pipe\aaa\bbb\myPipe";
        //连接命名管道
        WaitNamedPipeA(szName, NMPWAIT_WAIT_FOREVER);
        //打开命名管道
        HANDLE hPipe = CreateFileA(szName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if (INVALID_HANDLE_VALUE == hPipe)
            return -1;
        //
        char buf2[] = "PipeClient写的数据。";
        DWORD dwBytesWritten;
        WriteFile(hPipe, buf2, sizeof(buf2), &dwBytesWritten, NULL);
        //
        Sleep(100);//为了能Server端写上数据
        int nLen = GetFileSize(hPipe, NULL);
        char* buf = new char[nLen + 1]();//
        DWORD dwBytes;
        ReadFile(hPipe, buf, nLen, &dwBytes, NULL);
        cout << "读到的数据:" << buf << endl << "buf's length : " << nLen << "  dwBytes : " << dwBytes << endl;
        delete[] buf;
    
        getchar();
        return 0;
    }
    View Code

    Socket通信

    参考:MFC中Socket网络通讯  和  Windows下socket编程(console非MFC)

    发送WM_COPYDATA消息

    参考:MFC中WM_COPYDATA消息

    剪切板

    填充剪切板(像ctrl+c)

    void CClipboardDlg::OnBnClickedButtonSend()
    {
        // TODO:  在此添加控件通知处理程序代码
        if (OpenClipboard())
        {
            EmptyClipboard();
            CString str1;
            GetDlgItemText(IDC_EDIT_SEND, str1);
            CStringA str(str1);
            HANDLE hClip;//保存调用GlobalAlloc()后返回的内存对象地址
            char* pBuf;//保存调用GlobalLock后返回的内存地址
            DWORD dwBytes = (str.GetLength() + 1)*sizeof(str[0]);
            hClip = GlobalAlloc(GMEM_MOVEABLE, dwBytes);
            pBuf = (char*)GlobalLock(hClip);
            strcpy_s(pBuf, str.GetLength() + 1, str.GetString());
            GlobalUnlock(hClip);
            SetClipboardData(CF_TEXT, hClip);
            CloseClipboard();//一定要关闭剪切板
        }
    }
    View Code

    获取剪切板内容

    void CClipboardDlg::OnBnClickedButtonRecv()
    {
        // TODO:  在此添加控件通知处理程序代码
        if (OpenClipboard())
        {
            if (IsClipboardFormatAvailable(CF_TEXT))
            {
                HANDLE hClip;
                char* buf;
                hClip = GetClipboardData(CF_TEXT);
                buf = (char*)GlobalLock(hClip);
                GlobalUnlock(hClip);
                CString str(buf);
                SetDlgItemText(IDC_EDIT_RECV, str);
            }
            CloseClipboard();
        }
    }
    View Code

    ----------------------------------------------------

    常记溪亭日暮,沉醉不知归路。兴尽晚回舟,误入藕花深处。争渡,争渡,惊起一滩鸥鹭。

    昨夜雨疏风骤,浓睡不消残酒。试问卷帘人,却道海棠依旧。知否?知否?应是绿肥红瘦。
  • 相关阅读:
    [ARC101C] Ribbons on Tree
    NOIP2020 模拟赛 B 组 Day6
    #10471. 「2020-10-02 提高模拟赛」灌溉 (water)
    #10470. 「2020-10-02 提高模拟赛」流水线 (line)
    一类巧妙利用利用失配树的序列DP
    学军中学csp-noip2020模拟5
    信号与槽-高级应用
    PyQt5中的布局管理-QSplitter
    PyQt5中的布局管理-嵌套布局
    信号与槽-入门应用
  • 原文地址:https://www.cnblogs.com/htj10/p/12142446.html
Copyright © 2011-2022 走看看