C#/.NET 保持命名管道打开并支持任意数量的并行连接客户端

标签 c# .net named-pipes

我们有多个客户端通过命名管道连接到服务器。有时,当客户端尝试连接到命名管道时,我们会看到 pipe/file not found 错误。我们的原始代码是

    while (!cancelToken.IsCancellationRequested)
    {
        // This creates a new NamedPipeServerStream
        var stream = PipeHelper.NewCurrentUserServerStream(PipeNames.Server, PipeTransmissionMode.Byte);
        await stream.WaitForConnectionAsync(cancelToken);

        Task.Run(() => HandleStreamAsync(stream).WithExceptionTrapper(LogNamedPipeException));

据我所知,应该创建一个 NamedPipeServerStream,然后调用 WaitForConnection,然后服务器应该处理请求。

但是,如果该请求几乎是瞬时的,或者客户端关闭了管道,那么在代码循环并创建新的服务器流之前,服务器流可能会关闭并且整个命名管道将消失.

那么我们如何确保命名管道在服务器的生命周期内存在,而不管连接客户端的时间和数量如何?

这里的代码https://learn.microsoft.com/en-us/dotnet/standard/io/how-to-use-named-pipes-for-network-interprocess-communication建议简单地使用多个线程是一种选择(在该示例中为 4 个)。然而,这似乎只降低了出错的可能性,并且有可能让客户端尝试在所有 4 个线程刚刚关闭服务器流并且命名管道消失的罕见间隙中进行连接。此外,它将并行执行限制为 4 个线程。

是否有一种机制允许我们打开一个允许任意数量的连接的命名管道服务器,为每个连接创建一个新的服务器流并且永远不会冒险关闭命名管道?

现在我们正在考虑这样做:

    var nextStream = PipeHelper.NewCurrentUserServerStream(PipeNames.Server, PipeTransmissionMode.Byte);
    while (!cancelToken.IsCancellationRequested)
    {
        try
        {
            await nextStream.WaitForConnectionAsync(cancelToken);
            var currentStream = nextStream;
            // Always have another stream ready so if the task is handled and finished 
            // really quickly theres no chance of the named pipe being removed altogether.
            nextStream = PipeHelper.NewCurrentUserServerStream(PipeNames.Server, PipeTransmissionMode.Byte);

            Task.Run(() => HandleStreamAsync(currentStream).WithExceptionTrapper(LogNamedPipeException));
        }

这基本上确保我们在开始处理第一个服务器流连接之前创建第二个服务器流,因此我们保证始终有一个事件的,并且我们在单独的任务上运行处理程序,因此我们应该启动另一个 WaitForConnection尽快。

是否存在允许我们执行上述操作的框架模式,支持任意数量的并行客户端并确保在服务器仍处于事件状态时永远不会删除命名管道?

最佳答案

So how do we ensure the named pipe always exists regardless of timing and number of connecting clients?

这对于任何类型的网络服务器都是不可能的。甚至 TCP/IP(在其上构建命名管道)也有有限的“积压”。即使您将 backlog 修改到一个荒谬的数量,您仍然会受到服务器硬件的限制。

可以做的是始终保持一定数量的监听调用(即,WaitForConnectionAsync),因此始终有大量的监听器在运行,每个完成后立即开始新的监听,就像您的上一个代码示例一样。您需要多次运行该代码,例如 20 次左右,这样您就有很多听众。您所能做的就是尽量减少丢失连接的机会;你无法完全阻止它。

关于C#/.NET 保持命名管道打开并支持任意数量的并行连接客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55165363/

相关文章:

c# - 这怎么能不相等呢?

.net - 在 NAnt 中,我可以创建 VS 项目中列出的文件的文件集吗?

c - 将数据提供给需要文件名的 C API

bash - 处理命名管道时,fish shell 和 bash 有什么区别?

C#:System.Windows.Controls.UserControl 作为列表框

c# - 如何在 WP 8.1 中获得软键盘下方的按钮?

c# - Firebase 远程配置 : Version condition is disabled for Unity projects

.net - 包管理器控制台不工作

.net - 如何测试我的 .NET 客户端正在使用哪个版本的 TLS?

perl - 制作一个运行24/7并从命名管道读取的Perl守护程序