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\n", 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\n", GetLastError());
        return -1;
    }
    TCHAR content[] = _T("我是客户端邮槽,向服务器发送测试数据。");
    DWORD nBytesWritten;
    if (!WriteFile(hSlot, content, sizeof(content), &nBytesWritten, NULL))
    {
        printf("向邮槽写入数据失败,错误代码:%d\n", GetLastError());
        return -1;
    }
    printf("向邮槽写入了%d个字节的数据。\n", 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

 

 

 

 

 

 

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

posted @ 2020-01-02 22:35  htj10  阅读(506)  评论(0编辑  收藏  举报
TOP