Mar 18 2010

Audible Ping

Category: Networking, SoundMike Lovell @ 8:32 pm

This is either the greatest or most annoying tool ever!  I have to reboot a lot of machines and I always kick of a continuous ping against them to see them go down and come up again.  I thought it would be great if I could make a hospital heart-monitor style beeping ping utility, so I did.  Here it is.

First lets write a ‘ToneHandler‘ class to control our sound.  We’ll give this the capability to either make a single ‘beep‘ or a continous tone (indicating the machine is down).  We’re going to use ‘Console.Beep‘ for this.  We’ll run our continuous tone function in its own thread so we can terminate it when the machine starts pinging again.

   1:  // Author Mike Lovell (mike.lovell@gotinker.com)
   2:   
   3:  class ToneHandler
   4:  {
   5:      private    Thread    constantToneThread;
   6:   
   7:   
   8:      public void SingleTone(int frequency, int duration)
   9:      {
  10:          Console.Beep(frequency, duration);
  11:      }
  12:   
  13:   
  14:      public void ConstantToneBegin()
  15:      {
  16:          if (constantToneThread != null) return;    // If already making tone, exit
  17:   
  18:          constantToneThread    = new Thread(new ThreadStart(delegate()
  19:              {
  20:                  while (true)
  21:                  {    // Infinite loop, we'll kill it later
  22:                      Console.Beep(500, Int32.MaxValue);
  23:                  }
  24:              }));
  25:   
  26:          constantToneThread.IsBackground = true;
  27:          constantToneThread.Start();    // Kick it off
  28:      }
  29:   
  30:   
  31:      public void ConstantToneEnd()
  32:      {
  33:          if (constantToneThread == null) return;    // If already not making tone, exit
  34:   
  35:          Console.Beep(500, 1);    // Send another Beep, this will terminte the other one
  36:   
  37:          constantToneThread.Join(500);    // Terminate thread
  38:   
  39:          constantToneThread = null;
  40:   
  41:          return;
  42:      }
  43:  }
  44:   

Now lets make a little wrapper for the .NET ‘Ping‘ class.  Because we’re going to link the tone and duration of the tone to the round-trip time of the ping, all we want our ping class to return is the time the ping took, or ‘-1‘ if the ping failed.

  45:   
  46:  class PingWrapper
  47:  {
  48:      private    IPAddress    ipAddress;
  49:   
  50:      private    Ping        ping        = new Ping();
  51:      private    PingOptions    pingOptions    = new PingOptions();
  52:   
  53:      private    byte[]        buffer        = new byte[32]
  54:          {    // 32 byte buffer
  55:              0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  56:              0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  57:              0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  58:              0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
  59:          };
  60:   
  61:      public PingWrapper(string host)
  62:      {
  63:          // Resolve the host once, not at every ping
  64:          ipAddress = Dns.GetHostAddresses(host)[0];
  65:   
  66:          pingOptions.DontFragment = true;
  67:      }
  68:   
  69:   
  70:      public int Send()
  71:      {
  72:          var reply = ping.Send(ipAddress, 1000, buffer, pingOptions);
  73:   
  74:          // Only send a ping every 1 second
  75:          Thread.Sleep(1000 - (int)reply.RoundtripTime);
  76:   
  77:          if (reply.Status == IPStatus.Success)
  78:          {
  79:              return (int)reply.RoundtripTime;
  80:          }
  81:          else
  82:          {
  83:              return -1;
  84:          }
  85:      }
  86:  }
  87:   

Now we’ll take the first argument of the command line and use it as the host we’re going to ping.  We’ll setup a continuous loop in a different thread (so we can terminate it from the main thread) and get it to call our tone class based on the output of ping.  We’ll also display a 1 character status of what happened (success ‘_‘ or failed ‘!‘)

  88:   
  89:  class Program
  90:  {
  91:      static void Main(string[] args)
  92:      {
  93:          if (args.Length != 1)
  94:          {
  95:              Console.WriteLine("Usage: gotinker.audibleping <hostname or IP>");
  96:              return;
  97:          }
  98:   
  99:          var    terminate    = false;
 100:          var    toneHandler = new ToneHandler();
 101:          var    ping        = new PingWrapper(args[0]);
 102:   
 103:          var loopThread    = new Thread(new ThreadStart(delegate()
 104:              {
 105:                  while (true)
 106:                  {
 107:                      if (terminate) break;
 108:   
 109:                      var result = ping.Send();
 110:   
 111:                      if (result == -1)
 112:                      {
 113:                          Console.Write("!");
 114:                          toneHandler.ConstantToneBegin();
 115:                      }
 116:                      else
 117:                      {
 118:                          Console.Write("_");
 119:                          toneHandler.ConstantToneEnd();
 120:                          toneHandler.SingleTone(500 - (result / 4), ((result * 4) + 100));
 121:                      }
 122:                  }
 123:              }));
 124:   
 125:          Console.WriteLine("(Press any enter to exit)");
 126:   
 127:          loopThread.Start();
 128:   
 129:          Console.ReadLine();
 130:   
 131:          terminate = true;    // Our loops checks for this to exit
 132:   
 133:          while (loopThread.ThreadState == ThreadState.Running)
 134:          {
 135:              Thread.Sleep(50);    // Wait fot the thread to terminate
 136:          }
 137:      }
 138:  }

And the result, here’s me pinging something while I reboot it (Download Audio of Demo):

(Press any enter to exit)
________!!!!!!_________!_____________

Download Visual Studio 2010 Project (7.16k)

Tags: , , , , , , , , , , , ,

One Response to “Audible Ping”

Leave a Reply