jueves, 4 de marzo de 2010

Traceroute en .Net

Estos días estaba revisando un proyecto personal, y vi una clase que había hecho hace tiempo, y bastante interezante, es una implementacion de Traceroute/Tracert en .Net (C Sharp).

¿Cómo funciona un Traceroute?

No es tan complicado como pudiésemos llegar a pensar. Para explicarlo imaginémos el siguiente esquema de red:

A-----B-----C-----D-----E

Donde A es el equipo host local, y E el host remoto. El funcionamiendo de la aplicacion es la siguiente. Se hace un ping hacia el remoto pero con una opcion diferente, TTL = 1, es decir Time To Live = 1. Esto quiere decir que apenas el paquete salga hacia E, éste nada más va a poder pasar por un Nodo, Router, Modem, etc y el resultado del ping nos va a retornar la Dirección IP de dicho Nodo, en éste caso de B.

De ésta manera vamos aumentando el TTL de cada intento y vamos guardando la informacion hasta que el status de la respuesta del Ping sea satisfactoria (IPStatus.Success).

Ahora veamos el código:

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Text;
   4:  using System.Net.NetworkInformation;
   5:   
   6:  namespace NetworkSupervisor.ComponentModel
   7:  {
   8:      //Delegado para los eventos del Traceroute
   9:      public delegate void TracertEventHandler(object sender, TracertEventArgs e);
  10:      
  11:      public class Tracert
  12:      {
  13:          int     m_timeout   = 0;
  14:          string  m_host      = "";
  15:          int     m_maxHops   = 0;
  16:   
  17:          public event TracertEventHandler EchoReceived;
  18:          public event TracertEventHandler ErrorReceived;
  19:          public event TracertEventHandler TracertCompleted;
  20:   
  21:          public Tracert(string host, int TimeOut, int maxHops) 
  22:          {
  23:              m_host = host;
  24:              m_timeout = TimeOut;
  25:              m_maxHops = maxHops;
  26:          }
  27:          public void Start() 
  28:          {
  29:              PingReply reply;
  30:              Ping pinger = new Ping();
  31:              PingOptions options = new PingOptions();
  32:   
  33:              //Con esto le decimos al paquete que nada más salte un equipo.
  34:              options.Ttl = 1;
  35:   
  36:              options.DontFragment = true;
  37:   
  38:              byte[] buffer = Encoding.ASCII.GetBytes("Algo de datos");
  39:              try
  40:              {
  41:                  do
  42:                  {
  43:                      //Tiempo antes del comando
  44:                      DateTime start = DateTime.Now;
  45:   
  46:                     //Mandamos el ping
  47:                      reply = pinger.Send(m_host,
  48:                                          m_timeout,
  49:                                          buffer,
  50:                                          options);
  51:   
  52:                      //Restamos la diferencia de tiempo para conocer la latencia.
  53:                      long milliseconds = DateTime.Now.Subtract(start).Milliseconds;
  54:                      if ((reply.Status == IPStatus.TtlExpired)
  55:                         || (reply.Status == IPStatus.Success))
  56:                      {
  57:                          //Damos respuesta en caso de que encontremos un host
  58:                          //o que se haya finalizado el proceso.
  59:                          OnEchoReceived(reply, milliseconds, options.Ttl);
  60:                      }
  61:                      else
  62:                      {
  63:                          OnErrorReceived(reply, milliseconds);
  64:                      }
  65:                      options.Ttl++;
  66:   
  67:                     //Mientras no haya terminado, es decir, no sea Success
  68:                     //seguimos mandando ping con un TTL aumentado.
  69:        
  70:                     // Notemos que cuando la resuesta es Success 
  71:                     //es porque el paquete llego al destino
  72:                  } while ((reply.Status != IPStatus.Success)
  73:                          && (options.Ttl < m_maxHops));
  74:              }
  75:              catch (PingException pex)
  76:              {
  77:                  //Acá pueden implementar algo en caso de algun error.
  78:                  throw pex.InnerException;
  79:              }
  80:              finally 
  81:              {
  82:                  if (TracertCompleted != null)
  83:                      TracertCompleted(this, new TracertEventArgs(null, 0, 0));
  84:              }   
  85:          }
  86:   
  87:   
  88:          //Manejo de los eventos.
  89:          private void OnErrorReceived(PingReply reply, long milliseconds)
  90:          {
  91:              InvokeErrorReceived(reply, milliseconds);
  92:          }
  93:   
  94:          private void OnEchoReceived(PingReply reply, long milliseconds, int ttl)
  95:          {
  96:              InvokeEchoReceived(reply, milliseconds, ttl);
  97:          }
  98:          public void InvokeEchoReceived(PingReply reply, long milliseconds, int ttl)
  99:          {
 100:              if (EchoReceived != null)
 101:                  EchoReceived(this, new TracertEventArgs(reply, milliseconds,ttl));
 102:          }
 103:          public void InvokeErrorReceived(PingReply reply, long milliseconds)
 104:          {
 105:              if (ErrorReceived != null)
 106:                  ErrorReceived(this, new TracertEventArgs(reply, milliseconds,0));
 107:          }
 108:      }
 109:  }

Espero les sea de ayuda!

Gracias por leer!

No hay comentarios:

Publicar un comentario