• C# 获取服务器时间


    代码
    using System;
    using System.Net;
    using System.Net.Sockets;

    namespace SNTPTime
    {
    // Leap indicator field values
    public enum _LeapIndicator
    {
    NoWarning,
    // 0 - No warning
    LastMinute61, // 1 - Last minute has 61 seconds
    LastMinute59, // 2 - Last minute has 59 seconds
    Alarm // 3 - Alarm condition (clock not synchronized)
    }

    //Mode field values
    public enum _Mode
    {
    SymmetricActive,
    // 1 - Symmetric active
    SymmetricPassive, // 2 - Symmetric pasive
    Client, // 3 - Client
    Server, // 4 - Server
    Broadcast, // 5 - Broadcast
    Unknown // 0, 6, 7 - Reserved
    }

    // Stratum field values
    public enum _Stratum
    {
    Unspecified,
    // 0 - unspecified or unavailable
    PrimaryReference, // 1 - primary reference (e.g. radio-clock)
    SecondaryReference, // 2-15 - secondary reference (via NTP or SNTP)
    Reserved // 16-255 - reserved
    }

    /// <summary>
    /// SNTPTimeClient 的摘要说明。
    ///
    /// Public class members:
    ///
    /// LeapIndicator - Warns of an impending leap second to be inserted/deleted in the last
    /// minute of the current day. (See the _LeapIndicator enum)
    ///
    /// VersionNumber - Version number of the protocol (3 or 4).
    ///
    /// Mode - Returns mode. (See the _Mode enum)
    ///
    /// Stratum - Stratum of the clock. (See the _Stratum enum)
    ///
    /// PollInterval - Maximum interval between successive messages.
    ///
    /// Precision - Precision of the clock.
    ///
    /// RootDelay - Round trip time to the primary reference source.
    ///
    /// RootDispersion - Nominal error relative to the primary reference source.
    ///
    /// ReferenceID - Reference identifier (either a 4 character string or an IP address).
    ///
    /// ReferenceTimestamp - The time at which the clock was last set or corrected.
    ///
    /// OriginateTimestamp - The time at which the request departed the client for the server.
    ///
    /// ReceiveTimestamp - The time at which the request arrived at the server.
    ///
    /// Transmit Timestamp - The time at which the reply departed the server for client.
    ///
    /// RoundTripDelay - The time between the departure of request and arrival of reply.
    ///
    /// LocalClockOffset - The offset of the local clock relative to the primary reference
    /// source.
    ///
    /// Initialize - Sets up data structure and prepares for connection.
    ///
    /// Connect - Connects to the time server and populates the data structure.
    ///
    /// IsResponseValid - Returns true if received data is valid and if comes from
    /// a NTP-compliant time server.
    ///
    /// ToString - Returns a string representation of the object.
    ///
    /// -----------------------------------------------------------------------------
    /// Structure of the standard NTP header (as described in RFC 2030)
    /// 1 2 3
    /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    /// |LI | VN |Mode | Stratum | Poll | Precision |
    /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    /// | Root Delay |
    /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    /// | Root Dispersion |
    /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    /// | Reference Identifier |
    /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    /// | |
    /// | Reference Timestamp (64) |
    /// | |
    /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    /// | |
    /// | Originate Timestamp (64) |
    /// | |
    /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    /// | |
    /// | Receive Timestamp (64) |
    /// | |
    /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    /// | |
    /// | Transmit Timestamp (64) |
    /// | |
    /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    /// | Key Identifier (optional) (32) |
    /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    /// | |
    /// | |
    /// | Message Digest (optional) (128) |
    /// | |
    /// | |
    /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    ///
    /// -----------------------------------------------------------------------------
    ///
    /// NTP Timestamp Format (as described in RFC 2030)
    /// 1 2 3
    /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    /// | Seconds |
    /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    /// | Seconds Fraction (0-padded) |
    /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    ///
    /// </summary>
    public class SNTPTimeClient
    {
    // NTP Data Structure Length
    private const byte NTPDataLength = 48;
    // NTP Data Structure (as described in RFC 2030)
    byte[] NTPData = new byte[NTPDataLength];

    // Offset constants for timestamps in the data structure
    private const byte offReferenceID = 12;
    private const byte offReferenceTimestamp = 16;
    private const byte offOriginateTimestamp = 24;
    private const byte offReceiveTimestamp = 32;
    private const byte offTransmitTimestamp = 40;

    // Leap Indicator
    public _LeapIndicator LeapIndicator
    {
    get
    {
    // Isolate the two most significant bits
    byte val = (byte)(NTPData[0] >> 6);
    switch (val)
    {
    case 0: return _LeapIndicator.NoWarning;
    case 1: return _LeapIndicator.LastMinute61;
    case 2: return _LeapIndicator.LastMinute59;
    case 3:
    default:
    return _LeapIndicator.Alarm;
    }
    }
    }

    // Version Number
    public byte VersionNumber
    {
    get
    {
    // Isolate bits 3 - 5
    byte val = (byte)((NTPData[0] & 0x38) >> 3);
    return val;
    }
    }

    // Mode
    public _Mode Mode
    {
    get
    {
    // Isolate bits 0 - 3
    byte val = (byte)(NTPData[0] & 0x7);
    switch (val)
    {
    case 0:
    case 6:
    case 7:
    default:
    return _Mode.Unknown;
    case 1:
    return _Mode.SymmetricActive;
    case 2:
    return _Mode.SymmetricPassive;
    case 3:
    return _Mode.Client;
    case 4:
    return _Mode.Server;
    case 5:
    return _Mode.Broadcast;
    }
    }
    }

    // Stratum
    public _Stratum Stratum
    {
    get
    {
    byte val = (byte)NTPData[1];
    if (val == 0) return _Stratum.Unspecified;
    else
    if (val == 1) return _Stratum.PrimaryReference;
    else
    if (val <= 15) return _Stratum.SecondaryReference;
    else
    return _Stratum.Reserved;
    }
    }

    // Poll Interval
    public uint PollInterval
    {
    get
    {
    return (uint)Math.Round(Math.Pow(2, NTPData[2]));
    }
    }

    // Precision (in milliseconds)
    public double Precision
    {
    get
    {
    return (1000 * Math.Pow(2, NTPData[3]));
    }
    }

    // Root Delay (in milliseconds)
    public double RootDelay
    {
    get
    {
    int temp = 0;
    temp
    = 256 * (256 * (256 * NTPData[4] + NTPData[5]) + NTPData[6]) + NTPData[7];
    return 1000 * (((double)temp) / 0x10000);
    }
    }

    // Root Dispersion (in milliseconds)
    public double RootDispersion
    {
    get
    {
    int temp = 0;
    temp
    = 256 * (256 * (256 * NTPData[8] + NTPData[9]) + NTPData[10]) + NTPData[11];
    return 1000 * (((double)temp) / 0x10000);
    }
    }

    // Reference Identifier
    public string ReferenceID
    {
    get
    {
    string val = "";
    switch (Stratum)
    {
    case _Stratum.Unspecified:
    case _Stratum.PrimaryReference:
    val
    += Convert.ToChar(NTPData[offReferenceID + 0]);
    val
    += Convert.ToChar(NTPData[offReferenceID + 1]);
    val
    += Convert.ToChar(NTPData[offReferenceID + 2]);
    val
    += Convert.ToChar(NTPData[offReferenceID + 3]);
    break;
    case _Stratum.SecondaryReference:
    //// switch(VersionNumber)
    //// {
    //// case 3: // Version 3, Reference ID is an IPv4 address
    //// string Address = NTPData[offReferenceID + 0].ToString() + "." +
    //// NTPData[offReferenceID + 1].ToString() + "." +
    //// NTPData[offReferenceID + 2].ToString() + "." +
    //// NTPData[offReferenceID + 3].ToString();
    //// try
    //// {
    //// IPAddress RefAddr = new IPAddress(Address);
    //// IPHostEntry Host = DNS.GetHostByAddr(RefAddr);
    //// val = Host.Hostname + " (" + Address + ")";
    //// }
    //// catch(Exception)
    //// {
    //// val = "N/A";
    //// }
    ////
    //// break;
    //// case 4: // Version 4, Reference ID is the timestamp of last update
    //// DateTime time = ComputeDate(GetMilliSeconds(offReferenceID));
    //// // Take care of the time zone
    //// long offset = TimeZone.CurrentTimeZone.GetUTCOffset(DateTime.Now);
    //// TimeSpan offspan = TimeSpan.FromTicks(offset);
    //// val = (time + offspan).ToString();
    //// break;
    //// default:
    //// val = "N/A";
    //// }
    break;
    }

    return val;
    }
    }

    // Reference Timestamp
    public DateTime ReferenceTimestamp
    {
    get
    {
    DateTime time
    = ComputeDate(GetMilliSeconds(offReferenceTimestamp));
    // Take care of the time zone
    long offset = Convert.ToInt64(TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now));
    TimeSpan offspan
    = TimeSpan.FromTicks(offset);
    return time + offspan;
    }
    }

    // Originate Timestamp
    public DateTime OriginateTimestamp
    {
    get
    {
    return ComputeDate(GetMilliSeconds(offOriginateTimestamp));
    }
    }

    // Receive Timestamp
    public DateTime ReceiveTimestamp
    {
    get
    {
    DateTime time
    = ComputeDate(GetMilliSeconds(offReceiveTimestamp));
    // Take care of the time zone
    long offset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now).Ticks;
    TimeSpan offspan
    = TimeSpan.FromTicks(offset);
    return time + offspan;
    }
    }

    // Transmit Timestamp
    public DateTime TransmitTimestamp
    {
    get
    {
    DateTime time
    = ComputeDate(GetMilliSeconds(offTransmitTimestamp));
    // Take care of the time zone
    long offset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now).Ticks;
    TimeSpan offspan
    = TimeSpan.FromTicks(offset);
    return time + offspan;
    }
    set
    {
    SetDate(offTransmitTimestamp, value);
    }
    }

    // Reception Timestamp
    public DateTime ReceptionTimestamp;

    // Round trip delay (in milliseconds)
    public int RoundTripDelay
    {
    get
    {
    TimeSpan span
    = (ReceiveTimestamp - OriginateTimestamp) + (ReceptionTimestamp - TransmitTimestamp);
    return (int)span.TotalMilliseconds;
    }
    }

    // Local clock offset (in milliseconds)
    public int LocalClockOffset
    {
    get
    {
    TimeSpan span
    = (ReceiveTimestamp - OriginateTimestamp) - (ReceptionTimestamp - TransmitTimestamp);
    return (int)(span.TotalMilliseconds / 2);
    }
    }

    // Compute date, given the number of milliseconds since January 1, 1900
    private DateTime ComputeDate(ulong milliseconds)
    {
    TimeSpan span
    = TimeSpan.FromMilliseconds((double)milliseconds);
    DateTime time
    = new DateTime(1900, 1, 1);
    time
    += span;
    return time;
    }

    // Compute the number of milliseconds, given the offset of a 8-byte array
    private ulong GetMilliSeconds(byte offset)
    {
    ulong intpart = 0, fractpart = 0;

    for (int i = 0; i <= 3; i++)
    {
    intpart
    = 256 * intpart + NTPData[offset + i];
    }
    for (int i = 4; i <= 7; i++)
    {
    fractpart
    = 256 * fractpart + NTPData[offset + i];
    }
    ulong milliseconds = intpart * 1000 + (fractpart * 1000) / 0x100000000L;
    return milliseconds;
    }

    // Compute the 8-byte array, given the date
    private void SetDate(byte offset, DateTime date)
    {
    ulong intpart = 0, fractpart = 0;
    DateTime StartOfCentury
    = new DateTime(1900, 1, 1, 0, 0, 0); // January 1, 1900 12:00 AM

    ulong milliseconds = (ulong)(date - StartOfCentury).TotalMilliseconds;
    intpart
    = milliseconds / 1000;
    fractpart
    = ((milliseconds % 1000) * 0x100000000L) / 1000;

    ulong temp = intpart;
    for (int i = 3; i >= 0; i--)
    {
    NTPData[offset
    + i] = (byte)(temp % 256);
    temp
    = temp / 256;
    }

    temp
    = fractpart;
    for (int i = 7; i >= 4; i--)
    {
    NTPData[offset
    + i] = (byte)(temp % 256);
    temp
    = temp / 256;
    }
    }

    // Initialize the NTPClient data
    private void Initialize()
    {
    // Set version number to 4 and Mode to 3 (client)
    NTPData[0] = 0x1B;
    // Initialize all other fields with 0
    for (int i = 1; i < 48; i++)
    {
    NTPData[i]
    = 0;
    }
    // Initialize the transmit timestamp
    TransmitTimestamp = DateTime.Now;
    }

    // Connect to the time server
    public void Connect()
    {
    try
    {
    IPAddress hostadd
    = IPAddress.Parse(TimeServer);
    IPEndPoint EPhost
    = new IPEndPoint(hostadd, Convert.ToInt32(TimePort));

    UdpClient TimeSocket
    = new UdpClient();
    TimeSocket.Connect(EPhost);
    Initialize();
    TimeSocket.Send(NTPData, NTPData.Length);
    NTPData
    = TimeSocket.Receive(ref EPhost);
    if (!IsResponseValid())
    {
    throw new Exception("Invalid response from " + TimeServer);
    }
    ReceptionTimestamp
    = DateTime.Now;
    }
    catch (SocketException e)
    {
    throw new Exception(e.Message);
    }
    }

    // Check if the response from server is valid
    public bool IsResponseValid()
    {
    if (NTPData.Length < NTPDataLength || Mode != _Mode.Server)
    {
    return false;
    }
    else
    {
    return true;
    }
    }

    // Converts the object to string
    public override string ToString()
    {
    string str;

    str
    = "Leap Indicator: ";
    switch (LeapIndicator)
    {
    case _LeapIndicator.NoWarning:
    str
    += "No warning";
    break;
    case _LeapIndicator.LastMinute61:
    str
    += "Last minute has 61 seconds";
    break;
    case _LeapIndicator.LastMinute59:
    str
    += "Last minute has 59 seconds";
    break;
    case _LeapIndicator.Alarm:
    str
    += "Alarm Condition (clock not synchronized)";
    break;
    }
    str
    += "\r\nVersion number: " + VersionNumber.ToString() + "\r\n";
    str
    += "Mode: ";
    switch (Mode)
    {
    case _Mode.Unknown:
    str
    += "Unknown";
    break;
    case _Mode.SymmetricActive:
    str
    += "Symmetric Active";
    break;
    case _Mode.SymmetricPassive:
    str
    += "Symmetric Pasive";
    break;
    case _Mode.Client:
    str
    += "Client";
    break;
    case _Mode.Server:
    str
    += "Server";
    break;
    case _Mode.Broadcast:
    str
    += "Broadcast";
    break;
    }
    str
    += "\r\nStratum: ";
    switch (Stratum)
    {
    case _Stratum.Unspecified:
    case _Stratum.Reserved:
    str
    += "Unspecified";
    break;
    case _Stratum.PrimaryReference:
    str
    += "Primary Reference";
    break;
    case _Stratum.SecondaryReference:
    str
    += "Secondary Reference";
    break;
    }
    str
    += "\r\nLocal time: " + TransmitTimestamp.ToString();
    str
    += "\r\nPrecision: " + Precision.ToString() + " ms";
    str
    += "\r\nPoll Interval: " + PollInterval.ToString() + " s";
    str
    += "\r\nReference ID: " + ReferenceID.ToString();
    str
    += "\r\nRoot Dispersion: " + RootDispersion.ToString() + " ms";
    str
    += "\r\nRound Trip Delay: " + RoundTripDelay.ToString() + " ms";
    str
    += "\r\nLocal Clock Offset: " + LocalClockOffset.ToString() + " ms";
    str
    += "\r\n";

    return str;
    }

    // The URL of the time server we're connecting to
    private string TimeServer;
    private string TimePort;

    public SNTPTimeClient(string host, string port)
    {
    TimeServer
    = host;
    TimePort
    = port;
    }
    }
    }

     调用:

    SNTPTime.SNTPTimeClient client = new SNTPTime.SNTPTimeClient("210.72.145.44", "123");
    client.Connect();
    string strTest = client.ToString();
  • 相关阅读:
    RESTful日#2:使用Unity容器和引导程序在Web api中使用依赖注入实现控制反转
    RESTful日#2:使用Unity容器和引导程序在Web api中使用依赖注入实现控制反转
    带有可选选项的输入文本框(组合框)
    在组合框中嵌入一个DataGridView
    ItemData在。net
    实现一个所有者绘制的组合框
    模板化的“请等待”按钮和模板控件介绍
    使用AvalonEdit (WPF文本编辑器)
    办公风格的扁平组合箱
    【windows】telnet 和一些dos命令
  • 原文地址:https://www.cnblogs.com/Pagan/p/1625496.html
Copyright © 2020-2023  润新知