C++: Implementing Named Pipes using the Win32 API
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
.
Mike Pateras
Young developer, interested in gaming and game development, along with many other things.
Updated on August 02, 2020Comments
-
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!