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

6

我的当前命名管道实现的代码如下:

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
}

如何正确地检测客户端断开连接?
4个回答

3

设置读取超时时间并在超时发生时轮询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();
}

谢谢,但是如果我故意不在管道中读取超过此超时时间的数据怎么办?我的管道大部分时间都是空闲的。 - clamp
1
我建议使用一个工作线程来轮询您的管道的生命周期中的IsConnected。也许将其全部封装在一个专用类中。更新的答案。 - Gusdor

2

如果您的管道(远程)已经被破坏,一种简单的方法是始终使用异步读取而不是同步读取,并始终至少提交一个异步读取。也就是说,对于每个成功的读取,您会获得另一个异步读取,无论您是否打算进行另一个读取。如果您关闭了管道或远程端关闭了它,则会看到异步读取完成,但读取大小为null。您可以使用此来检测管道断开连接。不幸的是,管道仍将显示IsConnected,您仍需要手动关闭它,但它确实允许您检测何时出现问题。


我不会使用计时器。 - eric frazer

1

在同步调用的情况下,您可以通过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

你可能会注意到即使在微软的官方Illustration(更确切地说是在StreamString类中),也没有进行此检查:
不要忘记投票支持这个答案并访问我的YouTube频道了解更多信息。更多信息请查看我的个人资料。
祝好!

1

在使用WriteByte()Write()写入管道后,使用WaitForPipeDrain()方法,并捕获异常,异常信息为 "Pipe is Broken"。

您可能需要将其放在while循环中,并继续向管道中写入数据。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接