用网页来实现修改服务器系统时间

用网页来实现修改服务器系统时间

由于自动化测试需要,经常要修改内部web服务器的系统时间

先上代码

using System;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Threading.Tasks;

namespace HQ.Job.WebApi.Common
{
    // Leap indicator field values
    public enum _LeapIndicator
    {
        /// <summary>
        /// 0 - No warning
        /// </summary>
        NoWarning,  
        /// <summary>
        /// 1 - Last minute has 61 seconds
        /// </summary>
        LastMinute61,
        /// <summary>
        /// 2 - Last minute has 59 seconds
        /// </summary>
        LastMinute59,
        /// <summary>
        /// 3 - Alarm condition (clock not synchronized)
        /// </summary>
        Alarm
    }

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

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

    [StructLayout(LayoutKind.Sequential)]
    public struct SystemTime
    {
        public ushort wYear;
        public ushort wMonth;
        public ushort wDayOfWeek;
        public ushort wDay;
        public ushort wHour;
        public ushort wMinute;
        public ushort wSecond;
        public ushort wMiliseconds;
    }

    /// <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;

        [DllImport("Kernel32.dll")]
        public static extern bool SetSystemTime(ref SystemTime sysTime);
        [DllImport("Kernel32.dll")]
        public static extern bool SetLocalTime(ref SystemTime sysTime);
        [DllImport("Kernel32.dll")]
        public static extern void GetSystemTime(ref SystemTime sysTime);
        [DllImport("Kernel32.dll")]
        public static extern void GetLocalTime(ref SystemTime sysTime);

        // 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;
            }
        }

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

        /// <summary>
        /// Receive Timestamp
        /// </summary>
        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;
            }
        }

        /// <summary>
        /// Transmit Timestamp
        /// </summary>
 
        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);
            }
        }

        /// <summary>
        /// Reception Timestamp
        /// </summary>
 
        public DateTime ReceptionTimestamp;

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

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

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

        /// <summary>
        /// Compute the number of milliseconds, given the offset of a 8-byte array
        /// </summary>
        /// <param name="offset"></param>
        /// <returns></returns>
 
        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;
        }

        /// <summary>
        /// Compute the 8-byte array, given the date
        /// </summary>
        /// <param name="offset"></param>
        /// <param name="date"></param>
 
        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;
            }
        }

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

        /// <summary>
        /// Connect to the time server
        /// </summary>
 
        public void Connect()
        {
            try
            {
                IPAddress hostadd = IPAddress.Parse(TimeServer);
                var EPhost = new IPEndPoint(hostadd, Convert.ToInt32(TimePort));
                var TimeSocket = new UdpClient { Client = { ReceiveTimeout = 5000 } };
                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);
            }
        }

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

        /// <summary>
        /// Converts the object to string
        /// </summary>
        /// <returns></returns>
 
        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;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="host"></param>
        /// <param name="port"></param>
        public SNTPTimeClient(string host, string port)
        {
            TimeServer = host;
            TimePort = port;
        }

        /// <summary> 
        /// 设置本机时间 
        /// </summary> 
        public static void SetTime(DateTime currentTime)
        {
            try
            {
                var sysTime = new SystemTime();
                sysTime.wYear = Convert.ToUInt16(currentTime.Year);
                sysTime.wMonth = Convert.ToUInt16(currentTime.Month);
                sysTime.wDay = Convert.ToUInt16(currentTime.Day);
                sysTime.wDayOfWeek = Convert.ToUInt16(currentTime.DayOfWeek);
                sysTime.wMinute = Convert.ToUInt16(currentTime.Minute);
                sysTime.wSecond = Convert.ToUInt16(currentTime.Second);
                sysTime.wMiliseconds = Convert.ToUInt16(currentTime.Millisecond);

                //处理北京时间 
                int nBeijingHour = currentTime.Hour - 8;
                if (nBeijingHour <= 0)
                {
                    nBeijingHour = 24;
                    sysTime.wDay = Convert.ToUInt16(currentTime.Day - 1);
                    //sysTime.wDayOfWeek = Convert.ToUInt16(current.DayOfWeek - 1); 
                }
                else
                {
                    sysTime.wDay = Convert.ToUInt16(currentTime.Day);
                    sysTime.wDayOfWeek = Convert.ToUInt16(currentTime.DayOfWeek);
                }
                sysTime.wHour = Convert.ToUInt16(nBeijingHour);

                SetSystemTime(ref sysTime); //设置本机时间 
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 时间还原为当前时间
        /// </summary>
        public static async Task ResetTime()
        {
            //var dt = await GetBeijingTime();
            //ntp.sjtu.edu.cn 202.120.2.101 (上海交通大学网络中心NTP服务器地址)
            await Task.Run(() =>
            {
                var client = new SNTPTimeClient("202.120.2.101", "123");
                client.Connect();
                DateTime dt = client.ReceiveTimestamp;//获取指定IP的系统时间
                SetTime(dt);
            });
            
        }
    }
}

这是实现该功能的代码,调用的方法为:

SNTPTimeClient.SetTime(time) //传一个要修改的时间

SNTPTimeClient..ResetTime() //这里是把时间还原成当前时间,当前时间是从 网络时间服务器获取的,也可以修改方法,自己指定时间服务器的ip和端口,

说明:

在web上调用该方法如果没反应或提示权限问题,则需要修改服务器的权限

选运行,输入“gpedit.msc”选-计算机配置-安全设置-本地策略-用户权利指派,右边出现策略内容,双击“更改系统时间”,添加管理员用户名或你指定的用户(iis用户,iuser,erveryone,)就可以了

不行的话再重启下服务器试试

关于ntp时间服务器的相关知识

请搜索或参考 

NTP协议格式

winXP及win7下开启NTP服务方法

如果用自己的服务器做ntp

注:确保指定IP主机的Windows Time服务已开启,防火墙允许123端口通过,NTP服务也已开启。

    原文作者:Jack2013tong
    原文地址: https://blog.csdn.net/huwei2003/article/details/50401582
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