C# 命名管道,如何检测客户端断开连接

本文关键字:检测 客户端 连接 断开 何检测 管道 | 更新日期: 2023-09-27 18:30:58

我当前的命名管道实现如下所示:

while (true)
{
  byte[] data = new byte[256];                        
  int amount = pipe.Read(data, 0, data.Length);
  if (amount <= 0)
  {
      // i was expecting it to go here when a client disconnects but it doesnt
     break;
  }
  // do relevant stuff with the data
}

如何正确检测客户端何时断开连接?

C# 命名管道,如何检测客户端断开连接

设置读取超时并在发生超时时轮询NamedPipeClientStream.IsConnected标志。

读取

超时将导致在超时持续时间内处于空闲状态的读取引发InvalidOperationException

如果不读取,并且想要检测断开连接,请在管道连接的生存期内在工作线程上调用此方法。

while(pipe.IsConnected && !isPipeStopped) //use a flag so that you can manually stop this thread
{
    System.Threading.Thread.Current.Sleep(500);
}
if(!pipe.IsConnected)
{
    //pipe disconnected
    NotifyOfDisconnect();
}

判断管道是否已损坏(远程)的一种简单方法是始终使用异步读取而不是同步读取,并且始终异步提交至少一个读取。也就是说,对于您获得的每个成功读取,无论您是否打算读取另一个异步读取,都会发布另一个异步读取。如果关闭管道,或者远程端关闭管道,你将看到异步读取完成,但读取大小为空。您可以使用它来检测管道断开。不幸的是,管道仍然会显示IsConnected,我认为您仍然需要手动关闭它,但它确实可以让您检测何时出现问题。

在写入管道使用WaitForPipeDrain()方法(使用 WriteByte()Write() )并捕获异常"管道已损坏"。

您可能希望将其放在while循环中,并继续写入管道。

在同步调用的情况下,你跟踪 Stream 抽象类的 ReadByte 的 -1 返回,该返回由 NamedPipeServerStream 继承:

        var _pipeServer = new NamedPipeServerStream(PipeConst._PIPE_NAME, PipeDirection.InOut);
        int firstByte = _pipeServer.ReadByte();
        const int END_OF_STREAM = -1;
        if (firstByte == END_OF_STREAM)
        {
            return null;
        }

文档确实指出:

    //
    // Summary:
    //     Reads a byte from a pipe.
    //
    // Returns:
    //     The byte, cast to System.Int32, or -1 indicates the end of the stream (the pipe
    //     has been closed).
    public override int ReadByte();

只有在第一次读取失败后,您的 IsConnected 属性才会正确设置为 false:

_pipeServer.IsConnected

您可能会观察到,即使在Microsoft的官方插图(更准确地说是在 StreamString 类中)未执行此检查:

不要忘记投票支持这个答案并访问我的 Youtube 频道。有关我的个人资料的更多信息。

问候!