多方法获取网络时间

简介:        在做YH维护的时候,偶尔会碰到这样的问题:电脑的非正常关机导致系统时间出错(变为了2002-1-1),从而影响到项目系统的使用。尤其是设计到money的系统,如果时间错误,可能会导致无法想象的后果。

       在做YH维护的时候,偶尔会碰到这样的问题:电脑的非正常关机导致系统时间出错(变为了2002-1-1),从而影响到项目系统的使用。尤其是设计到money的系统,如果时间错误,可能会导致无法想象的后果。所以我们可能需要用系统和网络的双重验证。

 

       通过收集、修改、优化和测试,剔除了一些错误的和速度超慢的,只剩下了4种可行的方案。这些方案中主要有3类:

          一、通过向某网站发送请求,获取服务器响应请求的时间

          二、获某时间网页的html或xml码,读取其中的时间。

          三、通过向某授时服务器发送请求,获取网络时间

我把这些方法封装到了一个类库里了。

下面是具体的类:NetTime类(包含了多种获取网络时间的方法,标有速度),需要添加引用:COM-Microsoft Xml 3.0

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MSXML2;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text.RegularExpressions;
using System.IO.Compression;
using System.Xml;


namespace WebTime
{
    /// <summary>
    /// 网络时间
    /// </summary>
    public class NetTime
    {
        #region 获取标准北京时间1 速度100ms
        /// <summary>
        /// [1].获取标准北京时间1,读取http://www.beijing-time.org/time.asp
        /// </summary>
        /// <returns></returns>
        public  DateTime GetBeijingTime()
        {
            #region  格式
            // t0=new Date().getTime(); nyear=2012; nmonth=2; nday=11;
            // nwday=6; nhrs=0; nmin=23; nsec=0;   
            #endregion
            DateTime dt;
            WebRequest wrt = null;
            WebResponse wrp = null;
            try
            {
                wrt = WebRequest.Create("http://www.beijing-time.org/time.asp");
                wrp = wrt.GetResponse();

                string html = string.Empty;
                using (Stream stream = wrp.GetResponseStream())
                {
                    using (StreamReader sr = new StreamReader(stream, Encoding.UTF8))
                    {
                        html = sr.ReadToEnd();
                    }
                }

                string[] tempArray = html.Split(';');
                for (int i = 0; i < tempArray.Length; i++)
                {
                    tempArray[i] = tempArray[i].Replace("\r\n", "");
                }

                string year = tempArray[1].Split('=')[1];
                string month = tempArray[2].Split('=')[1];
                string day = tempArray[3].Split('=')[1];
                string hour = tempArray[5].Split('=')[1];
                string minite = tempArray[6].Split('=')[1];
                string second = tempArray[7].Split('=')[1];
                //for (int i = 0; i < tempArray.Length; i++)
                //{
                //    tempArray[i] = tempArray[i].Replace("\r\n", "");
                //}

                //string year = tempArray[1].Substring(tempArray[1].IndexOf("nyear=") + 6);
                //string month = tempArray[2].Substring(tempArray[2].IndexOf("nmonth=") + 7);
                //string day = tempArray[3].Substring(tempArray[3].IndexOf("nday=") + 5);
                //string hour = tempArray[5].Substring(tempArray[5].IndexOf("nhrs=") + 5);
                //string minite = tempArray[6].Substring(tempArray[6].IndexOf("nmin=") + 5);
                //string second = tempArray[7].Substring(tempArray[7].IndexOf("nsec=") + 5);
                dt = DateTime.Parse(year + "-" + month + "-" + day + " " + hour + ":" + minite + ":" + second);
            }
            catch (WebException)
            {
                return DateTime.Parse("2011-1-1");
            }
            catch (Exception)
            {
                return DateTime.Parse("2011-1-1");
            }
            finally
            {
                if (wrp != null)
                    wrp.Close();
                if (wrt != null)
                    wrt.Abort();
            }
            return dt;
        }
        #endregion

