how to ping multiple ip adresses at the same time

1

I currently have code that gets a range of ip addresses (ex. 192.168.1.101 to 192.168.1.110) and pings them individually by using a for loop. the problem is that this takes too long, especially if the ping is unsuccessful. Is it a good idea to ping 10 ip addresses at the same time? I tried using a background worker and i am hesitating on using multiple background workers. This is my working code:

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;
    }
}
c#
asked on Stack Overflow Oct 14, 2015 by Gian Marco Te • edited Sep 9, 2019 by Mong Zhu

3 Answers

1

This is not possible. You can only ping at one IP each time. This is the same in CMD. You can't do ping 127.0.0.1 127.0.0.2 or with a ,.

A good idea is to - as some people suggested in the comments - use threading for it. There's no way to ping at multiple IPs in 1 ping 'command'.

answered on Stack Overflow Oct 14, 2015 by Joshua Bakker
1

I run a program that pings 15000 machines in the network with threading. Funny enough I hardly see any network traffic, eventhough it pings/checks 200 systems per second.

Be careful! DataTable is not thread safe. I wrote a seperate method to lock the DataTable for each update.

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);

        }
    }

The system itself will determine how many backgroundworkers it should start. It will queue all of them at once and then start handling them according to system performance.

answered on Stack Overflow Oct 14, 2015 by Rahvin47
0

To all who are encountering the same problem, I coded this (I used a Parallel.For loop):

 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;
            }
        }
answered on Stack Overflow Oct 15, 2015 by Gian Marco Te

User contributions licensed under CC BY-SA 3.0