使用线程池的端口扫描

问题描述:

我想运行一个小应用程序,扫描端口并检查它们是否打开使用并使用线程池实践。控制台窗口会询问一个数字并扫描从1到X的端口,并显示每个端口是否打开或关闭。我的问题是,当它通过每个端口时,它有时会过早停止。它不止于一个数字,它非常随意。例如,它指定200.控制台将滚动通过每个端口,然后停在110.下一次我运行它,它停在80.使用线程池的端口扫描

代码 遗漏了一些事情,假设所有变量声明在哪里他们应该。第一部分在Main。

static void Main(string[] args) 
    { 
     string portNum; 
     int convertedNum; 
     Console.WriteLine("Scanning ports 1-X"); 
     portNum = Console.ReadLine(); 
     convertedNum = Convert.ToInt32(portNum); 
     try 
     { 
      for (int i = 1; i <= convertedNum; i++) 
      { 
       ThreadPool.QueueUserWorkItem(scanPort, i); 
       Thread.Sleep(100); 

      } 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine("exception " + e); 
     } 
    } 

    static void scanPort(object o) 
    { 
     TcpClient scanner = new TcpClient(); 
     try 
     { 
      scanner.Connect("127.0.0.1",(int)o); 
      Console.WriteLine("Port {0} open", o); 
     } 
     catch 
     { 
      Console.WriteLine("Port {0} closed",o); 
     } 
    } 

} 
+3

告诉我们一些代码 – unbeli 2010-06-11 15:26:48

+0

第二@unbeli。 – 2010-06-11 17:22:50

+0

@thenry用你评论中的代码编辑你的文章....如果有格式化问题...问好,我敢肯定有人会为你清理它。 – Rusty 2010-06-11 17:41:45

如果这是整个代码,那么该错误可能是由您刚刚经历到的main()末下降所致,而无需等待所有线程池中的线程来完成。 ThreadPool线程会在您的主线程在通过main()后退出时全部中止。 尝试删除Thread.Sleep(100)(不需要,这是错误的方式,你永远不会知道睡了多久,它部分地挫败了首先使用ThreadPool的目的),你甚至可能不会检查一个单一的端口!

相反,您可以让每个工作线程设置一个事件并使用主要的WaitAll来完成所有事件。一个例子见http://msdn.microsoft.com/en-us/library/3dasc8as.aspx

编辑: 通过在链接引用该解决方案思考这上面可能比​​您理想的选择较少,以及(可能涉及其分配的65000个事件的数组,这将是过度)。在.net 4中,您可以使用如下所示的CountdownEvent

对不起,我必须运行,但请检查此示例http://msdn.microsoft.com/en-us/library/system.threading.countdownevent.aspx并让我们知道您何时还有其他问题,我确定有人可以并将详细说明或建议更好解决方案和更适合.net3的解决方案

+0

它看起来像我本打在头上钉。如果你这样做了解更多关于线程的信息,你可能需要考虑使用SetMaxThreads()来明确地设置池中的最大线程。 MSDN表示默认值是池中的250个线程。对于某些类型的操作,使用更多或更少数量的并发线程可能会获得更好的性能。 – 2010-06-11 19:22:36

什么是操作系统?不要忘记,不同版本的XP有tcp连接限制,同时你也可能触发反DDOS保护。

此外,你的逻辑是有缺陷的。只是因为TcpClient.Connect例外,并不意味着该端口已关闭。您应该捕获并显示该异常的详细信息,因为我想它会让您更深入地了解代码停止的原因。请记住,它也可能抛出SocketException或SecurityException。

关于线程部分,您可以考虑使用任务并行库(TPL),而不是直接访问ThreadPool。它提供了一个更简单的使用和更直观/可读的语法。