在C#中检查服务器是否可通过网络访问的快速方法

我有一个项目,我在多个服务器上点击一堆自定义Windows性能计数器并将它们聚合到一个数据库中。 如果服务器关闭,我想跳过它,继续我的一天。

目前我正在检查服务器是否存在,通过对共享中的DirectoryInfo进行检查,我必须在此过程中稍后查看,然后检查.Exists属性。这是我当前用于测试的代码片段:

 DirectoryInfo di = new DirectoryInfo(machine.Share_Path); if (!di.Exists) { log.Warn("Could not access " + machine.Name + "! Maybe its down?"); continue; // Skips to the next server in my loop where this snippet exists. } 

这有效,但它很慢。 di.Exists位平均需要大约68秒来完成其工作,理想情况下我需要在一秒钟内知道服务器是否可访问。 Ping也不是一个选项,因为服务器可以ping通但不能在我们的环境中“活动”。

我对.NET世界仍然很新鲜,所以我愿意接受人们可以提供的任何建议。

提前致谢。

-Weegee

Ping先,稍后提问

为什么不先ping,然后再做di.Exists如果得到回复?

这将使您在无法访问的情况下提前失败,并且不会浪费时间用于严重损坏的机器。

事实上,我之前已经成功使用过这种方法。

  • MSDN Ping文档

Paralellize

您拥有的另一个选项是对已知可用的服务器上的检查和操作进行并行化。

您可以使用Paralell.ForEach()方法,并使用线程安全队列和简单的使用者线程来执行所需的操作。 结合上面的检查方法,这可以缓解上/下检查的几乎所有瓶颈。


敲门

另一种方法是阻止所需的远程服务是否正在运行(通过直接命中其端口或通过使用WMI查询它)。

由于WMI几乎总是在计算机启动时运行,因此您的连接应该非常快,无论是成功还是失败。

我认为唯一能够在不依赖ping的情况下查看的“快速”方法是创建套接字,看看是否可以实际连接到您尝试访问的服务端口。

这将相当于telnet servername 135 ,看它是否已经启动。

特别…

  1. 创建.NET TCP套接字客户端( System.Net.Sockets.TcpClient
  2. 将BeginConnect()作为异步操作调用,以连接到目录存在的代码将使用的其中一个RPC端口上的相关服务器(TCP 135,139或445)。
  3. 如果您在X毫秒内没有收到回复,请调用Close()取消连接。

免责声明:我不知道这会对任何威胁/防火墙保护产生什么影响,可能会发现此类连接/断开连接没有数据发送活动作为威胁。

打开Socket到特定端口通常可以解决问题。 如果你真的希望它快,请确保在新套接字(Nagle算法)上设置NoDelay属性,这样就没有缓冲。

Fast在很大程度上取决于延迟,但这可能是我知道连接到端点的最快方式。 使用异步方法进行并行化非常简单。 您检查的速度在很大程度上取决于您的网络拓扑,但在1000台服务器的测试中(0-75ms之间的延迟)我已经能够在~30秒内获得连接状态。 根本不是科学数据,但应该给你这个想法。

此外,不要通过UNC文件共享执行此操作,因为如果服务器不再存在,您将有很多悬挂连接永远超时。 因此,如果您有许多服务器具有无效的DNS记录并且您尝试轮询它们,那么随着时间的推移,您将完全关闭Windows。 像File.Exists和任何文件访问之类的东西都会导致这种情况。

  • “Full-Blown”选项将安装一个监控工具,如SCOM(System Center Operations Manager),它有一个SDK,您可以使用它来查询SCOM(性能)和维护信息avout机器被监控。 可能是一座通往远方的桥梁……

  • Telnet是另一种选择。 尝试远程登录到目标计算机以查看它是否响应。

  • 创建一个在目标计算机上安装的小型Windows服务,让sys管理员在对目标计算机执行维护时停止它(只需使用批处理文件来net stop / net启动服务)