1

我正在构建一个使用 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) - 一切正常。我确定我正在做的是一个角落案例,但我相信管道应该能够以优雅的方式处理这个问题。

关于什么可能是错误的任何想法?

谢谢!

4

1 回答 1

2

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

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

服务器在 BeginWaitForConnection 失败

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

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

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

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

于 2013-09-16T11:27:38.100 回答