Feedback

C# - Atomuhr-Datum von einem NIST-Server abfragen

Veröffentlicht von am 18.10.2006
(2 Bewertungen)
Das amerikanische Institut NIST (National Institute of Standards and Technology) betreibt einige hochgenaue Atomuhren, deren Datum in den USA als Standard gelten. Einige Server liefern dieses Datum in einem speziellen Format über das Daytime-Protokoll des W3C. Die Methode GetNISTTime fragt bei Bedarf bis zu fünf Standard-NIST-Server ab und liefert das gelesene Datum zurück.
// **********************************************
// Dies ist eines der 322 Rezepte aus dem
// C# 2005 Premium Codebook. 
// Das Snippet wurde vom Autor mit freundlicher 
// Genehmigung von Addison Wesley 
// bei dotnet-snippets.de veröffentlicht.
// **********************************************


using System;
using System.Text;
using System.Net.Sockets;

/// <summary>
/// Fragt das aktuelle Datum (inklusive Zeit) bei einem NIST-Server ab
/// </summary>
/// <returns>Gibt das abgefragte Datum zurück</returns>
public static System.DateTime GetNISTTime()
{
   // Variable für Fehlermeldungen
   string errors = null;

   // Array für die abzufragenden Server
   string[] servers = {"time-a.nist.gov", "time-b.nist.gov",
                     "time.nist.gov", "utcnist.colorado.edu", "nist1.datum.com"};

   // Schleife, in der die Server abgefragt werden, bis das Ergebnis 
   // in Ordnung ist
   for (int i = 0; i < servers.Length; i++)
   {
      TcpClient tcpClient = null;
      try
      {
         // TcpClient erzeugen und den Empfangs-Timeout auf eine Sekunde
         // setzen
         tcpClient = new TcpClient();
         tcpClient.ReceiveTimeout = 1000;

         // Versuch zum aktuellen Server eine Verbindung aufzubauen
         tcpClient.Connect(servers[i], 13);

         // Den NetworkStream referenzieren
         NetworkStream networkStream = tcpClient.GetStream();

         string result = null;
         if (networkStream.CanWrite && networkStream.CanRead)
         {
            // Das Ergebnis empfangen und in ASCII konvertieren
            byte[] bytes = new byte[tcpClient.ReceiveBufferSize];
            try
            {
               networkStream.Read(bytes, 0,
                  (int)tcpClient.ReceiveBufferSize);
               result = Encoding.ASCII.GetString(bytes);
            }
            catch (Exception ex)
            {
               // Fehler dokumentieren
               if (errors != null) errors += "\r\n";
               errors += "Fehler bei der Abfrage von '" + servers[i] +
                  ": " + ex.Message;
            }
         }

         if (result != null)
         {
            // Das Ergebnis, das die Form JJJJJ YR-MO-DA HH:MM:SS TT L H msADV 
            // UTC(NIST) OTM besitzt, in einzelne Token aufsplitten
            string[] token = result.Split(' ');

            // Anzahl der Token überprüfen
            if (token.Length >= 6)
            {
               // Den Health-Status auslesen und überprüfen
               string health = token[5];
               if (health == "0")
               {
                  // Alles ok:  Datums- und Zeitangaben auslesen
                  string[] dates = token[1].Split('-');
                  string[] times = token[2].Split(':');

                  // DateTime-Instanz mit diesen Daten erzeugen
                  System.DateTime utcDate =
                     new System.DateTime(Int32.Parse(dates[0]) + 2000,
                     Int32.Parse(dates[1]), Int32.Parse(dates[2]),
                     Int32.Parse(times[0]), Int32.Parse(times[1]),
                     Int32.Parse(times[2]));

                  // Lokale Zeit berechnen und zurückgeben
                  return TimeZone.CurrentTimeZone.ToLocalTime(utcDate);
               }
               else
               {
                  // Fehler dokumentieren
                  if (errors != null) errors += "\r\n";
                  errors += "Fehler bei der Abfrage von '" + servers[i] +
                     ": Der Health-Status ist " + health;
               }
            }
            else
            {
               // Fehler dokumentieren
               if (errors != null) errors += "\r\n";
               errors += "Fehler bei der Abfrage von '" + servers[i] +
                  ": Die Anzahl der Token ist kleiner als 6";
            }
         }
      }
      catch (Exception ex)
      {
         // Fehler dokumentieren
         if (errors != null) errors += "\r\n";
         errors += "Fehler bei der Abfrage von '" +
            servers[i] + ": " + ex.Message;
      }
      finally
      {
         try
         {
            // TcpClient schließen
            tcpClient.Close();
         }
         catch { }
      }
   }

   // Wenn die Methode hier ankommt, sind bei allen Abfragen
   // Fehler aufgetreten, also eine Ausnahme werfen
   throw new Exception(errors);
}
Abgelegt unter Datum, Atomzeit, Atomdatum, NIST.

Kommentare zum Snippet

 

Logge dich ein, um hier zu kommentieren!