        #region 获取网站响应请求的时间,速度200ms
        /// <summary>
        /// [2]获取网站响应请求的时间,速度200ms
        /// </summary>
        /// <param name="hUrl">网址</param>
        /// <returns>DateTime</returns>
        /// <remarks></remarks>
        public DateTime GetNetTime( string hUrl)
        {
            string datetxt = null;         //请求回应的时间
            string[] date1 = null;         //分割后的星期和日期
            string date2 = "";              //分割后的日期和GMT
            string[] date3 = null;         //最终成型的日期
            DateTime nTime  =DateTime.Today ; 
            string localtime = "";
            string mon = "";

            XMLHTTP objHttp = new XMLHTTP();

            objHttp.open("GET", hUrl, false);

            try
            {
                objHttp.send();

                //获取网站回应请求的日期时间。如: Wed, 08 Feb 2012 06:34:58 GMT
                datetxt = objHttp.getResponseHeader("Date");

                //分割时间
                date1 = datetxt.Split(',');

            }
            catch (Exception ex)
            {
                throw ex;
            }

            //
            if (date1 ==null )
            {
                localtime = "网络验证失败,请重新启动或检查网络设置";
            }
            else if (date1.Length  < 1)
            {
                localtime = "网络验证失败,请重新启动或检查网络设置";
            }
            else
            {
                //将时间中的GMT去掉
                date2 = date1[1].Replace("GMT", "");
                
                //如: 08 Feb 2012 06:34:58 GMT
                date3 = date2.Split(' ');
                //如: 08 Feb 2012 06:34:58 

                switch (date3[2])
                {
                    case  "Jan":
                        mon = "01";
                        break;
                    case "Feb":
                        mon = "02";
                        break;
                    case "Mar":
                        mon = "03";
                        break;
                    case "Apr":
                        mon = "04";
                        break;
                    case "May":
                        mon = "05";
                        break;
                    case "Jun":
                        mon = "06";
                        break;
                    case "Jul":
                        mon = "07";
                        break;
                    case "Aug":
                        mon = "08";
                        break;
                    case "Sep":
                        mon = "09";
                        break;
                    case "Oct":
                        mon = "10";
                        break;
                    case "Nov":
                        mon = "11";
                        break;
                    case "Dec":
                        mon = "12";
                        break;
                }

                //最终反馈是日期和时间
                localtime = date3[3] + "/" + mon + "/" + date3[1] + " " + date3[4];

                //获取的协调世界时
                DateTime sTime = Convert.ToDateTime(localtime);

                //转换为当前计算机所处时区的时间,即东八区时间
               nTime = TimeZone.CurrentTimeZone.ToLocalTime(sTime);
            }
            objHttp = null;
            return nTime;
        }
        #endregion

        #region 获取标准北京时间3,速度500ms-1500ms
        /// <summary>
        /// [3]获取标准北京时间2 ,读取(xml)http://www.time.ac.cn/timeflash.asp?user=flash
        /// </summary>
        /// <returns></returns>
        public DateTime GetStandardTime()
        {
            #region  文件格式
            /// //<?xml version="1.0" encoding="GB2312" ?>             
            //- <ntsc>            
            //- <time>           
            //  <year>2011</year>        
            //  <month>7</month>        
            //  <day>10</day>          
            //  <Weekday />   
            //  <hour>19</hour>        
            //  <minite>45</minite>        
            //  <second>37</second>         
            //  <Millisecond />        
            //  </time>         
            //  </ntsc>    
            #endregion

            DateTime dt;
            WebRequest wrt = null;
            WebResponse wrp = null;
            try
            {
                wrt = WebRequest.Create("http://www.time.ac.cn/timeflash.asp?user=flash");
                wrt.Credentials = CredentialCache.DefaultCredentials;
                
                wrp = wrt.GetResponse();
                StreamReader sr = new StreamReader(wrp.GetResponseStream(), Encoding.UTF8);
                string html = sr.ReadToEnd();
                sr.Close();
                wrp.Close();
                
                //int yearIndex = html.IndexOf("<year>") ;
                //int secondIndex = html.IndexOf("</second>");
                //html = html.Substring(yearIndex, secondIndex - yearIndex);
                html = html.Substring(51, 109);

                string[] s1 = html.Split(new char[2] { '<', '>' });
                string year = s1[2];
                string month = s1[6];
                string day = s1[10];
                string hour = s1[18];
                string minite = s1[22];
                string second = s1[26];
                
                dt = DateTime.Parse(year + "-" + month + "-" + day + " " + hour + ":" + minite + ":" + second);
            }
            catch (WebException)
            {
                return DateTime.Parse("0001-1-1");
            }
            catch (Exception)
            {
                return DateTime.Parse("0001-1-1");
            }
            finally
            {
                if (wrp != null)
                    wrp.Close();
                if (wrt != null)
                    wrt.Abort();
            }
            return dt;
        }
        #endregion
                
