pipe基本使用

一、基本函数介绍
BOOL CreatePipe( //创建管道
PHANDLE hReadPipe, //管道读数据句柄
PHANDLE hWritePipe, //管道写数据句柄
PLSECURITY_ATTRIBUTES lpPipeAttributes, //安全属性,成员bInhertHandle表示子进程是否可继承
DWORD nSize //管道缓冲区大小,0代表默认缓冲区代销
)
安全属性结构体如下:
typedef struct _SECURITY_ATTRBUTES{
DWORD nLength;
LPVOID lpSecurityDescriptor;
BOOL bInhertHandle;
}SECURITY_ATTRBUTES,*PLSECURITY_ATTRIBUTES;

BOOL CreateProcess //创建进程
(
LPCTSTR lpApplicationName,//用来指定可执行模块的字符串
LPTSTR lpCommandLine,//该字符串指定要执行的命令行
LPSECURITY_ATTRIBUTES lpProcessAttributes,//安全属性,NULL表示默认
LPSECURITY_ATTRIBUTES lpThreadAttributes,//线程是否被继承.通常置为NULL
BOOL bInheritHandles,//新进程是否从调用进程处继承了句柄
DWORD dwCreationFlags,//指定附加的、用来控制优先类和进程的创建的标志
LPVOID lpEnvironment,//指向一个新进程的环境块。如果此参数为空,新进程使用调用进程的环境
LPCTSTR lpCurrentDirectory,//这个字符串用来指定子进程的工作路径
LPSTARTUPINFO lpStartupInfo,//指向一个用于决定新进程的主窗体如何显示的STARTUPINFO结构体
LPPROCESS_INFORMATIONlpProcessInformation//指向一个用于决定新进程的主窗体如何显示的STARTUPINFO结构体
);

typedef struct _STARTUPINFO {
DWORD cb;
LPTSTR lpReserved;
LPTSTR lpDesktop;
LPTSTR lpTitle;
DWORD dwX;
DWORD dwY;
DWORD dwXSize;
DWORD dwYSize;
DWORD dwXCountChars;
DWORD dwYCountChars;
DWORD dwFillAttribute;
DWORD dwFlags;
WORD wShowWindow;
WORD cbReserved2;
LPBYTE lpReserved2;
HANDLE hStdInput;
HANDLE hStdOutput;
HANDLE hStdError;
} STARTUPINFO, *LPSTARTUPINFO;

typedef struct_PROCESS_INFORMATION{
HANDLE hProcess;
HANDLE hThread;
DWORD dwProcessId;
DWORD dwThreadId;
}PROCESS_INFORMATION;

二、匿名管道:只用于父子进程
创建匿名管道

SECURITY_ATTRIBUTES sa;
    sa.bInheritHandle = TRUE;
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    if (!CreatePipe(&hRead, &hWrite, &sa, 0))
    {
        MessageBox(L"创建匿名管道失败");
        return;
    }

    STARTUPINFO sui;
    ZeroMemory(&sui, sizeof(STARTUPINFO));
    sui.cb = sizeof(STARTUPINFO);
    sui.dwFlags = STARTF_USESTDHANDLES;
    sui.hStdInput = hRead;
    sui.hStdOutput = hWrite;
    sui.hStdError = GetStdHandle(STD_ERROR_HANDLE);

    PROCESS_INFORMATION pi;
    if (!CreateProcess(L"..\\Debug\\PipeChild.exe", NULL, NULL
        , NULL, TRUE, 0, NULL, NULL, &sui, &pi))
    {
        CloseHandle(hRead);
        CloseHandle(hWrite);
        hRead = NULL;
        hWrite = NULL;

        CString strTips;
        strTips.Format(L"%d", GetLastError());
        MessageBox(L"创建子进程失败");
        MessageBox(strTips);
        return;
    }
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

读取数据

char szBuf[100] = { 0 };
    DWORD dwRead;
    if (!ReadFile(hRead, szBuf, 100, &dwRead, NULL))
    {
        MessageBox(L"读取数据失败");
        return;
    }
    CString strData(szBuf);
    MessageBox(strData);

写入数据

char szData[] = "parent:this is a test";
    DWORD dwWrite;
    if (!WriteFile(hWrite, szData, strlen(szData) + 1, &dwWrite, NULL))
    {
        MessageBox(L"写入数据失败");
        return;
    }

Tips:在子进程需要获取父进程创建时指定的管道操作句柄

三、命名管道
创建管道

hPipe = CreateNamedPipe(L"\\\\.\\pipe\\MyPipe", PIPE_ACCESS_DUPLEX
        | FILE_FLAG_OVERLAPPED, 0, 1, 1024, 1024, 0, NULL);
    if (INVALID_HANDLE_VALUE == hPipe)
    {
        MessageBox(L"创建命名管道失败");
        hPipe = nullptr;
        return;
    }
    //创建那么人工重置事件对象
    HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (NULL == hEvent)
    {
        MessageBox(L"创建事件对象失败");
        CloseHandle(hPipe);
        hPipe = nullptr;
        return;
    }

    OVERLAPPED ovlap;
    ZeroMemory(&ovlap, 0, sizeof(OVERLAPPED));
    ovlap.hEvent = hEvent;
    if (!ConnectNamedPipe(hPipe, &ovlap))
    {
        if (ERROR_IO_PENDING != GetLastError())
        {
            MessageBox(L"等待客户端连接失败");
            CloseHandle(hPipe);
            hPipe = nullptr;
            CloseHandle(hEvent);
            return;
        }
    }
    if (WAIT_FAILED == WaitForSingleObject(hEvent, INFINITE))
    {
        MessageBox(L"等待对象失败");
        CloseHandle(hPipe);
        hPipe = nullptr;
        CloseHandle(hEvent);
        return;
    }
    CloseHandle(hEvent);

连接管道

if (!WaitNamedPipe(L"\\\\.\\pipe\\MyPipe", NMPWAIT_WAIT_FOREVER))
    {
        MessageBox(L"当前无可使用的命名管道");
        return;
    }
    hPipe = CreateFile(L"\\\\.\\pipe\\MyPipe", GENERIC_READ
        | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    if (INVALID_HANDLE_VALUE == hPipe)
    {
        MessageBox(L"打开命名管道失败");
        hPipe = nullptr;
        return;
    }

管道读写和匿名管道保持一致

你可能感兴趣的:(C++,管道,windows,管道通信)