我正在学习命名管道,并且正在使用来自MSDN doc的命名管道客户端和服务器示例:
我修改了客户端,因此我可以向控制台输入消息,并将它们发送到显示消息的服务器并发回回复。本质上我添加了一个循环,它在SetNamedPipeHandleState()调用之后开始,并在CloseHandle()调用之前结束(即,在循环外发生打开和关闭,所以我在循环中使用相同的管道句柄。)
我的问题是,如果我终止客户端(通过关闭它或通过任务管理器结束它),服务器端是否有办法检测断开连接?
我尝试使用GetNamedPipeHandleState()希望它返回失败,并且对GetLastError()的调用将返回ERROR_PIPE_NOT_CONNECTED,但事实并非如此。由于设置此服务器的方式,我必须在CompletedReadRoutine函数中执行此操作并创建“受控”故障。我做的是,在服务器的CompletedReadRoutine上有一个断点:
对GetNamedPipeHandleState()的调用成功返回,因此我从未进行过GetLastError()调用。当它到达WriteFileEx调用时它失败并且在那一点上对GetLastError的调用返回ERROR_NO_DATA。
查看管道功能,我看不到任何可能有用的东西。我遗失了一些东西,或者客户端断开连接只是检测不到。
我能想到的另一件事就是收集连接客户端的pid(通过GetNamedPipeClientProcessId)并关闭看门狗线程以检查它们是否还活着。但是,只是考虑这样做会引发我的狡猾感。
使用命名管道时有没有办法检测断开连接的客户端?
答案 0 :(得分:5)
ReadFile()
不会返回错误而GetLastError()
会返回ERROR_BROKEN_PIPE
吗?
答案 1 :(得分:1)
ReadFile()
+ GetLastError()
做得很好。以下是它们如何与I / O完成端口一起使用(我的实现是在python + ctypes中,但这个想法应该是清楚的):
def connect():
GetQueuedCompletionStatus()
receive()
def receive():
while True:
ret_code = ReadFile()
if ret_code == 0 and GetLastError() == ERROR_BROKEN_PIPE:
# client disconnected
GetQueuedCompletionStatus()
我们正在等待完成数据包,当客户端连接时,我们切换到主循环。在主循环中,我们通过查看ReadFile()
返回码和GetLastError()
来读取管道并检查客户端是否已断开连接。然后,我们将等待完成数据包。
客户端可以在任何阶段断开连接。完成数据包将排队,我们将获得ERROR_BROKEN_PIPE
。