        #region 访问标准校时服务器端口获取网络时间 速度:1000-2000ms
        /// <summary>
        /// 获取网络时间,通过标准校时服务器
        /// </summary>
        /// <param name="HostName">主机名</param>
        /// <param name="PortNum">端口号</param>
        /// <returns>DateTime</returns>
        public DateTime GetInternetTime(string HostName, int PortNum)
        {
            DateTime official, localtime;
            string returndata = null;
            string[] dates = new string[4];
            string[] times = new string[4];
            string[] tokens = new string[11];

            TcpClient tcpclient = new TcpClient();
            try
            {
                tcpclient.Connect(HostName, PortNum);

                NetworkStream networkStream = tcpclient.GetStream();
                if (networkStream.CanWrite && networkStream.CanRead)
                {
                    Byte[] sendBytes = Encoding.ASCII.GetBytes("Hello");
                    networkStream.Write(sendBytes, 0, sendBytes.Length);
                    byte[] bytes = new byte[tcpclient.ReceiveBufferSize];
                    networkStream.Read(bytes, 0, (int)tcpclient.ReceiveBufferSize);
                    returndata = Encoding.ASCII.GetString(bytes);
                }
                tcpclient.Close();
            }
            catch (Exception excep)
            {
                throw excep;
            }

            tokens = returndata.Split(' ');
            dates = tokens[1].Split('-');
            times = tokens[2].Split(':');

            official = new 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]));
            localtime = TimeZone.CurrentTimeZone.ToLocalTime(official);
            return localtime;

        }
        #endregion

    }

}


先说一下NetTime类,4个方法,

       第一个方法GetBeijingTime()速度最快,100ms的反应时间,快得没话说,不过在跟其他校时网比较时间时,它的时间比别的校时网站时间要提前10s。

       第二个方法GetNetTime(string Url),反应时间取决于你访问的网页,我这里用的是百度。通过查资料,百度的平均加载速度为:0.48s(2007年),而Google的加载速度为:0.48s(2007年0.87s)。这2个都可以,当然也可以用网易163或者其他的。推荐用这个。我用的Google,反应时间为200ms左右。完全可以满足你的一般需求。

       第三个方法GetStandardTime(),网站的加载速度为0.55s。但是处理起来有点费时,反应时间在500-1500ms。

       第四个方法GetInternetTime(string HostName,int PortNum),同样取决于授时服务器,我这里用的是time-a.timefreq.bldrdoc.gov,端口号为13,反应时间在1000-2000ms。

网络时间应用举例:

        private void timer2_Tick(object sender, EventArgs e)
        {
            //速度100ms           
            try
            {
                NetTime t = new NetTime();
                string time = t.GetBeijingTime().ToString();
                lblNetTime.Text = time;
            }
            catch (Exception ex)
            {
                lblNetTime.Text = ex.Message;
            }
            
        }

        private void timer3_Tick(object sender, EventArgs e)
        {
            //速度200ms           
            try
            {
                NetTime t = new NetTime();
                string time = t.GetNetTime("http://www.google.com.hk/").ToString();
                label3.Text = time;
            }
            catch (Exception ex)
            {                
                  label3.Text = ex.Message ;
            }         
        }

        private void timer4_Tick(object sender, EventArgs e)
        {
            //速度500-1500ms
            try
            {
                NetTime t = new NetTime();
                string time = t.GetStandardTime().ToString();
                label4.Text = time;
            }
            catch (Exception ex)
            {
                label4.Text = ex.Message;
            }
            
        }

        private void timer5_Tick(object sender, EventArgs e)
        {
            try
            {                
                NetTime t = new NetTime();
                string time = t.GetInternetTime("time-a.timefreq.bldrdoc.gov",13).ToString();
                label5.Text = time;
            }
            catch (Exception ex)
            {
                label5.Text = ex.Message;                
            }
        }


