【问题标题】:Create Named Pipe C++ Windows创建命名管道 C++ 窗口
【发布时间】:2014-12-21 02:23:08
【问题描述】:

我正在尝试在 C++ ( Windows ) 中的 2 个进程之间创建一个简单的通信,例如 linux 中的 FIFO。 这是我的服务器:

int main()
{
    HANDLE pipe = CreateFile(TEXT("\\\\.\\pipe\\Pipe"), GENERIC_READ, 0, NULL, OPEN_EXISTING,    FILE_FLAG_OVERLAPPED, NULL);
    ConnectNamedPipe(pipe, NULL);
    while(TRUE){
        string data;
        DWORD numRead =1 ;
        ReadFile(pipe, &data, 1024, &numRead, NULL);
        cout << data << endl;

}
    CloseHandle(pipe);
    return 0;
}

这是我的客户:

int main()
{
    HANDLE pipe = CreateFile(TEXT("\\\\.\\pipe\\Pipe"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
    ConnectNamedPipe(pipe, NULL);
    string message = "TEST";
    DWORD numWritten;
    WriteFile(pipe, message.c_str(), message.length(), &numWritten, NULL);
    return 0;
}

代码不起作用,我怎样才能将其修复为像 FIFO 一样?

【问题讨论】:

    标签: windows c++11 ipc named-pipes fifo


    【解决方案1】:

    你不能通过调用CreateFile(..)来创建命名管道。

    看看pipe examples of the MSDN。由于这些示例非常复杂,我很快就编写了一个非常简单的命名管道服务器和客户端。

    int main(void)
    {
        HANDLE hPipe;
        char buffer[1024];
        DWORD dwRead;
    
    
        hPipe = CreateNamedPipe(TEXT("\\\\.\\pipe\\Pipe"),
                                PIPE_ACCESS_DUPLEX,
                                PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,   // FILE_FLAG_FIRST_PIPE_INSTANCE is not needed but forces CreateNamedPipe(..) to fail if the pipe already exists...
                                1,
                                1024 * 16,
                                1024 * 16,
                                NMPWAIT_USE_DEFAULT_WAIT,
                                NULL);
        while (hPipe != INVALID_HANDLE_VALUE)
        {
            if (ConnectNamedPipe(hPipe, NULL) != FALSE)   // wait for someone to connect to the pipe
            {
                while (ReadFile(hPipe, buffer, sizeof(buffer) - 1, &dwRead, NULL) != FALSE)
                {
                    /* add terminating zero */
                    buffer[dwRead] = '\0';
    
                    /* do something with data in buffer */
                    printf("%s", buffer);
                }
            }
    
            DisconnectNamedPipe(hPipe);
        }
    
        return 0;
    }
    

    这是客户端代码:

    int main(void)
    {
        HANDLE hPipe;
        DWORD dwWritten;
    
    
        hPipe = CreateFile(TEXT("\\\\.\\pipe\\Pipe"), 
                           GENERIC_READ | GENERIC_WRITE, 
                           0,
                           NULL,
                           OPEN_EXISTING,
                           0,
                           NULL);
        if (hPipe != INVALID_HANDLE_VALUE)
        {
            WriteFile(hPipe,
                      "Hello Pipe\n",
                      12,   // = length of string + terminating '\0' !!!
                      &dwWritten,
                      NULL);
    
            CloseHandle(hPipe);
        }
    
        return (0);
    }
    

    您应该将管道名称TEXT("\\\\.\\pipe\\Pipe") 替换为位于常用头文件中的#define。

    【讨论】:

    • 我收到一个错误,FILE_FLAG_FIRST_PIPE_INSTANCE 在哪里:'FILE_FLAG_FIRST_PIPE_INSTANCE' 未在此范围内声明,但我在 msdn 上阅读过,这里应该没有任何错误。
    • 在第一个客户端之后,服务器没有读取任何其他消息,为什么他不能先通过?
    • @user3052078 我做了一些更改,现在如果客户端再次运行,它可以工作。进一步注意,如果您从客户端发送多条消息,服务器可能会使用一个 ReadFile(..) 读取数据(= 客户端 5x WriteFile!= 服务器 5x ReadFile)。因此,如果客户端发送的字符串包含 '\0' 字符,则本示例中的简单 printf("%s", buffer); 将不起作用,因为 printf 在第一个 '\0' 处停止。
    • CreateFile 在失败时返回 INVALID_HANDLE_VALUE。还有INVALID_HANDLE_VALUE != NULL.
    • 我迟到了,但如果CreateNamedPipe 成功,外循环将永远不会退出。即使在调用DisconnectNamedPipe 之后,hPipe 的值也没有改变。尽管如此,它仍然是人们可以使用的一个很好的例子。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多