【无标题】C#内网NTP时间同步源码

                              C#内网NTP时间同步源码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using System.Diagnostics;

namespace WindowsFormsApp3
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
           
            DateTime aa = MGetNetworkTime();
            textBox1.Text = aa.ToString("yyyy-MM-dd HH:mm:ss");
            if (textBox1.Text == "1900-12-31 00:00:00")
            { }
            else {
                string times = aa.ToString("yyyy-MM-dd HH:mm:ss");
                DateTimeSynchronization dt = new DateTimeSynchronization();
                if (dt.SetLocalTimeByStr(times))
                {
                    MessageBox.Show("修改成功");
                }
                else
                {
                    MessageBox.Show("修改失败");
                }
            }
        }
        public DateTime MGetNetworkTime()
        {
            try
            {
                //default Windows time server
                const string ntpServer = "time.windows.com";  //对于无法访问外网NTP服务器的,可以在内网假设NTP服务器,同时修改hosts文件

                // NTP message size - 16 bytes of the digest (RFC 2030)
                var ntpData = new byte[48];

                //Setting the Leap Indicator, Version Number and Mode values
                ntpData[0] = 0x1B; //LI = 0 (no warning), VN = 3 (IPv4 only), Mode = 3 (Client Mode)

                var addresses = Dns.GetHostEntry(ntpServer).AddressList;

                //The UDP port number assigned to NTP is 123
                var ipEndPoint = new IPEndPoint(addresses[0], 123);
                //NTP uses UDP
                var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

                socket.Connect(ipEndPoint);

                socket.Send(ntpData);
                socket.Receive(ntpData);
                socket.Close();

                //Offset to get to the "Transmit Timestamp" field (time at which the reply 
                //departed the server for the client, in 64-bit timestamp format."
                const byte serverReplyTime = 40;

                //Get the seconds part
                ulong intPart = BitConverter.ToUInt32(ntpData, serverReplyTime);

                //Get the seconds fraction
                ulong fractPart = BitConverter.ToUInt32(ntpData, serverReplyTime + 4);

                //Convert From big-endian to little-endian
                intPart = SwapEndianness(intPart);
                fractPart = SwapEndianness(fractPart);

                var milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);

                //**UTC** time
                var networkDateTime = (new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc)).AddMilliseconds((long)milliseconds);

                return networkDateTime.ToLocalTime();
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message+"请重试");
               
                Process p = new Process();
                p.StartInfo.FileName = "cmd.exe";
                p.StartInfo.UseShellExecute = false;//是否使用操作系统shell启动
                p.StartInfo.RedirectStandardInput = true;//接受来自调用程序的输入信息
                p.StartInfo.RedirectStandardOutput = true;//由调用程序获取输出信息
                p.StartInfo.RedirectStandardError = true;//重定向标准错误输出
                p.StartInfo.CreateNoWindow = true;//不显示程序窗口
                p.Start();//启动程序

                string strCMD = "echo 172.16.0.99 time.windows.com >C:\\Windows\\System32\\drivers\\etc\\hosts";
                p.StandardInput.WriteLine(strCMD + "&exit");

                p.StandardInput.AutoFlush = true;

                //获取cmd窗口的输出信息
                string output = p.StandardOutput.ReadToEnd();
                //等待程序执行完退出进程
                p.WaitForExit();
                p.Close();
                return Convert.ToDateTime("12-31-1900");
            }
        }

        uint SwapEndianness(ulong x)
        {
            return (uint)(((x & 0x000000ff) << 24) +
                           ((x & 0x0000ff00) << 8) +
                           ((x & 0x00ff0000) >> 8) +
                           ((x & 0xff000000) >> 24));
        }
        public class DateTimeSynchronization
        {

            [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;
            }
            public class Win32
            {
                [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);
            }

            public bool SetLocalTimeByStr(string timestr)
            {
                bool flag = false;
                SystemTime sysTime = new SystemTime();

                string SysTime = timestr.Trim();   //此步骤多余,为方便程序而用直接用timestr即可
                sysTime.wYear = Convert.ToUInt16(SysTime.Substring(0, 4));
                sysTime.wMonth = Convert.ToUInt16(SysTime.Substring(5, 2));
                sysTime.wDay = Convert.ToUInt16(SysTime.Substring(8, 2));
                sysTime.wHour = Convert.ToUInt16(SysTime.Substring(11, 2));
                sysTime.wMinute = Convert.ToUInt16(SysTime.Substring(14, 2));
                sysTime.wSecond = Convert.ToUInt16(SysTime.Substring(17, 2));
                //注意:
                //结构体的wDayOfWeek属性一般不用赋值,函数会自动计算,写了如果不对应反而会出错
                //wMiliseconds属性默认值为一,可以赋值
                try
                {
                    flag = Win32.SetLocalTime(ref sysTime);
                }
                //由于不是C#本身的函数,很多异常无法捕获
                //函数执行成功则返回true,函数执行失败返回false
                //经常不返回异常,不提示错误,但是函数返回false,给查找错误带来了一定的困难
                catch (Exception ex1)
                {
                    Console.WriteLine("SetLocalTime函数执行异常" + ex1.Message);
                }

                return flag;
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {

        }

        private void label1_Click(object sender, EventArgs e)
        {

        }
    }
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值