c#如何同时ping多个ip地址

时间:2015-10-14 07:36:50

标签: c#

我目前有代码获取一系列IP地址(例如192.168.1.101到192.168.1.110)并使用for循环单独ping它们。问题是这需要太长时间,特别是如果ping不成功。同时ping 10个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;
        }
    }

3 个答案:

答案 0 :(得分:1)

这是不可能的。您每次只能ping一个IP。在CMD中也是如此。您无法ping 127.0.0.1 127.0.0.2或使用,。

一个好主意是 - 正如一些人在评论中建议的那样 - 使用线程。在1 ping&#39;命令中没有办法ping多个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);

        }
    }

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

答案 2 :(得分: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;
            }
        }