如何使用命名管道客户端/服务器检测客户端断开连接?

发布于 2024-08-23 07:37:27 字数 1162 浏览 8 评论 0原文

我正在学习命名管道,并正在使用 MSDN 文档中的命名管道客户端和服务器示例:

命名管道服务器

命名管道客户端

我修改了客户端,以便可以在控制台中输入消息,并将它们发送到服务器,在服务器上显示消息并发回回复。本质上,我添加了一个循环,该循环在 SetNamedPipeHandleState() 调用之后开始,在 CloseHandle() 调用之前结束(即打开和关闭发生在循环外部,因此我在循环内使用相同的管道句柄)。

我的问题是,如果我杀死客户端(通过关闭客户端或通过任务管理器结束它),服务器端是否有任何方法可以检测到断开连接?

我尝试使用 GetNamedPipeHandleState() 希望它返回失败,并且调用 GetLastError() 将返回 ERROR_PIPE_NOT_CONNECTED,但事实并非如此。由于该服务器的设置方式,我必须在 CompletedReadRoutine 函数中执行此操作并创建“受控”故障。我所做的是,在服务器中的 CompletedReadRoutine 上设置断点:

  1. 启动服务器
  2. 启动客户端
  3. 通过客户端发送消息(在此处命中服务器中的断点)
  4. 杀死客户端
  5. 单步执行到 GetNamedPipeHandleState

对 GetNamedPipeHandleState() 的调用返回成功,所以我永远不需要执行 GetLastError() 调用。当它到达 WriteFileEx 调用时,它失败并且此时对 GetLastError 的调用返回 ERROR_NO_DATA。

看看管道函数,我看不到任何其他可能有帮助的东西。我丢失了一些东西,或者客户端断开连接无法检测到。

我唯一能想到的另一件事是收集连接客户端的 pid(通过 GetNamedPipeClientProcessId)并分离看门狗线程以检查它们是否仍然存在。不过,光是想到这么做就让我产生了一种蜘蛛侠般的感觉。

使用命名管道时有没有办法检测断开连接的客户端?

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:

  1. started the server
  2. started the client
  3. sent a message via the client (hits the breakpoint in the server here)
  4. killed the client
  5. Stepped through to the GetNamedPipeHandleState

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

云醉月微眠 2024-08-30 07:37:27

ReadFile() 不会返回错误,然后 GetLastError() 返回 ERROR_BROKEN_PIPE 吗?

Doesn't ReadFile() return and error and GetLastError() then return ERROR_BROKEN_PIPE?

困倦 2024-08-30 07:37:27

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文