当客户端除了快速连接-断开之外啥都不做时,命名管道会失败

Posted

技术标签:

【中文标题】当客户端除了快速连接-断开之外啥都不做时,命名管道会失败【英文标题】:Named pipes are failing when clients does nothing but quickly connect-disconnect当客户端除了快速连接-断开之外什么都不做时,命名管道会失败 【发布时间】:2013-09-16 09:29:43 【问题描述】:

我正在构建一个使用 IPC 命名管道的应用程序。 在开始编写压力测试时,我发现了一个与客户端快速连接断开相关的问题。

服务器代码:

static void ServerThread()

    var serverPipe = new NamedPipeServerStream("myipc", PipeDirection.InOut, -1, PipeTransmissionMode.Message, PipeOptions.Asynchronous | PipeOptions.WriteThrough);

    serverPipe.BeginWaitForConnection(
        ar =>
        
            var thisPipe = (NamedPipeServerStream)ar.AsyncState;
            thisPipe.EndWaitForConnection(ar);

            Task.Factory.StartNew(ServerThread);

            thisPipe.Dispose();
        ,
       serverPipe);

客户端只做如下连接-断开:

static void RunClients()

    for (int i = 0; i < 100; i++)
    
        var clientPipe = new NamedPipeClientStream(".", "myipc", PipeDirection.InOut, PipeOptions.Asynchronous | PipeOptions.WriteThrough);

        clientPipe.Connect(1000);
        clientPipe.Dispose();
    

当它运行时,其中一个客户端在 Connect() 中失败,而服务器在 BeginWaitForConnection 中失败 - 表示管道正在关闭。 如果我在每个客户端处理之前至少添加 Thread.Sleep(100) - 一切正常。 我确定我正在做的是一个角落案例,但我相信管道应该能够以优雅的方式处理这个问题。

对可能出现的问题有任何想法吗?

谢谢!

【问题讨论】:

您的管道是异步的,因此您在建立连接之前Dispose 您的管道。 我是在服务器端还是在客户端配置它?感谢您的提示!如何同步它们? 【参考方案1】:

其中一个客户端在 Connect() 中失败

因为服务器在连接后立即处理管道。

服务器在 BeginWaitForConnection 中失败

因为客户端在连接后立即处理管道。

我相信管道应该能够以优雅的方式处理这个问题。

确实如此,它优雅地抛出异常,让您的代码知道发生了异常情况。您似乎认为代码关闭管道而不做任何事情让另一端知道管道即将消失是正常的。这是不正常的,是异常的。因此,您会收到一个异常通知。

您可以使用 try/catch 捕获异常。您可以在 catch 处理程序中做两件事。您可以假设代码可以随意关闭管道,在这种情况下,您除了关闭管道的末端并离开之外什么都不做。或者你可以假设发生了一些非常糟糕的事情,因为管道的另一端没有很好地告别。这对于区分糟糕的事故非常重要,例如管道客户端或服务器崩溃。您可以选择自己喜欢的方式,但我强烈建议不要忽略糟糕的场景,它确实会发生并且将会发生。您刚刚为此类事故创建了一个很好的模拟。

【讨论】:

有趣的是我试图在服务器上删除 Dispose() ,但它没有帮助。问题出在客户端的 Dispose() 调用中。我假设在 Connect() 完成后,我应该能够立即使用管道做所有事情 - 甚至 Dispose() 它,但似乎并非如此......最终我决定在 Connect() 之后写入一个字节并阅读它在服务器上。在这种情况下,一切似乎都很好。

以上是关于当客户端除了快速连接-断开之外啥都不做时,命名管道会失败的主要内容,如果未能解决你的问题,请参考以下文章

Sencha Touch 2 谷歌地图啥都不做

命名管道:服务器端如何知道客户端已断开连接?

GIT push 命令啥都不做 - 命令在 1 秒内完成

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

检测命名管道与 I/O 完成断开连接

当阅读器断开连接时,命名管道 (FIFO) 数据会去哪里?