I'm learning about named pipes and was playing with the named pipe client and server examples from the MSDN doc:
Named Pipe Server
Named Pipe Client
I modified the client so I can type in messages to the console and have them sent to the server where it displays the message and sends back a reply. Essentially I added a loop which starts after the SetNamedPipeHandleState() call and ends before the CloseHandle() call (i.e. the open and close happen outside the loop, so I am using the same pipe handle within the loop).
My question is, if I kill the client (by closing it or ending it via Task Manager) is there any way for the server side to detect the disconnect?
I've tried using GetNamedPipeHandleState() hoping it return failure and a call to GetLastError() would return ERROR_PIPE_NOT_CONNECTED, but that was not the case. Because of the way this server is set up I had to do this in the CompletedReadRoutine function and create a "controlled" failure. What I did was, with a breakpoint on the CompletedReadRoutine in the server:
The call to GetNamedPipeHandleState() returns successfully so I never got to do the GetLastError() call. When it gets to the WriteFileEx call it fails and a call to GetLastError at that point returns an ERROR_NO_DATA.
Looking at the pipe functions I can't see anything else that would possibly help here. I am missing something or is a client disconnect just not detectable.
The only other thing I can think of is collecting the pid's of the connecting clients (via GetNamedPipeClientProcessId) and spinning off watchdog threads to check if they are still alive. Though, just thinking about doing that sets off my spidey sense.
Is there a way to detect disconnected clients when using named pipes?
Doesn't ReadFile()
return and error and GetLastError()
then return ERROR_BROKEN_PIPE
?
ReadFile()
+ GetLastError()
do the job well. Here is how they can be used with I/O Completion Ports (my implementation is in python+ctypes, but the idea should be clear):
def connect():
GetQueuedCompletionStatus()
receive()
def receive():
while True:
ret_code = ReadFile()
if ret_code == 0 and GetLastError() == ERROR_BROKEN_PIPE:
# client disconnected
GetQueuedCompletionStatus()
We are waiting for a completion packet, and when a client connects, we switch to the main loop. In the main loop we read the pipe and check if the client has disconnected by looking at ReadFile()
return code and GetLastError()
. Then again, we will wait for a completion packet.
A client can disconnect on any stage. Completion packet will be queued and we will get ERROR_BROKEN_PIPE
.
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