C++: Implementing Named Pipes using the Win32 API

23,932

Solution 1

You must use CreateNamedPipe() to create the server end of a named pipe. Be sure to specify a non-zero buffer size, zero (documented by MSDN as 'use system default buffer size') doesn't work. MSDN has decent samples for a multi-threaded client&server.

Solution 2

A named pipe client can open the named pipe with CreateFile -- but the named pipe server needs to use CreateNamedPipe to create the named pipe. After it's created the named pipe, the server uses ConnectNamedPipe to wait for a client to connect. Only after the client has connected should the server do a blocking read like your call to ReadFile.

Share:
23,932
Mike Pateras
Author by

Mike Pateras

Young developer, interested in gaming and game development, along with many other things.

Updated on August 02, 2020

Comments

  • Mike Pateras
    Mike Pateras almost 4 years

    I'm trying to implement named pipes in C++, but either my reader isn't reading anything, or my writer isn't writing anything (or both). Here's my reader:

    int main()
    {
        HANDLE pipe = CreateFile(GetPipeName(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
    
        char data[1024];
        DWORD numRead = 1;
    
        while (numRead >= 0)
        {
            ReadFile(pipe, data, 1024, &numRead, NULL);
    
            if (numRead > 0)
                cout << data;
        }
    
        return 0;
    }
    
    LPCWSTR GetPipeName()
    {
        return L"\\\\.\\pipe\\LogPipe";
    }
    

    And here's my writer:

    int main()
    {
        HANDLE pipe = CreateFile(GetPipeName(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
    
        string message = "Hi";
        WriteFile(pipe, message.c_str(), message.length() + 1, NULL, NULL); 
    
        return 0;
    }
    
    LPCWSTR GetPipeName()
    {
        return L"\\\\.\\pipe\\LogPipe";
    }
    

    Does that look right? numRead in the reader is always 0, for some reason, and it reads nothing but 1024 -54's (some weird I character).

    Solution:

    Reader (Server):

    while (true)
    {
        HANDLE pipe = CreateNamedPipe(GetPipeName(), PIPE_ACCESS_INBOUND | PIPE_ACCESS_OUTBOUND , PIPE_WAIT, 1, 1024, 1024, 120 * 1000, NULL);
    
        if (pipe == INVALID_HANDLE_VALUE)
        {
            cout << "Error: " << GetLastError();
        }
    
        char data[1024];
        DWORD numRead;
    
        ConnectNamedPipe(pipe, NULL);
    
        ReadFile(pipe, data, 1024, &numRead, NULL);
    
        if (numRead > 0)
            cout << data << endl;
    
        CloseHandle(pipe);
    }
    

    Writer (client):

    HANDLE pipe = CreateFile(GetPipeName(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
    
    if (pipe == INVALID_HANDLE_VALUE)
    {
        cout << "Error: " << GetLastError();
    }
    
    string message = "Hi";
    
    cout << message.length();
    
    DWORD numWritten;
    WriteFile(pipe, message.c_str(), message.length(), &numWritten, NULL); 
    
    return 0;
    

    The server blocks until it gets a connected client, reads what the client writes, and then sets itself up for a new connection, ad infinitum. Thanks for the help, all!