2015-10-14 385 views
1

我目前有代碼獲取一系列ip地址(例如192.168.1.101到192.168.1.110),並通過使用for循環來單獨ping它們。問題是這需要太長時間,特別是如果ping不成功。同時ping 10個IP地址是個好主意嗎?我嘗試過使用後臺工作人員,並且對使用多個後臺工作人員猶豫不決。 這是我的工作代碼:c#如何在同一時間ping多個ip地址

private void btnPingRange_Click(object sender, EventArgs e) 
     { 
      Control.CheckForIllegalCrossThreadCalls = false; 
      backgroundWorker1.RunWorkerAsync(); 
      UpdateControls(true); 
     } 
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      UpdateControls(false); 
     } 
static uint str2ip(string ip) 
    { 
     string[] octets = ip.Split('.'); 

     uint x1 = (uint)(Convert.ToByte(octets[0]) << 24); 
     uint x2 = (uint)(Convert.ToByte(octets[1]) << 16); 
     uint x3 = (uint)(Convert.ToByte(octets[2]) << 8); 
     uint x4 = (uint)(Convert.ToByte(octets[3])); 

     return x1 + x2 + x3 + x4; 
    } 
    static string ip2str(uint ip) 
    { 
     string s1 = ((ip & 0xff000000) >> 24).ToString() + "."; 
     string s2 = ((ip & 0x00ff0000) >> 16).ToString() + "."; 
     string s3 = ((ip & 0x0000ff00) >> 8).ToString() + "."; 
     string s4 = (ip & 0x000000ff).ToString(); 

     string ip2 = s1 + s2 + s3 + s4; 
     return ip2; 
    } 
public string GetMacAddress(string ipAddress) 
     { 
      string macAddress = string.Empty; 
      System.Diagnostics.Process pProcess = new System.Diagnostics.Process(); 
      pProcess.StartInfo.FileName = "arp"; 
      pProcess.StartInfo.Arguments = "-a " + ipAddress; 
      pProcess.StartInfo.UseShellExecute = false; 
      pProcess.StartInfo.RedirectStandardOutput = true; 
      pProcess.StartInfo.CreateNoWindow = true; 
      pProcess.Start(); 
      string strOutput = pProcess.StandardOutput.ReadToEnd(); 
      string[] substrings = strOutput.Split('-'); 
      if (substrings.Length >= 8) 
      { 
       macAddress = substrings[3].Substring(Math.Max(0, substrings[3].Length - 2)) 
         + "-" + substrings[4] + "-" + substrings[5] + "-" + substrings[6] 
         + "-" + substrings[7] + "-" 
         + substrings[8].Substring(0, 2); 
       return macAddress; 
      } 

      else 
      { 
       return "not found"; 
      } 
     } 
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
    { 

     try 
     { 
      uint startIP = str2ip(txtFrom.Text); 
      uint endIP = str2ip(txtTo.Text); 
      DataTable pingResults = new DataTable(); 
      pingResults.Columns.Add("Date"); 
      pingResults.Columns.Add("IP Address"); 
      pingResults.Columns.Add("Mac Address"); 
      pingResults.Columns.Add("Result"); 
//slow part 
      for (uint currentIP = startIP; currentIP <= endIP; currentIP++) 
      { 
       string thisIP = ip2str(currentIP); 

       Ping ping = new Ping(); 
       PingReply pingReply = ping.Send(thisIP.ToString()); 


       var message = (pingReply.Status == IPStatus.Success) ? "On" : "Off"; 
       pingResults.Rows.Add(DateTime.Now.ToShortDateString(), thisIP.ToString(),GetMacAddress(thisIP), message.ToString()); 

      } 
      dataGridView1.DataSource = pingResults; 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.ToString()); 
     } 
    } 
    private void UpdateControls(bool isVisible) 
    { 
     if (isVisible) 
     { 
      panel1.Visible = true; 
      pictureBox1.Refresh(); 
      pictureBox2.Refresh(); 
      groupBox1.Enabled = false; 
      groupBox2.Enabled = false; 
     } 
     else 
     { 
      panel1.Visible = false; 
      groupBox1.Enabled = true; 
      groupBox2.Enabled = true; 
     } 
    } 
+0

