我們都知道,NTP透過UDP協定與Port 123來進行操作,而UDP本身機制實在是太弱了,非常容易遭受到DDoS阻斷式服務的攻擊,因此這個管道常常會被網管人員封鎖掉。這篇文章試著使用C#搭配InterOP與HTTP,來進行遠端的時間查詢(非透過NTP機制)與設定本地端的時間。
我們這次使用的機制是採用TimeAndDate TAIWAN TAIPEI所提供的資訊,解析其網頁下,發現有一個WebRequest會傳送UTC資訊的時間,這就是我們採用的基礎啦!
有了正確的來源後,一切不再是問題,因此我們所需要的只剩將UTC轉GMT,並且轉換到+8時區(TimeZone: Taipei, Taiwan),然後去設定到本地端時間即可。程式碼如下:
using System; using System.Runtime.InteropServices; using static System.Console; namespace SimplyConsole { class Program { [DllImport("kernel32.dll")] private extern static uint SetSystemTime(ref SYSTEMTIME lpSystemTime); private 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; } static void Main(string[] args) { System.Timers.Timer oTimer = new System.Timers.Timer() { Interval = 1000 }; oTimer.Elapsed += OnRefresh; Console.CursorVisible = false; WriteLine(); WriteLine("Press any key to exit ..."); oTimer.Start(); ReadKey(); oTimer.Stop(); oTimer = null; } static void OnRefresh(Object sender, EventArgs args) { System.DateTime oUTC = new System.DateTime(1970, 1, 1, 0, 0, 0, System.DateTimeKind.Utc).AddSeconds(getUtcTimeStamp()); //如果年分是錯的,表示網路回應有問題,那就跳出不進行更新 if (oUTC.Year == 1970) { return; } System.DateTime oGMT = System.TimeZoneInfo.ConvertTime(oUTC, System.TimeZoneInfo.FindSystemTimeZoneById("Taipei Standard Time")); //設定 SYSTEMTIME oTime = new SYSTEMTIME(); oTime.wYear = System.Convert.ToUInt16(oUTC.Year); oTime.wMonth = System.Convert.ToUInt16(oUTC.Month); oTime.wDay = System.Convert.ToUInt16(oUTC.Day); oTime.wHour = System.Convert.ToUInt16(oUTC.Hour); oTime.wMinute = System.Convert.ToUInt16(oUTC.Minute); oTime.wSecond = System.Convert.ToUInt16(oUTC.Second); oTime.wMilliseconds = System.Convert.ToUInt16(oUTC.Millisecond); SetSystemTime(ref oTime); //輸出 Console.CursorTop = 0; Console.CursorLeft = 0; Write($"NowTime: {oGMT.ToString("yyyy-MM-dd HH:mm:ss")}"); } static double getUtcTimeStamp() { System.Net.HttpWebRequest oWRq = (System.Net.HttpWebRequest)System.Net.WebRequest.Create("http://www.timeanddate.com/scripts/ts.php?ut=1443508040915"); //設定網路對接逾時秒數 oWRq.Timeout = 1000; try { System.Net.HttpWebResponse oWRp = (System.Net.HttpWebResponse)oWRq.GetResponse(); using (System.IO.StreamReader oSR = new System.IO.StreamReader(oWRp.GetResponseStream(), System.Text.Encoding.UTF8)) { string cUTC = oSR.ReadToEnd(); if (cUTC.IndexOf(".") != -1 cUTC.IndexOf(" ") != -1) { return System.Convert.ToDouble(cUTC.Split(' ')[0]); } else { return 0.0; } } } catch { return 0.0; } } } }
在這裡將檔案包裝成exe,放到網路上方便您使用。依存.NET Framework 4.6,執行時請使用系統管理權限(在該執行檔案上方按右鍵)。
C# SyncSystemTimeViaHTTP NTPClient NTPServer TimeSync