检查 NamedPipeServerStream 是否在客户端启动的方法

Way to check if NamedPipeServerStream started in Client side

我有一个使用 NamedPipeClientStream 的客户端和一个使用 NamedPipeServerStream 的服务器。

客户端可能在服务器之前启动,当它调用 clientStream.Connect(timeout) 时,我会按预期得到 TimeoutException。

有什么方法可以在调用 Connect 之前检查是否有 NamedPipeServerStream 监听以防止异常?

我建议您应该使用 EventWaitHandle。在所有客户端上,调用 WaitOne(),在服务器上打开流后,调用 Set()。

所以,在"server"这边,这样写:

EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.ManualReset, String.Format(@"Global\{0}", "SERVER_OPENED_HANDLE"));

OpenStream (); // inside this method you would have code that opens your named pipe for incomming messages

// finally, signal that you are done

handle.Set ();

在客户端,这样写:

EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.ManualReset, String.Format(@"Global\{0}", "SERVER_OPENED_HANDLE"));

// here your thread will sleep until the server calls "Set"
handle.WaitOne ();

// then you can safelly connect to the server here

ConnectToServer ();

只有几种情况需要处理:

1) 无法在服务器上打开管道,因为已经有一个打开的同名管道(会抛出异常)。

2) 您成功打开了管道,您通知客户端您已准备就绪,但在那之后,一毫秒后,服务器由于某些意外原因崩溃,客户端无法访问服务器。

3) 用户权限问题

在所有这些情况下,您应该使用 try / catch 处理这些异常,通常情况下,如果一切顺利,此代码将确保客户端不会在服务器成功打开管道之前尝试连接。

无论如何,我建议使用更高级的技术通过命名管道制作 IPC,例如使用 WCF 甚至 .NET Remoting,除了事实上它被许多人(不包括我)认为已经过时之外,这是非常不错的至少对于 IPC 通信。这会给你自由和可扩展性(也许有一天你会需要你的客户端能够驻留在其他机器上,你将不得不从 IPC 切换到 LAN 通信甚至在 WAN / internet 中)。

无法仅使用 NamedPipeClientStream 进行检查。但是,您可以像这样使用 Mutex

// In the server
var mutex = new System.Threading.Mutex(false, "MyPipeMutex");
OpenPipeAndRunServer();
mutex.Close();

// In the client process    
var mutex = new System.Threading.Mutex(false, "MyPipeMutex");
if (!mutex.WaitOne(0, false))
{
    OpenPipe();
}
mutex.Close();

您可能希望将 Close 调用包装在 try-finally 块中以确保它始终关闭。在客户端中,您可以使用不同的超时时间来实际等待 NamedPipe 打开。

您也可以捕获异常作为变通方法。

如果五年后有人遇到这个问题,这可能会有所帮助:

var isPipeRunning = Directory.GetFiles( @"\.\pipe\" ).Contains( $"\.\pipe\{pipeName}" )