前面说系统和网络的双重验证,其实只要判断一下2者 在日期上不同,就用网络时间来纠正一下本地时间即可。

下面是系统时间类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace WebTime
{ 
    /// <summary>
    ///  系统时间结构
    /// </summary>
    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 wmilliseconds;    //毫秒

        /// <summary>
        /// 从System.DateTime转换。
        /// </summary>
        /// <param name="time">System.DateTime类型的时间。</param>
        public void fromDateTime(DateTime time)
        {
            wyear = (ushort)time.Year;
            wmonth = (ushort)time.Month;
            wdayofweek = (ushort)time.DayOfWeek;
            wday = (ushort)time.Day;
            whour = (ushort)time.Hour;
            wminute = (ushort)time.Minute;
            wsecond = (ushort)time.Second;
            wmilliseconds = (ushort)time.Millisecond;
        }


        /// <summary>
        /// 转换为system.DateTime类型。
        /// </summary>
        /// <returns></returns>
        public DateTime toDateTime()
        {
            return new DateTime(wyear, wmonth, wday, whour, wminute, wsecond, wmilliseconds);
        }

        /// <summary>
        /// 静态方法。转换为system.DateTime类型。
        /// </summary>
        /// <param name="time">systemtime类型的时间。</param>
        /// <returns></returns>
        public static DateTime toDateTime(SystemTime time)
        {
            return time.toDateTime();
        }
    }

    /// <summary>
    /// 系统时间类
    /// </summary>
    public class SysTime
    {
        [DllImport("Kernel32.dll ")]
        public static extern bool SetSystemTime(ref   SystemTime SystemTime);
        [DllImport("Kernel32.dll ")]
        public static extern void GetSystemTime(ref   SystemTime SystemTime);
    }
}

其中定义一个系统时间的结构体类型和一个类。SetSystemTime是来设置系统时间,GetSystemTime用来获取系统时间。

下面是用网络时间来校对系统时间的源码:

        private void btnCorretTime_Click(object sender, EventArgs e)
        {
            NetTime nt = new NetTime();

            //获取网络时间
            string time = nt.GetNetTime("http://www.google.com.hk/").ToString();

            DateTime t=Convert.ToDateTime(time);

 
            //实例化一个系统时间结构体对象
            SystemTime st = new SystemTime();

           
            //将当前计算机所在时区时间转化为协调世界时
            t = TimeZone.CurrentTimeZone.ToUniversalTime(t);

            st.fromDateTime(t);

            //修改系统时间
            SysTime.SetSystemTime(ref st);
            MessageBox.Show("时间改为"+ st.toDateTime().ToString());
        }


       所以只需要给项目系统添加一个通过网络时间来校对系统时间功能,而其他代码不用改,还是用系统时间,这样也符合了开闭原则。

转载的朋友请说明出处:http://blog.csdn.net/xiaoxian8023/article/details/7250385

