我们有多个客户端通过命名管道连接到服务器。当客户端尝试连接到命名管道时,偶尔会看到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://docs.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可能。
是否存在允许我们执行上述操作的框架模式,支持任意数量的并行客户端并确保在服务器仍处于活动状态时永远不会删除命名管道?
那么,无论连接客户端的时间和数量如何,我们如何确保命名管道始终存在?
这对任何类型的网络服务器都是不可能的。甚至TCP / IP(在其上构建命名管道)具有有限的“积压”。即使您将积压修改为荒谬的金额,您仍然会受到服务器硬件的限制。
你能做的就是总是保持一定数量的听力调用(即WaitForConnectionAsync
),所以你总是会有很多听众,每次听完就开始新的听,就像你上一个代码的例子一样。你需要多次运行该代码,比如大约20个,所以你有很多听众。您所能做的就是尽量减少错过连接的可能性;你不能完全阻止它。