2010-06-11 112 views
1

我想運行一個小應用程序,掃描端口並檢查它們是否打開使用並使用線程池實踐。控制檯窗口會詢問一個數字並掃描從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

回答

3

如果這是整個代碼,那麼該錯誤可能是由您剛剛經歷到的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

0

什麼是操作系統?不要忘記,不同版本的XP有tcp連接限制,同時你也可能觸發反DDOS保護。

此外,你的邏輯是有缺陷的。只是因爲TcpClient.Connect例外,並不意味着該端口已關閉。您應該捕獲並顯示該異常的詳細信息,因爲我想它會讓您更深入地瞭解代碼停止的原因。請記住,它也可能拋出SocketException或SecurityException。

0

關於線程部分,您可以考慮使用任務並行庫(TPL),而不是直接訪問ThreadPool。它提供了一個更簡單的使用和更直觀/可讀的語法。