[Windows进程间通信] 命名管道


参考链接:

一个比较基本的示例:https://blog.csdn.net/caoshangpa/article/details/53199022

详细的介绍及对命名管道安全的探讨:https://blog.csdn.net/qq_36119192/article/details/112274131

命名管道虽然看起来和匿名管道类似,但是却是大大的不同。以下列出几点

1. 匿名管道只能用于父子进程间通信,命名管道则无此限制,各个进程都可以通过名字获取管道并通信。但是因此比匿名管道要占用更多资源,效率略低

2. 命名管道不仅可以跨进程,也可以跨机器,同时也存在安全问题。详细可以参考开头的链接

关于管道的内容可以写出很多,这里暂时先写一个例程。思路与文件映射类似,server端负责创建管道,cient端通过管道名字获取管道并和server交互。

如果需要使用其他机器上的管道,那么管道的名字需要加入server name。需要注意的是,命名管道受到windows ACL的控制,如果权限不够的话,是无法连接其他机器上的管道的。

下面是一个使用本地命名管道的示例

Server端

#include 
#include 
using namespace std;

#define BUFFER_SIZE 1024
#define PIPE_NAME "\\\\.\\pipe\\test"

int main() {
    char buffer[BUFFER_SIZE] = { 0 };
    DWORD readNum;

    auto hPipe = CreateNamedPipe(
        PIPE_NAME, 
        PIPE_ACCESS_DUPLEX, 
        PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 
        1, 
        0, 
        0, 
        1000, 
        NULL
    );
    if (hPipe == INVALID_HANDLE_VALUE) {
        cout << "Create named pipe failed!" << endl;
        return -1;
    }

    if (ConnectNamedPipe(hPipe, NULL) == FALSE) {
        cout << "Failed to connect pipe!" << endl;
        CloseHandle(hPipe);
        return -1;
    }
    cout << "Connected to pipe!" << endl;

    while (1) {
        if (ReadFile(hPipe, buffer, 1024, &readNum, NULL) == FALSE) {
            cout << "Failed to read data!" << endl;
            break;
        }

        buffer[readNum] = 0;
        cout << "Read data: " << buffer << endl;
    }

    cout << "Close pipe!" << endl;
    CloseHandle(hPipe);

    return 0;
}

Client端

#include 
#include 
using namespace std;

#define PIPE_NAME "\\\\.\\pipe\\test"
#define BUFFER_SIZE 1024

int main() {
    char buffer[BUFFER_SIZE] = { 0 };
    DWORD writeNum;

    if (WaitNamedPipe(PIPE_NAME, NMPWAIT_WAIT_FOREVER) == FALSE) {
        cout << "Wait named pipe failed!" << endl;
        return -1;
    }

    auto hPipe = CreateFile(
        PIPE_NAME, 
        GENERIC_READ | GENERIC_WRITE, 
        0, 
        NULL, 
        OPEN_EXISTING, 
        FILE_ATTRIBUTE_NORMAL, 
        NULL
    );
    if (hPipe == INVALID_HANDLE_VALUE) {
        cout << "Failed to create file!" << endl;
        return -1;
    }
    cout << "Connected to server!" << endl;

    while (1) {
        cin >> buffer;
        if (WriteFile(
            hPipe, 
            buffer, 
            strnlen_s(buffer, BUFFER_SIZE), 
            &writeNum, 
            NULL
        ) == FALSE) {
            cout << "write failed!" << endl;
            break;
        }
    }

    cout << "Close pipe!" << endl;
    CloseHandle(hPipe);

    return 0;
}