Gehe zu deutscher Webseite

ViaThinkSoft CodeLib

This article is in:
CodeLibProgramming aidsC#

ATTENTION: The DayTime-Protocol is outdated! Please use the NTP variant here.

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Net.Sockets;

namespace ConsoleApp6
{

    class Program
    {
        public class AtomzeitAsync
        {
            public struct Atomzeit
            {
                public string server;
                public DateTime zeit;
            }
            public static string[] servers = { "time-a.nist.gov", "time-b.nist.gov", "time.nist.gov", "utcnist.colorado.edu", "nist1.datum.com" };
            public static Atomzeit? GetAtomzeit(int timeout = 1000)
            {
                List<Task<Atomzeit>> tasks = new List<Task<Atomzeit>>();

                int bakWorkerThreads = 0;
                int bakCompletionPortThreads = 0;
                ThreadPool.GetMinThreads(out bakWorkerThreads, out bakCompletionPortThreads);
                ThreadPool.SetMinThreads(bakWorkerThreads + servers.Length, bakCompletionPortThreads + servers.Length);
                try
                {
                    for (int i = 0; i < servers.Length; i++)
                    {
                        tasks.Add(GetFileLengthsAsync(servers[i], false));
                    }

                    Thread.Sleep(timeout);

                    for (int ctr = 0; ctr < tasks.Count; ctr++)
                    {
                        if (tasks[ctr].Status == TaskStatus.RanToCompletion)
                        {
                            return tasks[ctr].Result;
                        }
                    }
                    return null;
                }
                finally
                {
                    ThreadPool.SetMinThreads(bakWorkerThreads, bakCompletionPortThreads);
                }
            }

            private static Task<Atomzeit> GetFileLengthsAsync(string serverIp, bool utc)
            {
                return Task.Factory.StartNew/*Task.Run*/(() =>
                {


                        // Variable für Fehlermeldungen
                        string errors = null;

                    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(serverIp, 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 '" + serverIp +
                                   ": " + 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
                                        if (utc)
                                    {
                                        Atomzeit res = new Atomzeit();
                                        res.server = serverIp;
                                        res.zeit = utcDate;
                                        return res;
                                    }
                                    else
                                    {
                                        Atomzeit res = new Atomzeit();
                                        res.server = serverIp;
                                        res.zeit = TimeZone.CurrentTimeZone.ToLocalTime(utcDate);
                                        return res;
                                    }
                                }
                                else
                                {
                                        // Fehler dokumentieren
                                        if (errors != null) errors += "\r\n";
                                    errors += "Fehler bei der Abfrage von '" + serverIp +
                                       ": Der Health-Status ist " + health;
                                }
                            }
                            else
                            {
                                    // Fehler dokumentieren
                                    if (errors != null) errors += "\r\n";
                                errors += "Fehler bei der Abfrage von '" + serverIp +
                                   ": 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 '" +
                           serverIp + ": " + 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);
                });
            }

        }

        public static void Main()
        {
            AtomzeitAsync.Atomzeit? az = AtomzeitAsync.GetAtomzeit();
            if (az == null)
            {
                Console.WriteLine("Atomzeit konnte nicht ermittelt werden");
            }
            else
            {
                Console.WriteLine("Atomzeit: {0} gemeldet durch {1}", ((AtomzeitAsync.Atomzeit)az).zeit, ((AtomzeitAsync.Atomzeit)az).server);
            }

            Console.ReadLine();
        }

    }
}
Daniel Marschall
ViaThinkSoft Co-Founder