2015-10-14 71 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); 

     } 
    } 

系统本身将决定它应该启动多少个背景工人。它会立即将所有这些队列排队,然后根据系统性能开始处理它们。