TODO: Summary explanation to come later. Code comments work for now.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
namespace com.network_junkies.networking
{
public class TraceRouteEntry
{
/// <summary>
/// The hop id. Represents the number of the hop.
/// </summary>
public int HopID { get; set; }
/// <summary>
/// The IP address.
/// </summary>
public string Address { get; set; }
/// <summary>
/// The hostname
/// </summary>
public string Hostname { get; set; }
/// <summary>
/// The reply time it took for the host to receive and reply to the request in milliseconds.
/// </summary>
public long ReplyTime { get; set; }
/// <summary>
/// The reply status of the request.
/// </summary>
public IPStatus ReplyStatus { get; set; }
public override string ToString()
{
return string.Format("{0} | {1} | {2}",
HopID,
string.IsNullOrEmpty(Hostname) ? Address : Hostname + "[" + Address + "]",
ReplyStatus == IPStatus.TimedOut ? "Request Timed Out." : ReplyTime.ToString() + " ms"
);
}
}
public static class TraceRoute
{
public static IEnumerable<TraceRouteEntry> Tracert(IPAddress address, int maxHops, int timeout, bool resolveHost = false)
{
// Max hops should be at least one or else there won't be any data to return.
if (maxHops < 1)
throw new ArgumentException("Max hops can't be lower than 1.");
// Ensure that the timeout is not set to 0 or a negative number.
if (timeout < 1)
throw new ArgumentException("Timeout value must be higher than 0.");
var ping = new Ping();
var pingOptions = new PingOptions(1, true);
var pingReplyTime = new Stopwatch();
PingReply reply;
do
{
pingReplyTime.Start();
reply = ping.Send(address, timeout, new byte[] {0}, pingOptions);
pingReplyTime.Stop();
var hostname = String.Empty;
if (reply != null)
{
if (reply.Address != null && resolveHost)
{
try
{
hostname = Dns.GetHostEntry(reply.Address).HostName;
}
catch (SocketException)
{
}
}
}
yield return new TraceRouteEntry()
{
HopID = pingOptions.Ttl,
Address = reply.Address == null ? "Timeout" : reply.Address.ToString(),
Hostname = String.IsNullOrEmpty(hostname) ? "" : hostname,
ReplyTime = pingReplyTime.ElapsedMilliseconds,
ReplyStatus = reply.Status
};
pingOptions.Ttl++;
pingReplyTime.Reset();
} while (reply.Status != IPStatus.Success && pingOptions.Ttl <= maxHops);
}
}
}