每一個ping請求創建單獨的線程。 –

+0

@HarshitShrivastava如果我想ping整個網絡,啓動254個線程會好嗎? –

+0

也許是並聯循環? https://msdn.microsoft.com/en-us/library/ff963552.aspx –

回答

0

所有誰遇到同樣的問題,我這個編碼(我用的Parallel.For循環):

static uint str2ip(string ip) 
    { 
    //this converts the ip address from the textboxes to bytes 
    string[] octets = ip.Split('.'); 
    uint x1 = (uint)(Convert.ToByte(octets[0]) << 24); 
    uint x2 = (uint)(Convert.ToByte(octets[1]) << 16); 
    uint x3 = (uint)(Convert.ToByte(octets[2]) << 8); 
    uint x4 = (uint)(Convert.ToByte(octets[3])); 
    return x1 + x2 + x3 + x4; 
    } 
    private volatile DataTable pingResults = new DataTable(); 
    //And I use str2ip in the button click event which contains this: 
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
     { 
      try 
      { 
       pingResults.Clear(); 
       uint startIP = str2ip(txtFrom.Text); 
       uint endIP = str2ip(txtTo.Text); 
       Parallel.For(startIP, endIP, index => pingIpAddress(ip2str(startIP++))); 
       Thread.Sleep(1000); 
       //for (uint currentIP = startIP; currentIP <= endIP; currentIP++) 
         // { 
         //  string thisIP = ip2str(currentIP); 
         //  Thread myNewThread = new Thread(() => pingIpAddress(thisIP)); 
         //  myNewThread.Start(); 

         // } 
       dataGridView1.DataSource = pingResults; 

      } 
      catch (Exception ex) 
      { 
       MessageBox.Show(String.Format("Exception {0} Trace {1}", ex.Message, ex.StackTrace)); 
      } 
     } 
     private void pingIpAddress(string ip3) 
     {//this method is where I ping the IP addresses 
      try 
      { 
      string ip2 = ip3; 
      Ping ping = new Ping(); 
      PingReply pingReply = ping.Send(ip2.ToString()); 
      var message = (pingReply.Status == IPStatus.Success) ? "On" : "Off"; 
       lock (pingResults.Rows.SyncRoot) 
       { 
        AddToDataTable(ip2, message); 
       } 
      } 
      catch (Exception ex) 
      { 

       MessageBox.Show(String.Format("Exception {0} Trace {1}", ex.Message, ex.StackTrace)); 
      } 
     } 
     private void AddToDataTable(string ip2,string msg) 
     { 
      try 
      { 
       pingResults.Rows.Add(DateTime.Now.ToShortDateString(), ip2, GetMacAddress(ip2), msg.ToString(), GetMachineNameFromIPAddress(ip2)); 

      } 
      catch (Exception) 
      { 

       throw; 
      } 
     } 
1

這是不可能的。每次只能在一個IP上執行ping操作。這在CMD中是一樣的。你不能ping 127.0.0.1 127.0.0.2或使用a,。

一個好主意是 - 正如一些人在評論中提出的 - 使用線程代碼。沒有辦法在1個'命令'中ping多個IP。

+0

我知道我不能ping多個IP地址「在同一時間在1命令」這就是爲什麼我使用循環來檢查範圍內的每個IP,但它太慢.. –

+1

只需使用線程,就沒有辦法躲開它。這就是我所說的:-)它仍然是緩慢的,但不幸的是你無法避免它,所以我建議你只是忍受它。 –

1

我運行一個程序,在網絡中使用線程ping 15000臺機器。 有趣的是,我幾乎看不到任何網絡流量,儘管它每秒鐘ping /檢查200個系統。

小心! DataTable不是線程安全的。我編寫了一個獨立的方法來鎖定每個更新的DataTable。

public static void UpdateValue(DataRow dr, string property, object value) 
    { 
     Monitor.Enter(computerTable); 
     try 
     { 

      dr[property] = value; 

     } 
     catch 
     { 
      //Do something with errors 
     } 

     finally 
     { 

      Monitor.Exit(computerTable); 

     } 
    } 

系統本身將決定它應該啓動多少個背景工人。它會立即將所有這些隊列排隊,然後根據系統性能開始處理它們。