目录
相关文章
|
3月前
|
监控 安全 网络安全
深入解析PDCERF:网络安全应急响应的六阶段方法
PDCERF是网络安全应急响应的六阶段方法,涵盖准备、检测、抑制、根除、恢复和跟进。本文详细解析各阶段目标与操作步骤,并附图例,助读者理解与应用,提升组织应对安全事件的能力。
535 89
|
22天前
|
缓存 数据中心 网络架构
5个减少网络延迟的简单方法
高速互联网对工作与娱乐至关重要,延迟和断线会严重影响效率和体验。本文探讨了导致连接缓慢的三个关键因素:吞吐量、带宽和延迟,并提供了减少延迟的实用方法。包括重启设备、关闭占用带宽的程序、使用有线连接、优化数据中心位置以及添加内容分发网络 (CDN) 等策略。虽然完全消除延迟不可能,但通过这些方法可显著改善网络性能。
187 7
|
29天前
|
机器学习/深度学习 数据安全/隐私保护
基于神经网络逆同步控制方法的两变频调速电机控制系统matlab仿真
本课题针对两电机变频调速系统,提出基于神经网络a阶逆系统的控制方法。通过构造原系统的逆模型,结合线性闭环调节器实现张力与速度的精确解耦控制,并在MATLAB2022a中完成仿真。该方法利用神经网络克服非线性系统的不确定性,适用于参数变化和负载扰动场景,提升同步控制精度与系统稳定性。核心内容涵盖系统原理、数学建模及神经网络逆同步控制策略,为工业自动化提供了一种高效解决方案。
|
1月前
|
Kubernetes Shell Windows
【Azure K8S | AKS】在AKS的节点中抓取目标POD的网络包方法分享
在AKS中遇到复杂网络问题时,可通过以下步骤进入特定POD抓取网络包进行分析:1. 使用`kubectl get pods`确认Pod所在Node;2. 通过`kubectl node-shell`登录Node;3. 使用`crictl ps`找到Pod的Container ID;4. 获取PID并使用`nsenter`进入Pod的网络空间;5. 在`/var/tmp`目录下使用`tcpdump`抓包。完成后按Ctrl+C停止抓包。
66 12
|
3月前
|
机器学习/深度学习 数据采集 人工智能
GeneralDyG:南洋理工推出通用动态图异常检测方法,支持社交网络、电商和网络安全
GeneralDyG 是南洋理工大学推出的通用动态图异常检测方法,通过时间 ego-graph 采样、图神经网络和时间感知 Transformer 模块,有效应对数据多样性、动态特征捕捉和计算成本高等挑战。
113 18
GeneralDyG:南洋理工推出通用动态图异常检测方法,支持社交网络、电商和网络安全
|
2月前
|
机器学习/深度学习 算法 文件存储
神经架构搜索:自动化设计神经网络的方法
在人工智能(AI)和深度学习(Deep Learning)快速发展的背景下,神经网络架构的设计已成为一个日益复杂而关键的任务。传统上,研究人员和工程师需要通过经验和反复试验来手动设计神经网络,耗费大量时间和计算资源。随着模型规模的不断扩大,这种方法显得愈加低效和不够灵活。为了解决这一挑战,神经架构搜索(Neural Architecture Search,NAS)应运而生,成为自动化设计神经网络的重要工具。
|
4月前
|
机器学习/深度学习 数据采集 人工智能
基于Huffman树的层次化Softmax:面向大规模神经网络的高效概率计算方法
层次化Softmax算法通过引入Huffman树结构,将传统Softmax的计算复杂度从线性降至对数级别,显著提升了大规模词汇表的训练效率。该算法不仅优化了计算效率,还在处理大规模离散分布问题上提供了新的思路。文章详细介绍了Huffman树的构建、节点编码、概率计算及基于Gensim的实现方法,并讨论了工程实现中的优化策略与应用实践。
112 15
基于Huffman树的层次化Softmax:面向大规模神经网络的高效概率计算方法
|
4月前
|
域名解析 缓存 网络协议
优化Lua-cURL:减少网络请求延迟的实用方法
优化Lua-cURL:减少网络请求延迟的实用方法
|
5月前
|
机器学习/深度学习 数据采集 算法
机器学习在医疗诊断中的前沿应用,包括神经网络、决策树和支持向量机等方法,及其在医学影像、疾病预测和基因数据分析中的具体应用
医疗诊断是医学的核心,其准确性和效率至关重要。本文探讨了机器学习在医疗诊断中的前沿应用,包括神经网络、决策树和支持向量机等方法,及其在医学影像、疾病预测和基因数据分析中的具体应用。文章还讨论了Python在构建机器学习模型中的作用,面临的挑战及应对策略,并展望了未来的发展趋势。
383 1
|
5月前
|
安全 算法 网络安全
量子计算与网络安全:保护数据的新方法
量子计算的崛起为网络安全带来了新的挑战和机遇。本文介绍了量子计算的基本原理,重点探讨了量子加密技术,如量子密钥分发(QKD)和量子签名,这些技术利用量子物理的特性,提供更高的安全性和可扩展性。未来,量子加密将在金融、政府通信等领域发挥重要作用,但仍需克服量子硬件不稳定性和算法优化等挑战。