检查多台机器上的开放端口

时间:2009-11-17 10:01:46

标签: c# multithreading

我有一个程序从数据库中提取一个ip地址列表,总共大约3000个。每个地址都与一台远程计算机有关,该计算机应该运行我的应用程序作为客户端的.NET Remoting服务器。我需要连接到每个通过.Net Remoting撤回一些数据。但是,如果远程站点存在某种问题,则需要等待很长时间才能返回该程序。

我研究过并发现在使用套接字尝试.Net Remoting连接之前,我可以检查.Net Remoting端口。此外,使用异步Socket.BeginConnect方法,我可以超时在指定的超时期限内不返回的任何连接。当我一次检查一个IP地址但是对于X个地址时,这很有效,这可能需要(X *超时)时间来完成。所以我的下一步是引入一个线程池,这样我就可以同时检查多个站点:

我为循环中的每个ip创建一个OpenPortChecker对象,为它提供一个ManualResetEvent和ip,然后在线程池中将其排队。一旦将所有内容添加到池中,我等待所有线程完成,方法是遍历ManualResetEvents列表并在每个上调用WaitOne()。 OpenPortChecker包含一个方法,该方法对上面详述的指定ip执行定时Socket.BeginConnect调用,然后调用ManualResetEvent.Set()以在完成时发出信号。

然而这并不像我预期的那样工作:如果我不限制线程池大小,所有连接都会因超时而失败(即使我知道它们可用)并且最终程序因为创建了太多线程而失败。事实上,我可以看到任务管理器中的线程数量上升和上升,即使每个线程在返回池之前应该只在指定的超时时间内生存。这可以通过限制线程池大小来解决,但随后时间问题重新发挥作用。此外,除非我使用severley限制池(大约10个线程)并将超时设置为20秒,否则没有任何连接成功。然后,这成为线程数和超时时间之间的平衡行为,这似乎是错误的,并且可能根据运行的机器而波动。事实上,如果它比一次检查一个地址更好是有争议的。

我可以立即制作连接数量吗?我在某处做错了吗?有更好的方法吗?任何帮助将不胜感激。

谢谢,

詹姆斯

4 个答案:

答案 0 :(得分:1)

似乎你有tcpip.sys“半开连接”限制。 如果你有这些操作系统之一,你有这个限制:

  • Windows XP Service Pack 2/3
  • Windows 2003 Service Pack 1及更高版本
  • 没有Service Pack或Service Pack 1的Windows Vista / 2008。
  • 早于RTM的Windows 7。

绕过此限制:

  • 在Windows XP / 2003上 - 安装第三方补丁 - http://www.lvllord.de
  • 在Windows Vista / 2008上 - 安装Service Pack 2
  • 在Windows 7上 - 安装RTM版本。

答案 1 :(得分:0)

据我所知,当远程站点没有应答时,远程站点拒绝连接以及由于某种传出连接配额而无法建立连接时,错误会有所不同。请记住,简单的网络接口拥塞可能是罪魁祸首,而不是任何类型的配额。

答案 2 :(得分:0)

c#中是否可以使用非阻塞i / o?然后使用一个线程,您可以启动多次连接尝试,并在成功或超时时获得回叫。

答案 3 :(得分:0)

感谢您的回复。我现在已经解决了这个问题,所以如果其他人遇到类似的问题,我想发帖分享我的答案。正如Kieran Benton指出的那样,XP允许的连接数限制为10(cmd:net config server),所以我限制了我的程序一次只能运行10个线程(尽管这仍然存在一个问题,即用户可能已经在使用某些连接配额)。接下来,使用Robert Obryk提供的信息,我对Remoting连接做了一些研究,发现在通过以下方式进行远程连接时确实可以设置超时:

IDictionary prop = ChannelServices.GetChannelSinkProperties(remObject);
prop["timeout"] = remotingTimeout;

此时,我删除了初始定时Socket连接,因为它似乎不再需要,但是测试显示Remoting超时仅在通过指定端口可以访问远程机器时才有效。如果端口已关闭,则忽略超时并挂起连接。因此,我的最终实现涉及定时Socket连接,首先检查端口是否打开,然后尝试对响应式站点进行定时远程调用。有点长的啰嗦但是有效!

再次感谢,

詹姆斯