所以我有一个提供.NET API的应用程序。他们的API库通过.NET远程调用与他们的主应用程序通信。为了使用API,应用程序必须已经启动并运行。
所以,我有一个实例,我需要以编程方式启动应用程序,然后实例化一个API对象,它试图打开一个IPC远程通道到主应用程序。问题是,在我开始这个过程之后,启动和应用程序注册通道之间会有几秒钟的时间。如果我在注册频道之前尝试实例化一个API对象,那么就会发出异常信号。
我对.NET远程处理知之甚少没有帮助。
如果他的应用程序已经注册了通信通道,我如何从我的应用程序确定使用他们的API,所以我知道可以实例化他们的API对象?
答案 0 :(得分:2)
试试这个:
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;
}
传入端口,你应该得到一个值,表明该端口上是否有监听器。希望这有帮助
答案 1 :(得分:0)
只是为了开箱即用,您是否考虑过将WCF与MSMQ一起使用?我不确定我是否完全理解您的体系结构,但听起来API的客户端必须启动另一个承载API的进程。启动API主机和客户端尝试拨打电话之间可能存在时间问题。微软最近将.NET Remoting(以及其他所有其他通信技术,如ASMX Web服务)弃用为遗产,并强烈建议开发人员迁移到WCF平台。
如果您将WCF与MSMQ一起使用,那么您应该没有时间问题。无论API主机是否正在运行,您的客户端应用程序都可以将消息丢弃到持久队列中。 API主机可以随时启动,它将接收并处理队列中等待的任何消息。即使您仍然让客户端应用程序启动API主机,时间问题也不再是问题,因为您使用排队来传输消息而不是.NET Remoting。 WCF为MSMQ提供了一个漂亮,方便,易用的包装器,因此进入门槛相对较低。
在.NET Remoting上使用WCF的另一个好处是,您可以轻松地将API主机移动到其他物理服务器,而无需更改客户端应用程序。如果您愿意,您甚至可以移动到不同的排队平台(例如AMQP上的RabbitMQ),而无需更改客户端或API主机应用程序。 WCF为您处理所有这些交互,在您的客户端应用程序和API主机之间提供更清晰的解耦和更可靠的通信。
如果不能选择移动到WCF,则应该能够使用.NET Remoting显式设置端口。我不确定您是如何配置API主机的,但任何给定的远程对象的URL通常采用以下形式:
tcp://<hostname>[:<port>]/<object>
如果您添加端口,那么您应该能够使用Abhijeet的解决方案来确定端口是否打开。您不会获得WCF的松散耦合和可靠的通信优势,但肯定会减少工作量。 ;)
答案 2 :(得分:0)
您是否考虑过将实例化API对象的尝试包装到try-catch块中?然后,您可以分析异常并查看它是否是由服务器未侦听引起的。如果是的话,你可以等待并重试。
有道理吗?
答案 3 :(得分:0)
代码中只是一个小错字。 更正如下:
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;
}
答案 4 :(得分:0)
当您注册IpcServerChannel时,它会使命名管道与您为IpcServerChannel选择的端口名称进行通信。您可以查看命名管道列表以查看您的端口名称是否存在。
System.IO.Directory.GetFiles(@"\\.\pipe\").Any((path) => path.Contains(@"\\.\pipe\" + pipeName));