Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Perform Multiple "Pings" in Parallel using C#

I am trying to calculate the average round-trip time for a collection of servers. In order to speed things up, I would like to perform the pings in parallel. I have written a function called AverageRoundtripTime() and it seems to work, however, since I don't know very much about multi-threading, I am wondering if what I've done is okay. Please take a look at my code and let me know if it's okay or if there's a better way to achieve what I want:

public void Main()
{
    // Collection of hosts.
    List<String> hosts = new List<String>();

    // Add 100 hosts to the collection.
    for (Int32 i = 0; i < 100; ++i) hosts.Add("www.google.com");

    // Display the average round-trip time for 100 hosts.
    Console.WriteLine(AverageRoundtripTime(hosts));

}

public Double AverageRoundtripTime(IEnumerable<String> hosts)
{
    // Collection of threads.
    List<Thread> threads = new List<Thread>();

    // Collection of ping replies.
    List<PingReply> pingReplies = new List<PingReply>();

    // Loop through all host names.
    foreach (var host in hosts)
    {
        // Create a new thread.
        Thread thread = new Thread(() =>
        {
            // Variable to hold the ping reply.
            PingReply reply = null;

            // Create a new Ping object and make sure that it's 
            // disposed after we're finished with it.
            using (Ping ping = new Ping())
            {
                    reply = ping.Send(host);

            }

            // Get exclusive lock on the pingReplies collection.
            lock (pingReplies)
            {
                // Add the ping reply to the collection.
                pingReplies.Add(reply);

            }

        });

        // Add the newly created thread to the theads collection.
        threads.Add(thread);

        // Start the thread.
        thread.Start();

    }

    // Wait for all threads to complete
    foreach (Thread thread in threads)
    {
        thread.Join();

    }

    // Calculate and return the average round-trip time.
    return pingReplies.Average(x => x.RoundtripTime);

}

Update:

Check out a related question that I asked:

Task Parallel Library Code Freezes in a Windows Forms Application - Works fine as a Windows Console Application

like image 445
HydroPowerDeveloper Avatar asked Nov 15 '12 20:11

HydroPowerDeveloper


People also ask

How do you do multiple pings?

Use the command "ping 192.168. 1.101 -t" to initiate a continuous ping. Again, replace the IP address with one specific to your device as needed. The -t can be placed before or after the IP address.

How do I ping multiple IP addresses at once?

While the ping command is used to ping a single host device to identify its existence, ping sweep helps to ping multiple IP addresses simultaneously. It's a basic network scanning technique used to determine the range of active and inactive IP addresses available on the network.

How do I ping multiple servers at a time?

First, put all of your server names into a text file with each server name on a separate line. Let's call it "servers. txt" and save it (as you going to ping server names so make sure name resolution is happening).


2 Answers

use the Parallel.For and a ConcurrentBag

    static void Main(string[] args)
    {
        Console.WriteLine(AverageRoundTripTime("www.google.com", 100));
        Console.WriteLine(AverageRoundTripTime("www.stackoverflow.com", 100));
        Console.ReadKey();
    }

    static double AverageRoundTripTime(string host, int sampleSize)
    {
        ConcurrentBag<double> values = new ConcurrentBag<double>();
        Parallel.For(1, sampleSize, (x, y) => values.Add(Ping(host)));
        return values.Sum(x => x) / sampleSize;
    }
    static double Ping(string host)
    {
        var reply = new Ping().Send(host);
        if (reply != null)
            return reply.RoundtripTime;
        throw new Exception("denied");
    }
like image 75
agradl Avatar answered Oct 27 '22 18:10

agradl


The ping class has a method SendAsync. This follows the Event-based Asynchronous Programming (EAP) pattern. Check out this article: http://msdn.microsoft.com/en-us/library/ee622454.aspx.

For a quick example here is a method I have that implements that article in a very basic fashion. You can basically call this as many times as you want and all the pings will be done asychronously.

    class Program
    {
    public static string[] addresses = {"microsoft.com", "yahoo.com", "google.com"};
    static void Main(string[] args)
    {
        List<Task<PingReply>> pingTasks = new List<Task<PingReply>>();
        foreach (var address in addresses)
        {
            pingTasks.Add(PingAsync(address));
        }

        //Wait for all the tasks to complete
        Task.WaitAll(pingTasks.ToArray());

        //Now you can iterate over your list of pingTasks
        foreach (var pingTask in pingTasks)
        {
            //pingTask.Result is whatever type T was declared in PingAsync
            Console.WriteLine(pingTask.Result.RoundtripTime);
        }
        Console.ReadLine();
    }

    static Task<PingReply> PingAsync(string address)
    {
        var tcs = new TaskCompletionSource<PingReply>();
        Ping ping = new Ping();
        ping.PingCompleted += (obj, sender) =>
            {
                tcs.SetResult(sender.Reply);
            };
        ping.SendAsync(address, new object());
        return tcs.Task;
    }
}
like image 40
Pete Avatar answered Oct 27 '22 20:10

Pete