I use a named pipe and I want to reuse the same pipe on the server to allow connecting another client once the original client has disconnected. What I do is:
- server creates a pipe using
CreateNamedPipe
- server writes data using
WriteFile
, and retries doing so as long as errorERROR_PIPE_LISTENING
is returned (which is before any client is connected) - clients connects using
CreateFile
- client reads data
- client close pipe handle using
CloseHandle
- at this point server gets error
ERROR_NO_DATA
when it attemps to write more data - server disconnects the pipe using
DisconnectNamedPipe
, which I hoped should make it free again - server tries writing data, gets error
ERROR_PIPE_NOT_CONNECTED
, it retries doing so until there is no error - however, when new client connects, and attempts
CreateFile
on the pipe, it getsERROR_PIPE_BUSY
Hence, my question is: what other steps I need to do to disconnect client from the pipe properly so that a new client can connect?
Best Answer
The problem is that you've left out ConnectNamedPipe(), which should be always be called after CreateNamedPipe() or DisconnectNamedPipe() but before attempting any I/O.
If you don't want to block while waiting for a client to connect, you can create the pipe in asynchronous I/O mode, in which case the call to ConnectNamedPipe() requires an event object which will be set when a client connects. Alternatively, you can set PIPE_NOWAIT and call ConnectNamedPipe() periodically until it succeeds, but this is a legacy feature and its use is discouraged. (In most situations using an event object will also be significantly more efficient than polling.)
As you've discovered, Windows does allow you to get away without the call to ConnectNamedPipe() but since this behaviour is undocumented it should probably be avoided. Similarly, the fact that calling ConnectNamedPipe() without waiting for it to succeed resets the connection state of the pipe is undocumented and should not be depended upon.
As requested, here's some real-world code to demonstrate the use of the server end of a pipe. This code was taken from a GUI application, so it uses asynchronous I/O, but it should be noted that it only talks to one client at a time. (It could however be run in multiple threads with only minor modifications.)
(This code has been edited down from the original to remove extraneous logic. I haven't tried compiling the edited version, so there may be some minor problems.)