TraceRoute et Ping en C #

Est-ce que quelqu’un a le code C # à scope de main pour faire un ping et traceroute sur un ordinateur cible? Je cherche une solution de code pur, pas ce que je fais maintenant, qui appelle le programme ping.exe et tracert.exe et parsing la sortie. Je voudrais quelque chose de plus robuste.

Bien que la bibliothèque de classes de base inclue Ping , la BCL n’inclut aucune fonctionnalité tracert.

Cependant, une recherche rapide révèle deux tentatives d’open-source, la première en C # et la seconde en C ++:

Étant donné que je devais écrire une classe TraceRoute aujourd’hui, je me suis dit que je pourrais aussi bien partager le code source.

using System.Collections.Generic; using System.Net.NetworkInformation; using System.Text; using System.Net; namespace Answer { public class TraceRoute { private const ssortingng Data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; public static IEnumerable GetTraceRoute(ssortingng hostNameOrAddress) { return GetTraceRoute(hostNameOrAddress, 1); } private static IEnumerable GetTraceRoute(ssortingng hostNameOrAddress, int ttl) { Ping pinger = new Ping(); PingOptions pingerOptions = new PingOptions(ttl, true); int timeout = 10000; byte[] buffer = Encoding.ASCII.GetBytes(Data); PingReply reply = default(PingReply); reply = pinger.Send(hostNameOrAddress, timeout, buffer, pingerOptions); List result = new List(); if (reply.Status == IPStatus.Success) { result.Add(reply.Address); } else if (reply.Status == IPStatus.TtlExpired || reply.Status == IPStatus.TimedOut) { //add the currently returned address if an address was found with this TTL if (reply.Status == IPStatus.TtlExpired) result.Add(reply.Address); //recurse to get the next address... IEnumerable tempResult = default(IEnumerable); tempResult = GetTraceRoute(hostNameOrAddress, ttl + 1); result.AddRange(tempResult); } else { //failure } return result; } } } 

Et une version VB pour tous ceux qui en veulent / en ont besoin

 Public Class TraceRoute Private Const Data As Ssortingng = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" Public Shared Function GetTraceRoute(ByVal hostNameOrAddress As Ssortingng) As IEnumerable(Of IPAddress) Return GetTraceRoute(hostNameOrAddress, 1) End Function Private Shared Function GetTraceRoute(ByVal hostNameOrAddress As Ssortingng, ByVal ttl As Integer) As IEnumerable(Of IPAddress) Dim pinger As Ping = New Ping Dim pingerOptions As PingOptions = New PingOptions(ttl, True) Dim timeout As Integer = 10000 Dim buffer() As Byte = Encoding.ASCII.GetBytes(Data) Dim reply As PingReply reply = pinger.Send(hostNameOrAddress, timeout, buffer, pingerOptions) Dim result As List(Of IPAddress) = New List(Of IPAddress) If reply.Status = IPStatus.Success Then result.Add(reply.Address) ElseIf reply.Status = IPStatus.TtlExpired Then 'add the currently returned address result.Add(reply.Address) 'recurse to get the next address... Dim tempResult As IEnumerable(Of IPAddress) tempResult = GetTraceRoute(hostNameOrAddress, ttl + 1) result.AddRange(tempResult) Else 'failure End If Return result End Function End Class 

Pour la partie ping, consultez la classe Ping sur MSDN.

Ce qui suit est une implémentation de tracert meilleure en C # que dans d’autres réponses jusqu’à présent.

 public static IEnumerable GetTraceRoute(ssortingng hostname) { // following are the defaults for the "traceroute" command in unix. const int timeout = 10000; const int maxTTL = 30; const int bufferSize = 32; byte[] buffer = new byte[bufferSize]; new Random().NextBytes(buffer); Ping pinger = new Ping(); for (int ttl = 1; ttl <= maxTTL; ttl++) { PingOptions options = new PingOptions(ttl, true); PingReply reply = pinger.Send(hostname, timeout, buffer, options); if (reply.Status == IPStatus.TtlExpired) { // TtlExpired means we've found an address, but there are more addresses yield return reply.Address; continue; } if (reply.Status == IPStatus.TimedOut) { // TimedOut means this ttl is no good, we should continue searching continue; } if (reply.Status == IPStatus.Success) { // Success means the tracert has completed yield return reply.Address; } // if we ever reach here, we're finished, so break break; } } 

Les pièges résolus ici et présents dans d'autres réponses incluent:

  • C'est paresseux. Ex: il utilise correctement enumerable / un iterator afin de ne pas avoir à calculer l’arbre complet, vous pouvez vous arrêter à tout moment en sortant de votre propre boucle consommasortingce.
  • maxTTL implémenté pour que la fonction ne tourne pas pour toujours.
  • option bufferSize compatible avec les autres implémentations de tracert.
  • C'est super concis et propre. Il est contenu dans une seule méthode et est considérablement plus court que les autres options ici.

En améliorant la réponse du code Scotts ci-dessus, j’ai constaté que sa solution ne fonctionnait pas si la route se réduisait en rien avant d’atteindre la destination; elle ne reviendrait jamais. Voici une meilleure solution avec au moins un itinéraire partiel (que j’ai testée et qui fonctionne bien). Vous pouvez modifier le “20” de la boucle for en un format plus grand ou plus petit ou essayer de détecter si sa durée est trop longue si vous souhaitez contrôler le nombre d’itérations d’une autre manière. Un grand crédit à Scott pour le code original – merci.

  using System.Collections.Generic; using System.Net.NetworkInformation; using System.Text; using System.Net; ... public static void TraceRoute(ssortingng hostNameOrAddress) { for (int i = 1; i < 20; i++) { IPAddress ip = GetTraceRoute(hostNameOrAddress, i); if(ip == null) { break; } Console.WriteLine(ip.ToString()); } } private static IPAddress GetTraceRoute(string hostNameOrAddress, int ttl) { const string Data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; Ping pinger = new Ping(); PingOptions pingerOptions = new PingOptions(ttl, true); int timeout = 10000; byte[] buffer = Encoding.ASCII.GetBytes(Data); PingReply reply = default(PingReply); reply = pinger.Send(hostNameOrAddress, timeout, buffer, pingerOptions); List result = new List(); if (reply.Status == IPStatus.Success || reply.Status == IPStatus.TtlExpired) { return reply.Address; } else { return null; } } 

Ping : Nous pouvons utiliser la classe Ping intégrée au .NET Framework.

Instanciez un Ping et abonnez-vous à l’événement PingCompleted :

 Ping pingSender = new Ping(); pingSender.PingCompleted += PingCompletedCallback; 

Ajoutez du code pour configurer et exécuter le ping, par exemple:

 ssortingng data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; byte[] buffer = Encoding.ASCII.GetBytes(data); ssortingng who = "www.google.com"; AutoResetEvent waiter = new AutoResetEvent(false); int timeout = 12000; PingOptions options = new PingOptions(64, true); pingSender.SendAsync(who, timeout, buffer, options, waiter); 

Ajoutez un PingCompletedEventHandler :

 public static void PingCompletedCallback(object sender, PingCompletedEventArgs e) { ... Do stuff here } 

Dump de code d’un exemple de travail complet, basé sur l’exemple de MSDN :

 public static void Main(ssortingng[] args) { ssortingng who = "www.google.com"; AutoResetEvent waiter = new AutoResetEvent(false); Ping pingSender = new Ping(); // When the PingCompleted event is raised, // the PingCompletedCallback method is called. pingSender.PingCompleted += PingCompletedCallback; // Create a buffer of 32 bytes of data to be transmitted. ssortingng data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; byte[] buffer = Encoding.ASCII.GetBytes(data); // Wait 12 seconds for a reply. int timeout = 12000; // Set options for transmission: // The data can go through 64 gateways or routers // before it is destroyed, and the data packet // cannot be fragmented. PingOptions options = new PingOptions(64, true); Console.WriteLine("Time to live: {0}", options.Ttl); Console.WriteLine("Don't fragment: {0}", options.DontFragment); // Send the ping asynchronously. // Use the waiter as the user token. // When the callback completes, it can wake up this thread. pingSender.SendAsync(who, timeout, buffer, options, waiter); // Prevent this example application from ending. // A real application should do something useful // when possible. waiter.WaitOne(); Console.WriteLine("Ping example completed."); } public static void PingCompletedCallback(object sender, PingCompletedEventArgs e) { // If the operation was canceled, display a message to the user. if (e.Cancelled) { Console.WriteLine("Ping canceled."); // Let the main thread resume. // UserToken is the AutoResetEvent object that the main thread // is waiting for. ((AutoResetEvent)e.UserState).Set(); } // If an error occurred, display the exception to the user. if (e.Error != null) { Console.WriteLine("Ping failed:"); Console.WriteLine(e.Error.ToSsortingng()); // Let the main thread resume. ((AutoResetEvent)e.UserState).Set(); } Console.WriteLine($"Roundsortingp Time: {e.Reply.RoundsortingpTime}"); // Let the main thread resume. ((AutoResetEvent)e.UserState).Set(); }