如何判断其他应用是否已注册IPC Remoting频道?

所以我有一个提供.NET API的应用程序。 他们的API库通过.NET远程调用与他们的主应用程序通信。 要使用API​​,应用程序必须已启动并运行。

所以,我有一个实例,我需要以编程方式启动应用程序,然后实例化一个API对象,它试图打开一个IPC远程通道到主应用程序。 问题是,在我开始这个过程之后,启动和应用程序注册通道之间有几秒钟的时间。 如果我在注册频道之前尝试实例化一个API对象,它就会发出exception。

我对.NET远程处理知之甚少并没有帮助。

如果他的应用程序已经注册了通信通道,我如何从我的应用程序确定使用他们的API,所以我知道可以实例化他们的API对象?

试试这个:

using System.Net.NetworkInformation; using System.Net; private static bool IsPortAvailable(int port) { IPGlobalProperties globalProperties = IPGlobalProperties.GetIPGlobalProperties(); IPEndPoint[] activeListeners = globalProperties.GetActiveTcpListeners(); if (activeListeners.Any(conn => conn.Port == port)) { return true; } return false; } 

传入端口,你应该得到一个值,表明该端口上是否有一个监听器。希望这有帮助

只是为了开箱即用,您是否考虑过将WCF与MSMQ一起使用? 我不确定我是否完全理解您的架构,但听起来API的客户端必须启动另一个承载API的进程。 启动API主机和客户端尝试拨打电话之间可能存在时间问题。 微软最近将.NET Remoting(以及其他所有其他通信技术,如ASMX Web服务)弃用为遗产,并强烈建议开发人员迁移到WCF平台。

如果您将WCF与MSMQ一起使用,那么您应该没有时间问题。 无论API主机是否正在运行,您的客户端应用程序都可以将消息丢弃到持久队列中。 API主机可以随时启动,它将接收并处理队列中等待的任何消息。 即使您仍然让客户端应用程序启动API主机,时间问题也不再是问题,因为您使用排队来传输消息而不是.NET Remoting。 WCF为MSMQ提供了一个漂亮,方便,易用的包装器,因此进入门槛相对较低。

使用WCF over .NET Remoting的另一个好处是,您可以轻松地将API主机移动到不同的物理服务器,而无需更改客户端应用程序。 如果您愿意,您甚至可以移动到不同的排队平台(例如AMQP上的RabbitMQ),而无需更改客户端或API主机应用程序。 WCF为您处理所有这些交互,在您的客户端应用程序和API主机之间提供更清晰的解耦和更可靠的通信。

如果不能选择移动到WCF,则应该能够使用.NET Remoting显式设置端口。 我不确定您是如何配置API主机的,但任何给定的远程对象的URL通常采用以下forms:

 tcp://[:]/ 

如果添加端口,那么您应该能够使用Abhijeet的解决方案来确定端口是否打开。 您不会获得WCF的松散耦合和可靠的通信优势,但肯定会减少工作量。 ;)

您是否考虑过将实例化API对象的尝试包装到try-catch块中? 然后,您可以分析exception并查看它是否是由服务器未侦听引起的。 如果是的话,你可以等待并重试。

说得通?

只是代码中的一个小错字。 更正如下:

 using System.Net.NetworkInformation; using System.Net; private static bool IsPortAvailable(int port) { IPGlobalProperties globalProperties = IPGlobalProperties.GetIPGlobalProperties(); IPEndPoint[] activeListeners = globalProperties.GetActiveTcpListeners(); if (activeListeners.Any(conn => conn.Port == port)) { return true; } return false; } 

当您注册IpcServerChannel时,它会使命名管道与您为IpcServerChannel选择的端口名称进行通信。 您可以查看命名管道列表以查看您的端口名称是否存在。

 System.IO.Directory.GetFiles(@"\\.\pipe\").Any((path) => path.Contains(@"\\.\pipe\" + pipeName));