ZetCode

C# Ping

last modified October 18, 2026

In this article we show how to determine the accessibility of a remote host in C# with the Ping class.

The name and the functionality of the Ping class come from the classic ping networking utility. The ping utility is used to test the reachability of a remote host on an IP network. It operates on the ICMP protocol.

The Internet Control Message Protocol (ICMP) is used by hosts and routers to communicate network-layer information to each other. Typically, it is used for error reporting. The protocol is described by RFC 792.

Pinging is sending an ICMP echo request to the target host and waiting for an ICMP echo reply.

The Ping class is located in the System.Net.NetworkInformation namespace. Its Send and SendPingAsync methods send an ICMP echo request message to a remote computer and wait for an ICMP echo reply message from that computer. The PingReply provides information about the status and data resulting from the message.

Note that many servers and firewalls block ICMP. A failed ping does not necessarily mean that the host is down; a web server may refuse pings and still serve web pages.

C# Ping Send

The Send method sends the ICMP echo request message to a remote computer synchronously.

Program.cs
using System.Net.NetworkInformation;

string host = "example.com";

using var ping = new Ping();
PingReply res = ping.Send(host);

Console.WriteLine(res.Status);

The program pings a remote host in a synchronous manner.

using var ping = new Ping();

A Ping object is created. It implements IDisposable.

PingReply res = ping.Send(host);

We ping a host specified by its name and receive a PingReply. An IP address can be used as well.

Console.WriteLine(res.Status);

We print the status of the reply. It is a value of the IPStatus enumeration.

$ dotnet run
Success

C# PingReply.RoundtripTime

The PingReply.RoundtripTime returns the number of milliseconds taken to send an ICMP echo request and receive the corresponding ICMP echo reply message.

Program.cs
using System.Net.NetworkInformation;

string host = "example.com";
using var ping = new Ping();

for (int i = 0; i < 3; i++)
{
    PingReply res = await ping.SendPingAsync(host);

    Console.WriteLine($"{res.Status} from {res.Address} in {res.RoundtripTime} ms");
}

The program sends three asynchronous ping requests and prints the status, address, and the round trip time.

Console.WriteLine($"{res.Status} from {res.Address} in {res.RoundtripTime} ms");

The round trip time is retrieved through the RoundtripTime property of the PingReply.

$ dotnet run
Success from 172.66.147.243 in 3 ms
Success from 104.20.23.154 in 8 ms
Success from 172.66.147.243 in 2 ms

The host name is resolved for each request. The example.com domain has several addresses, so the replies may come from different addresses.

C# Ping timeout

Some overloaded methods allow to specify a timeout. If no reply arrives in time, the status is TimedOut.

Program.cs
using System.Net.NetworkInformation;

string host = "192.0.2.1";
using var ping = new Ping();

var timeout = TimeSpan.FromMilliseconds(500);

PingReply res = await ping.SendPingAsync(host, timeout);
Console.WriteLine($"{res.Status} from {res.Address} in {res.RoundtripTime} ms");

We ping the 192.0.2.1 address with a timeout of 500 ms. The address belongs to a block reserved for documentation (RFC 5737), so no host answers.

$ dotnet run
TimedOut from 0.0.0.0 in 0 ms

On a timeout, the address and the round trip time of the reply are not meaningful.

C# PingException

If the ping cannot be sent at all, for instance because the host name cannot be resolved, the methods throw a PingException.

Program.cs
using System.Net.NetworkInformation;

string[] hosts = ["example.com", "nonexistent.invalid"];

using var ping = new Ping();

foreach (var host in hosts)
{
    try
    {
        PingReply res = await ping.SendPingAsync(host);
        Console.WriteLine($"{host}: {res.Status}");
    }
    catch (PingException e)
    {
        Console.WriteLine($"{host}: {e.InnerException?.Message ?? e.Message}");
    }
}

The .invalid top-level domain is reserved and never resolves.

catch (PingException e)
{
    Console.WriteLine($"{host}: {e.InnerException?.Message ?? e.Message}");
}

The PingException wraps the original error; the inner exception tells us what went wrong.

$ dotnet run
example.com: Success
nonexistent.invalid: Name or service not known

C# ping multiple hosts

A Ping object can send only one request at a time. To ping several hosts concurrently, we create a Ping object for each request.

Program.cs
using System.Net.NetworkInformation;

string[] hosts = ["example.com", "wikipedia.org", "dotnet.microsoft.com", "192.0.2.1"];

var tasks = hosts.Select(PingHostAsync);
string[] results = await Task.WhenAll(tasks);

foreach (var line in results)
{
    Console.WriteLine(line);
}

static async Task<string> PingHostAsync(string host)
{
    using var ping = new Ping();

    try
    {
        PingReply res = await ping.SendPingAsync(host, TimeSpan.FromSeconds(1));

        return res.Status == IPStatus.Success
            ? $"{host,-22} {res.RoundtripTime,4} ms"
            : $"{host,-22} {res.Status}";
    }
    catch (PingException)
    {
        return $"{host,-22} unknown host";
    }
}

We ping four hosts at the same time and wait for all replies with Task.WhenAll. The results are in the order of the hosts.

$ dotnet run
example.com               3 ms
wikipedia.org            24 ms
dotnet.microsoft.com     17 ms
192.0.2.1              TimedOut

C# ping tool

In the last example, we create a simple ping tool. It accepts the host, the number of requests, and the timeout from the command line and prints statistics at the end.

Program.cs
using System.Net.NetworkInformation;

if (args.Length is < 1 or > 3)
{
    Console.WriteLine("usage: dotnet run <host> [count] [timeout_ms]");
    return;
}

string host = args[0];
int count = args.Length > 1 ? int.Parse(args[1]) : 4;
int timeout = args.Length > 2 ? int.Parse(args[2]) : 2000;

using var ping = new Ping();
var times = new List<long>();

for (int i = 0; i < count; i++)
{
    PingReply res = await ping.SendPingAsync(host, TimeSpan.FromMilliseconds(timeout));

    if (res.Status == IPStatus.Success)
    {
        times.Add(res.RoundtripTime);
        Console.WriteLine($"Reply from {res.Address}: time={res.RoundtripTime} ms");
    }
    else
    {
        Console.WriteLine(res.Status);
    }

    if (i < count - 1)
    {
        await Task.Delay(1000);
    }
}

int lost = count - times.Count;
Console.WriteLine($"{count} sent, {times.Count} received, {lost * 100 / count}% loss");

if (times.Count > 0)
{
    Console.WriteLine($"min/avg/max = {times.Min()}/{times.Average():F1}/{times.Max()} ms");
}

The host is mandatory; the number of requests and the timeout are optional.

if (args.Length is < 1 or > 3)

We check the number of arguments with a relational pattern.

if (i < count - 1)
{
    await Task.Delay(1000);
}

Like the ping utility, we wait one second between requests.

$ dotnet run example.com 3
Reply from 172.66.147.243: time=8 ms
Reply from 172.66.147.243: time=4 ms
Reply from 172.66.147.243: time=4 ms
3 sent, 3 received, 0% loss
min/avg/max = 4/5.3/8 ms

Source

Ping class - language reference

In this article we have worked with the C# Ping class to ping remote hosts.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all C# tutorials.