• 多方法获取网络时间


    转自:http://blog.csdn.net/xiaoxian8023/article/details/7250385

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

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

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

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

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

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

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

    [csharp] view plaincopy
    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.Linq;  
    4. using System.Text;  
    5. using MSXML2;  
    6. using System.IO;  
    7. using System.Net;  
    8. using System.Net.Sockets;  
    9. using System.Text.RegularExpressions;  
    10. using System.IO.Compression;  
    11. using System.Xml;  
    12.   
    13.   
    14. namespace WebTime  
    15. {  
    16.     /// <summary>  
    17.     /// 网络时间  
    18.     /// </summary>  
    19.     public class NetTime  
    20.     {  
    21.         #region 获取标准北京时间1 速度100ms  
    22.         /// <summary>  
    23.         /// [1].获取标准北京时间1,读取http://www.beijing-time.org/time.asp  
    24.         /// </summary>  
    25.         /// <returns></returns>  
    26.         public  DateTime GetBeijingTime()  
    27.         {  
    28.             #region  格式  
    29.             // t0=new Date().getTime(); nyear=2012; nmonth=2; nday=11;  
    30.             // nwday=6; nhrs=0; nmin=23; nsec=0;     
    31.             #endregion  
    32.             DateTime dt;  
    33.             WebRequest wrt = null;  
    34.             WebResponse wrp = null;  
    35.             try  
    36.             {  
    37.                 wrt = WebRequest.Create("http://www.beijing-time.org/time.asp");  
    38.                 wrp = wrt.GetResponse();  
    39.   
    40.                 string html = string.Empty;  
    41.                 using (Stream stream = wrp.GetResponseStream())  
    42.                 {  
    43.                     using (StreamReader sr = new StreamReader(stream, Encoding.UTF8))  
    44.                     {  
    45.                         html = sr.ReadToEnd();  
    46.                     }  
    47.                 }  
    48.   
    49.                 string[] tempArray = html.Split(';');  
    50.                 for (int i = 0; i < tempArray.Length; i++)  
    51.                 {  
    52.                     tempArray[i] = tempArray[i].Replace(" ", "");  
    53.                 }  
    54.   
    55.                 string year = tempArray[1].Split('=')[1];  
    56.                 string month = tempArray[2].Split('=')[1];  
    57.                 string day = tempArray[3].Split('=')[1];  
    58.                 string hour = tempArray[5].Split('=')[1];  
    59.                 string minite = tempArray[6].Split('=')[1];  
    60.                 string second = tempArray[7].Split('=')[1];  
    61.                 //for (int i = 0; i < tempArray.Length; i++)  
    62.                 //{  
    63.                 //    tempArray[i] = tempArray[i].Replace(" ", "");  
    64.                 //}  
    65.   
    66.                 //string year = tempArray[1].Substring(tempArray[1].IndexOf("nyear=") + 6);  
    67.                 //string month = tempArray[2].Substring(tempArray[2].IndexOf("nmonth=") + 7);  
    68.                 //string day = tempArray[3].Substring(tempArray[3].IndexOf("nday=") + 5);  
    69.                 //string hour = tempArray[5].Substring(tempArray[5].IndexOf("nhrs=") + 5);  
    70.                 //string minite = tempArray[6].Substring(tempArray[6].IndexOf("nmin=") + 5);  
    71.                 //string second = tempArray[7].Substring(tempArray[7].IndexOf("nsec=") + 5);  
    72.                 dt = DateTime.Parse(year + "-" + month + "-" + day + " " + hour + ":" + minite + ":" + second);  
    73.             }  
    74.             catch (WebException)  
    75.             {  
    76.                 return DateTime.Parse("2011-1-1");  
    77.             }  
    78.             catch (Exception)  
    79.             {  
    80.                 return DateTime.Parse("2011-1-1");  
    81.             }  
    82.             finally  
    83.             {  
    84.                 if (wrp != null)  
    85.                     wrp.Close();  
    86.                 if (wrt != null)  
    87.                     wrt.Abort();  
    88.             }  
    89.             return dt;  
    90.         }  
    91.         #endregion  
    92.  
    93.         #region 获取网站响应请求的时间,速度200ms  
    94.         /// <summary>  
    95.         /// [2]获取网站响应请求的时间,速度200ms  
    96.         /// </summary>  
    97.         /// <param name="hUrl">网址</param>  
    98.         /// <returns>DateTime</returns>  
    99.         /// <remarks></remarks>  
    100.         public DateTime GetNetTime( string hUrl)  
    101.         {  
    102.             string datetxt = null;         //请求回应的时间  
    103.             string[] date1 = null;         //分割后的星期和日期  
    104.             string date2 = "";              //分割后的日期和GMT  
    105.             string[] date3 = null;         //最终成型的日期  
    106.             DateTime nTime  =DateTime.Today ;   
    107.             string localtime = "";  
    108.             string mon = "";  
    109.   
    110.             XMLHTTP objHttp = new XMLHTTP();  
    111.   
    112.             objHttp.open("GET", hUrl, false);  
    113.   
    114.             try  
    115.             {  
    116.                 objHttp.send();  
    117.   
    118.                 //获取网站回应请求的日期时间。如: Wed, 08 Feb 2012 06:34:58 GMT  
    119.                 datetxt = objHttp.getResponseHeader("Date");  
    120.   
    121.                 //分割时间  
    122.                 date1 = datetxt.Split(',');  
    123.   
    124.             }  
    125.             catch (Exception ex)  
    126.             {  
    127.                 throw ex;  
    128.             }  
    129.   
    130.             //  
    131.             if (date1 ==null )  
    132.             {  
    133.                 localtime = "网络验证失败,请重新启动或检查网络设置";  
    134.             }  
    135.             else if (date1.Length  < 1)  
    136.             {  
    137.                 localtime = "网络验证失败,请重新启动或检查网络设置";  
    138.             }  
    139.             else  
    140.             {  
    141.                 //将时间中的GMT去掉  
    142.                 date2 = date1[1].Replace("GMT", "");  
    143.                   
    144.                 //如: 08 Feb 2012 06:34:58 GMT  
    145.                 date3 = date2.Split(' ');  
    146.                 //如: 08 Feb 2012 06:34:58   
    147.   
    148.                 switch (date3[2])  
    149.                 {  
    150.                     case  "Jan":  
    151.                         mon = "01";  
    152.                         break;  
    153.                     case "Feb":  
    154.                         mon = "02";  
    155.                         break;  
    156.                     case "Mar":  
    157.                         mon = "03";  
    158.                         break;  
    159.                     case "Apr":  
    160.                         mon = "04";  
    161.                         break;  
    162.                     case "May":  
    163.                         mon = "05";  
    164.                         break;  
    165.                     case "Jun":  
    166.                         mon = "06";  
    167.                         break;  
    168.                     case "Jul":  
    169.                         mon = "07";  
    170.                         break;  
    171.                     case "Aug":  
    172.                         mon = "08";  
    173.                         break;  
    174.                     case "Sep":  
    175.                         mon = "09";  
    176.                         break;  
    177.                     case "Oct":  
    178.                         mon = "10";  
    179.                         break;  
    180.                     case "Nov":  
    181.                         mon = "11";  
    182.                         break;  
    183.                     case "Dec":  
    184.                         mon = "12";  
    185.                         break;  
    186.                 }  
    187.   
    188.                 //最终反馈是日期和时间  
    189.                 localtime = date3[3] + "/" + mon + "/" + date3[1] + " " + date3[4];  
    190.   
    191.                 //获取的协调世界时  
    192.                 DateTime sTime = Convert.ToDateTime(localtime);  
    193.   
    194.                 //转换为当前计算机所处时区的时间,即东八区时间  
    195.                nTime = TimeZone.CurrentTimeZone.ToLocalTime(sTime);  
    196.             }  
    197.             objHttp = null;  
    198.             return nTime;  
    199.         }  
    200.         #endregion  
    201.  
    202.         #region 获取标准北京时间3,速度500ms-1500ms  
    203.         /// <summary>  
    204.         /// [3]获取标准北京时间2 ,读取(xml)http://www.time.ac.cn/timeflash.asp?user=flash  
    205.         /// </summary>  
    206.         /// <returns></returns>  
    207.         public DateTime GetStandardTime()  
    208.         {  
    209.             #region  文件格式  
    210.             /// //<?xml version="1.0" encoding="GB2312" ?>               
    211.             //- <ntsc>              
    212.             //- <time>             
    213.             //  <year>2011</year>          
    214.             //  <month>7</month>          
    215.             //  <day>10</day>            
    216.             //  <Weekday />     
    217.             //  <hour>19</hour>          
    218.             //  <minite>45</minite>          
    219.             //  <second>37</second>           
    220.             //  <Millisecond />          
    221.             //  </time>           
    222.             //  </ntsc>      
    223.             #endregion  
    224.   
    225.             DateTime dt;  
    226.             WebRequest wrt = null;  
    227.             WebResponse wrp = null;  
    228.             try  
    229.             {  
    230.                 wrt = WebRequest.Create("http://www.time.ac.cn/timeflash.asp?user=flash");  
    231.                 wrt.Credentials = CredentialCache.DefaultCredentials;  
    232.                   
    233.                 wrp = wrt.GetResponse();  
    234.                 StreamReader sr = new StreamReader(wrp.GetResponseStream(), Encoding.UTF8);  
    235.                 string html = sr.ReadToEnd();  
    236.                 sr.Close();  
    237.                 wrp.Close();  
    238.                   
    239.                 //int yearIndex = html.IndexOf("<year>") ;  
    240.                 //int secondIndex = html.IndexOf("</second>");  
    241.                 //html = html.Substring(yearIndex, secondIndex - yearIndex);  
    242.                 html = html.Substring(51, 109);  
    243.   
    244.                 string[] s1 = html.Split(new char[2] { '<', '>' });  
    245.                 string year = s1[2];  
    246.                 string month = s1[6];  
    247.                 string day = s1[10];  
    248.                 string hour = s1[18];  
    249.                 string minite = s1[22];  
    250.                 string second = s1[26];  
    251.                   
    252.                 dt = DateTime.Parse(year + "-" + month + "-" + day + " " + hour + ":" + minite + ":" + second);  
    253.             }  
    254.             catch (WebException)  
    255.             {  
    256.                 return DateTime.Parse("0001-1-1");  
    257.             }  
    258.             catch (Exception)  
    259.             {  
    260.                 return DateTime.Parse("0001-1-1");  
    261.             }  
    262.             finally  
    263.             {  
    264.                 if (wrp != null)  
    265.                     wrp.Close();  
    266.                 if (wrt != null)  
    267.                     wrt.Abort();  
    268.             }  
    269.             return dt;  
    270.         }  
    271.         #endregion  
    272.                  
    273.         #region 访问标准校时服务器端口获取网络时间 速度:1000-2000ms  
    274.         /// <summary>  
    275.         /// 获取网络时间,通过标准校时服务器  
    276.         /// </summary>  
    277.         /// <param name="HostName">主机名</param>  
    278.         /// <param name="PortNum">端口号</param>  
    279.         /// <returns>DateTime</returns>  
    280.         public DateTime GetInternetTime(string HostName, int PortNum)  
    281.         {  
    282.             DateTime official, localtime;  
    283.             string returndata = null;  
    284.             string[] dates = new string[4];  
    285.             string[] times = new string[4];  
    286.             string[] tokens = new string[11];  
    287.   
    288.             TcpClient tcpclient = new TcpClient();  
    289.             try  
    290.             {  
    291.                 tcpclient.Connect(HostName, PortNum);  
    292.   
    293.                 NetworkStream networkStream = tcpclient.GetStream();  
    294.                 if (networkStream.CanWrite && networkStream.CanRead)  
    295.                 {  
    296.                     Byte[] sendBytes = Encoding.ASCII.GetBytes("Hello");  
    297.                     networkStream.Write(sendBytes, 0, sendBytes.Length);  
    298.                     byte[] bytes = new byte[tcpclient.ReceiveBufferSize];  
    299.                     networkStream.Read(bytes, 0, (int)tcpclient.ReceiveBufferSize);  
    300.                     returndata = Encoding.ASCII.GetString(bytes);  
    301.                 }  
    302.                 tcpclient.Close();  
    303.             }  
    304.             catch (Exception excep)  
    305.             {  
    306.                 throw excep;  
    307.             }  
    308.   
    309.             tokens = returndata.Split(' ');  
    310.             dates = tokens[1].Split('-');  
    311.             times = tokens[2].Split(':');  
    312.   
    313.             official = new DateTime(Int32.Parse(dates[0]) + 2000, Int32.Parse(dates[1]), Int32.Parse(dates[2]),  
    314.                     Int32.Parse(times[0]), Int32.Parse(times[1]), Int32.Parse(times[2]));  
    315.             localtime = TimeZone.CurrentTimeZone.ToLocalTime(official);  
    316.             return localtime;  
    317.   
    318.         }  
    319.         #endregion  
    320.   
    321.     }  
    322.   
    323. }  


    先说一下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。

    网络时间应用举例:

    [csharp] view plaincopy
    1. private void timer2_Tick(object sender, EventArgs e)  
    2. {  
    3.     //速度100ms             
    4.     try  
    5.     {  
    6.         NetTime t = new NetTime();  
    7.         string time = t.GetBeijingTime().ToString();  
    8.         lblNetTime.Text = time;  
    9.     }  
    10.     catch (Exception ex)  
    11.     {  
    12.         lblNetTime.Text = ex.Message;  
    13.     }  
    14.       
    15. }  
    16.   
    17. private void timer3_Tick(object sender, EventArgs e)  
    18. {  
    19.     //速度200ms             
    20.     try  
    21.     {  
    22.         NetTime t = new NetTime();  
    23.         string time = t.GetNetTime("http://www.google.com.hk/").ToString();  
    24.         label3.Text = time;  
    25.     }  
    26.     catch (Exception ex)  
    27.     {                  
    28.           label3.Text = ex.Message ;  
    29.     }           
    30. }  
    31.   
    32. private void timer4_Tick(object sender, EventArgs e)  
    33. {  
    34.     //速度500-1500ms  
    35.     try  
    36.     {  
    37.         NetTime t = new NetTime();  
    38.         string time = t.GetStandardTime().ToString();  
    39.         label4.Text = time;  
    40.     }  
    41.     catch (Exception ex)  
    42.     {  
    43.         label4.Text = ex.Message;  
    44.     }  
    45.       
    46. }  
    47.   
    48. private void timer5_Tick(object sender, EventArgs e)  
    49. {  
    50.     try  
    51.     {                  
    52.         NetTime t = new NetTime();  
    53.         string time = t.GetInternetTime("time-a.timefreq.bldrdoc.gov",13).ToString();  
    54.         label5.Text = time;  
    55.     }  
    56.     catch (Exception ex)  
    57.     {  
    58.         label5.Text = ex.Message;                  
    59.     }  
    60. }  


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

    下面是系统时间类

    [csharp] view plaincopy
    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.Linq;  
    4. using System.Text;  
    5. using System.Runtime.InteropServices;  
    6.   
    7. namespace WebTime  
    8. {   
    9.     /// <summary>  
    10.     ///  系统时间结构  
    11.     /// </summary>  
    12.     public struct SystemTime  
    13.     {  
    14.         public ushort wyear;            //年  
    15.         public ushort wmonth;           //月  
    16.         public ushort wdayofweek;       //星期  
    17.         public ushort wday;             //日  
    18.         public ushort whour;            //时  
    19.         public ushort wminute;          //分  
    20.         public ushort wsecond;          //秒  
    21.         public ushort wmilliseconds;    //毫秒  
    22.   
    23.         /// <summary>  
    24.         /// 从System.DateTime转换。  
    25.         /// </summary>  
    26.         /// <param name="time">System.DateTime类型的时间。</param>  
    27.         public void fromDateTime(DateTime time)  
    28.         {  
    29.             wyear = (ushort)time.Year;  
    30.             wmonth = (ushort)time.Month;  
    31.             wdayofweek = (ushort)time.DayOfWeek;  
    32.             wday = (ushort)time.Day;  
    33.             whour = (ushort)time.Hour;  
    34.             wminute = (ushort)time.Minute;  
    35.             wsecond = (ushort)time.Second;  
    36.             wmilliseconds = (ushort)time.Millisecond;  
    37.         }  
    38.   
    39.   
    40.         /// <summary>  
    41.         /// 转换为system.DateTime类型。  
    42.         /// </summary>  
    43.         /// <returns></returns>  
    44.         public DateTime toDateTime()  
    45.         {  
    46.             return new DateTime(wyear, wmonth, wday, whour, wminute, wsecond, wmilliseconds);  
    47.         }  
    48.   
    49.         /// <summary>  
    50.         /// 静态方法。转换为system.DateTime类型。  
    51.         /// </summary>  
    52.         /// <param name="time">systemtime类型的时间。</param>  
    53.         /// <returns></returns>  
    54.         public static DateTime toDateTime(SystemTime time)  
    55.         {  
    56.             return time.toDateTime();  
    57.         }  
    58.     }  
    59.   
    60.     /// <summary>  
    61.     /// 系统时间类  
    62.     /// </summary>  
    63.     public class SysTime  
    64.     {  
    65.         [DllImport("Kernel32.dll ")]  
    66.         public static extern bool SetSystemTime(ref   SystemTime SystemTime);  
    67.         [DllImport("Kernel32.dll ")]  
    68.         public static extern void GetSystemTime(ref   SystemTime SystemTime);  
    69.     }  
    70. }  

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

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

    [csharp] view plaincopy
    1. private void btnCorretTime_Click(object sender, EventArgs e)  
    2. {  
    3.     NetTime nt = new NetTime();  
    4.   
    5.     //获取网络时间  
    6.     string time = nt.GetNetTime("http://www.google.com.hk/").ToString();  
    7.   
    8.     DateTime t=Convert.ToDateTime(time);  
    9.   
    10.   
    11.     //实例化一个系统时间结构体对象  
    12.     SystemTime st = new SystemTime();  
    13.   
    14.      
    15.     //将当前计算机所在时区时间转化为协调世界时  
    16.     t = TimeZone.CurrentTimeZone.ToUniversalTime(t);  
    17.   
    18.     st.fromDateTime(t);  
    19.   
    20.     //修改系统时间  
    21.     SysTime.SetSystemTime(ref st);  
    22.     MessageBox.Show("时间改为"+ st.toDateTime().ToString());  
    23. }  


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

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

  • 相关阅读:
    分模块开发创建service子模块——(八)
    分模块开发创建dao子模块——(七)
    分模块开发创建父工程——(六)
    Html设置html与body元素高度问题
    原生JS给元素添加class属性
    【雪花点】雪花点的显示——(二)
    【雪花点】雪花点的显示——(一)
    Dom4j用Xpath获取节点——(六)
    Dom4j向XML中指定位置添加、删除、修改节点——(五)
    [置顶] 详细解读:技术有没有前途之分
  • 原文地址:https://www.cnblogs.com/zhxwaaa/p/4471636.html
Copyright © 2020-2023  润新知