Search code examples
c++windowsipcnamed-pipesfifo

Create Windows named pipe in C++


I am trying to create a simple communication between 2 processes in C++ (Windows) like FIFO in Linux.

This is my server:

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;
}

And this is my client:

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;
}

The code doesn't work. How can I fix it to work like FIFO?


Solution

  • You cannot create a named pipe by calling CreateFile(..).

    Have a look at the pipe examples of the Microsoft Learn. Since these examples are quite complex I've quickly written a VERY simple named pipe server and client.

    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;
    }
    

    And here is the client code:

    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);
    }
    

    You should replace the name of the pipe TEXT("\\\\.\\pipe\\Pipe") by a #define which is located in a commonly used header file.