I'm trying to write in a named pipe and read back the same thing. Consider the following code snippet (the error handling is stripped for brevity):
const char * pipeName = "\\\\.\\pipe\\pipe";
const char * buffWrite = "SOME TEXT";
unsigned buffLength = strlen(buffWrite);
char buffRead[1024];
DWORD nWritten, nRead;
HANDLE hPipe = CreateNamedPipe(pipeName,
PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 1024, 1024, 0, 0);
HANDLE hFile = CreateFile(pipeName, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
WriteFile(hFile, buffWrite, buffLength, &nWritten, 0);
CloseHandle(hFile);
//the next line fails with >>All pipe instances are busy.<<
hFile = CreateFile(pipeName, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
ReadFile(hFile, buffRead, buffLength, &nRead, 0);
...
However when I try reopen the pipe for reading the CreateFile call fails with "All pipes are busy."
What am I missing here?
EDIT. Peeking works fine, i.e.
DWORD nRead, nTotal, nLeft;
PeekNamedPipe(hPipe, buffRead, buffLength, &nRead, &nTotal, &nLeft);
returns the written data correctly.
REMARK. This is a proof of concept for something larger. No new threads and processes will be involved.
The reason you're getting that specific error code is that you only created one instance of the named pipe, and you've already used it. (You can create a new instance by calling CreateNamedPipe
a second time, or you can reuse an existing instance by calling DisconnectNamedPipe
.)
However, based on your commentary, I believe you want the call to ReadFile to retrieve the data written by the call to WriteFile, i.e., you want the same instance of the pipe, not a new one.
To do that, do not open a new handle. Use the existing handle, hPipe
.
(Note that each pipe instance has two ends; a server end and a client end. The handle from CreateNamedPipe is always to the server end, and the handle from CreateFile is always to the client end. Data written to the server end can only be read from the client end, and vice-versa.)
You are trying to use named pipe as some kind of buffer - client connects to it, puts some data, then disconnects, after that other client connects and retrieves this data. This is invalid approach, named pipe is just that - a pipe, it has two sides - server side and client side, server and client could communicate through it. Usual pipe usage scenario:
CreateNamedPipe
function;ConnectNamedPipe
method;CreateFile
API call;ReadFile/WriteFile
;DisconnectNamedPipe
and could be reactivated again with ConnectNamedPipe
.You could see complete example in the MSDN here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With