Tracert implementation in C#
While I was looking for a tracert method that I could use for an application of mine I noticed that the .NET framework doesn’t provide one out of the box, so I decided to create one that matched my requirements.
The method below works in the exact same fashion the tracert method works. Providing
the method with the IP address, the max number of hops you would like to receive and a timeout value for the hops will allow you to track down the route your data will travel in order to get to their destination, as well as the time (in milliseconds) it will take for each hop.
Main method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | /// <summary> /// Traces the route which data have to travel through in order to reach an IP address. /// </summary> /// <param name="ipAddress">The IP address of the destination.</param> /// <param name="maxHops">Max hops to be returned.</param> public IEnumerable<TracertEntry> Tracert(string ipAddress, int maxHops, int timeout) { IPAddress address; // Ensure that the argument address is valid. if (!IPAddress.TryParse(ipAddress, out address)) throw new ArgumentException(string.Format("{0} is not a valid IP address.", ipAddress)); // 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."); Ping ping = new Ping(); PingOptions pingOptions = new PingOptions(1, true); Stopwatch pingReplyTime = new Stopwatch(); PingReply reply; do { pingReplyTime.Start(); reply = ping.Send(address, timeout, new byte[] { 0 }, pingOptions); pingReplyTime.Stop(); string hostname = string.Empty; if (reply.Address != null) { try { hostname = Dns.GetHostByAddress(reply.Address).HostName; // Retrieve the hostname for the replied address. } catch (SocketException) { /* No host available for that address. */ } } // Return out TracertEntry object with all the information about the hop. yield return new TracertEntry() { HopID = pingOptions.Ttl, Address = reply.Address == null ? "N/A" : reply.Address.ToString(), Hostname = hostname, ReplyTime = pingReplyTime.ElapsedMilliseconds, ReplyStatus = reply.Status }; pingOptions.Ttl++; pingReplyTime.Reset(); } while (reply.Status != IPStatus.Success && pingOptions.Ttl <= maxHops); } |
TracertEntry Class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | using System.Net.NetworkInformation; namespace Tracert { public class TracertEntry { /// <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" ); } } } |
Usage:
1 2 3 4 5 | // Tracert google.com foreach (var entry in Tracert("213.140.209.181", 30, 5000)) { Console.WriteLine(entry); } |
Feel free to modify the code to suit your needs and as always post any feedback or questions you might have below in the comment section.
Added hostname support by changing/adding the lines below
if (!IPAddress.TryParse(host, out address) && Dns.GetHostAddresses(host).Length == 0)
throw new ArgumentException(string.Format(“{0} is not a valid IP address or hostname”, host));
if(address == null && Dns.GetHostAddresses(host).Length > 0)
address = Dns.GetHostAddresses(host)[0];
Anyplace where i can download the source code, without having to create a new project at vs?
Sorry we don’t have a demo project for this example.
Nevertheless, it should be fairly easy to implement since you just require the TracertEntry class and the Tracert() method.
Tip: If you want better performance comment out line 34-42 and line 49.
So you don’t see the hostnames but it has a much better performance.
hey
reply.Address and Dns.GetHostByAddress()
both are deprecated by Microsoft so please suggest anything optional for them.
Thanks for pointing that out.
From what I am aware reply.Address isn’t obsolete. As for Dns.GetHostByAddress(), replace it with Dns.GetHostEntry().
Please keep in mind that GetHostEntry() doesn’t behave like GetHostByAddress() and might throw exceptions on valid IP address because of the reverse lookup it is performing.
If you are interested to know the exact reason why this happens take a look at http://social.msdn.microsoft.com/Forums/en-US/d3590a4a-3715-499d-ac2d-c49c01e5f543/dnsgethostentryserver-does-not-work-sometimes-however-dnsgethostbyaddressserver-does