C#通過NTP服務器獲取NTP時間

C#通過NTP服務器獲取NTP時間

注意事項:

  1. 如果NTP服務器地址是域名,如阿里云的NTP服務器地址。需要DNS解析。
  2. NTP使用UDP通訊,默認端口是123
  3. NTP經過很多年的發展,有4個版本號,目前常用的3和4。NTP區分客戶端和服務端,客戶端角色標志為3。
  4. NTP發送的時間戳是第41到48個字節。獲取到的字節需要轉為大端序列。
  5. NTP標準協議返回的時間是自1900.1.1 00:00:00開始的毫秒時間數值,需要字節轉換為你需要的日期時間。

以下是通過NTP服務器獲取NTP時間的代碼:

/// <summary>
/// 獲取NTP時間
/// </summary>
/// <param name="serverList"></param>
/// <param name="timeoutMilliseconds"></param>
/// <param name="isToLocal"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static async Task<DateTime> GetNtpTime(List<string> serverList, bool isToLocal = false, int timeoutMilliseconds = 2000)
{List<string> realServerList = new List<string>();bool needUseLastIp = false;if (serverList is null || !serverList.Any()){serverList = NtpServers;needUseLastIp = true;if (!string.IsNullOrEmpty(lastIpAddress)){realServerList.Add(lastIpAddress);if (serverList.Contains(lastIpAddress)){serverList.Remove(lastIpAddress);}}}realServerList.AddRange(serverList);Log.Information($"GetNtpTime realServerList: {JsonConvert.SerializeObject(realServerList)}");foreach (var server in realServerList){try{IPAddress? ipAddress;List<IPAddress> addressList = new List<IPAddress>();if (!IPAddress.TryParse(server, out ipAddress)){// 如果不是IP地址,則嘗試DNS解析try{var hostEntry = await Dns.GetHostEntryAsync(server);addressList = hostEntry.AddressList.ToList();}catch (Exception e){Log.Error($"DNS resolution failed: {e.Message} {e.StackTrace}");}}else{addressList.Add(ipAddress);}if (addressList is null || !addressList.Any()){continue;}foreach (var address in addressList){using (var client = new UdpClient()){client.Client.ReceiveTimeout = timeoutMilliseconds;client.Client.SendTimeout = timeoutMilliseconds;// 發送NTP請求var request = new byte[48];request[0] = 0x1B; // 設置版本號4,模式3(客戶端)var endPoint = new IPEndPoint(address, 123);client.Send(request, request.Length, endPoint);// 發送請求并接收響應var response = await client.ReceiveAsync();// 驗證響應數據長度if (response.Buffer.Length < 48 || !IsValidNtpResponse(response.Buffer))continue;// 解析時間戳(注意:BitConverter默認是小端,需要反轉)ulong intPart = BitConverter.ToUInt32(response.Buffer, 40);ulong fractPart = BitConverter.ToUInt32(response.Buffer, 44);// 轉換為大端序(NTP使用大端)intPart = SwapEndianness((uint)intPart);fractPart = SwapEndianness((uint)fractPart);// 計算總時間戳ulong ntpTimestamp = (intPart << 32) | (fractPart & 0xFFFFFFFF);double totalSeconds = (double)ntpTimestamp / (double)(1UL << 32);if (needUseLastIp){lastIpAddress = endPoint.Address.ToString();Log.Information($"記錄本次獲取NTP時間的IP為:{lastIpAddress}");}// 轉換為DateTimeDateTime epoch = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc);DateTime ntpTime = epoch.AddSeconds(totalSeconds);if (isToLocal){ntpTime = ntpTime.ToLocalTime();}return ntpTime;}}}catch (Exception ex){Log.Error($"連接服務器 {server} 失敗: {ex.Message} {ex.StackTrace}");continue;}}throw new Exception("所有NTP服務器均無法連接!");
}

獲取到的時間,如果需要自己進行時區轉換,可以通過C#代碼從電腦本機獲取到標準的時區列表,然后將獲取到的NTP時間加上時區的BaseUtcOffset,即可轉換到所需要的時區時間。
C#獲取時區列表代碼如下

var allZones = TimeZoneInfo.GetSystemTimeZones().ToList();

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/80745.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/80745.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/80745.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用cmd來創建數據庫和數據庫表-簡潔步驟

創建數據庫和表&#xff1a; 1. 按WinR打開“運行”&#xff0c;輸入cmd&#xff0c;回車 2. 登錄數據庫&#xff1a;mysql -u root -p 然后輸入密碼 3. 創建數據庫create database myblog; myblog為數據庫名(自定義你的數據庫名) &#xff01;注意分號不要漏了&#xff01; …

java工具類

LocalDateTime LocalDateTime可以獲取當前時間&#xff1a; LocalDateTime now LocalDateTime.now(); 同時他也可以獲取指定時間&#xff1a; LocalDateTime dateTime LocalDateTime.of(2023, 5, 15, 10, 30) 若我們時間值超出了我們的實際情況值&#xff0c;我們將會出現…

02_java的運行機制以及JDKJREJVM基本介紹

1、運行機制 2、JDK&JRE&JVM JDK 基本介紹 &#xff08;1&#xff09; JDK 的全稱(Java Development Kit Java開發工具包) JDK JRE java的開發工具 [ java, javac, javadoc, javap等 ] &#xff08;2&#xff09;JDK是提供給Java開發人員使用的&#xff0c;其…

【文心快碼】確實有點東西!

這里寫自定義目錄標題 背景 Electron 開發 Markdown 編輯器全記錄提問1&#xff1a;提問2&#xff1a;提問3&#xff1a;提問4&#xff1a;完整項目結構總結 背景 前兩天百度在2025 百度AI開發者大會"如何駕馭Coding Agent分會場"上發布了文心快碼&#xff0c;注冊試…

AI心理健康服務平臺項目面試實戰

AI心理健康服務平臺項目面試實戰 第一輪提問&#xff1a; 面試官&#xff1a; 請簡要介紹一下AI心理健康服務平臺的核心技術架構。在AI領域&#xff0c;心理健康服務的機遇主要體現在哪些方面&#xff1f;如何利用NLP技術提升用戶與AI的心理健康對話體驗&#xff1f; 馬架構…

Win10安裝 P104-100 驅動

安裝完之后總結一下, 之前做了不少功課, 在網上搜了很多教程, 視頻的文字的, 但是很多已經比較陳舊了. 最后發現的這個 GitHub 項目 NVIDIA-patcher 是最有用的, 因為這是現在這些魔改驅動的來源. NVIDIA-patcher 倉庫地址: https://github.com/dartraiden/NVIDIA-patcher 安…

把一個 PyTorch 的圖像張量轉換成 NumPy 格式,并按照正確的維度順序顯示出來

示例代碼&#xff1a; plt.imshow(np.transpose(tensor_denorm.numpy(), (1, 2, 0)))它的作用是&#xff1a;把一個 PyTorch 的圖像張量轉換成 NumPy 格式&#xff0c;并按照正確的維度順序顯示出來。 &#x1f680; 一步步解釋&#xff1a; ? tensor_denorm 這是一個形狀為…

【速寫】conda安裝(linux)

序言 昨天葉凱浩空降&#xff08;全馬241&#xff09;&#xff0c;降維打擊&#xff0c;10分24秒斷層奪冠。 夏瀟陽10分53秒絕殺小崔10分54秒第2&#xff0c;小崔第3&#xff0c;均配都在3’30"以內&#xff0c;即便我是去年巔峰期也很難跑出這種水平。我就知道他去年大…

算法題(135):唯一的雪花

審題&#xff1a; 本題需要我們對于每一組數據都找出最大的包裹大小 思路&#xff1a; 本題解析題目意思后我們可以把雪花的編號當成數組中元素的值&#xff0c;把包裹看成一個區間。 本質上就是讓我們找出一組數據中&#xff0c;所有子段中最長的子段。 方法一&#xff1a;暴力…

算法習題-力扣446周賽題解

算法可以調度思維&#xff0c;讓程序員的思維發散&#xff0c;找到更好的解決方案。 第一題&#xff1a;執行指令后的得分 題目&#xff1a; 給你兩個數組&#xff1a;instructions 和 values&#xff0c;數組的長度均為 n。你需要根據以下規則模擬一個過程&#xff1a; 從下標…

Ubuntu下MySQL的安裝

Ubuntu下MySQL的安裝 1. 查看當前操作系統版本2. 添加MySQL APT源2.1 訪問下載頁面&#xff0c;并下載發布包2.2 執行安裝指令2.3 安裝MySQL 3. 查看MySQL狀態4. 設置開機自啟動 1. 查看當前操作系統版本 通過命令lsb_release -a查看&#xff1a; 2. 添加MySQL APT源 2.1 訪問下…

航順 芯片 開發記錄 (一) 2025年4月27日19:23:32

芯片型號: HK32F030MF4P6 第一步:創建工程目錄 inc :頭文件目錄 MDK-ARM : 工程根目錄 (新建工程選擇該目錄) src :相關資源存放位置 官方函數庫相關內容 官方函數庫大致結構圖 ├─HK32F030MLib ├─CMSIS │ ├─CM0 │ │ └─Core │ │ arm_common_table…

Python 數據可視化進階:精準插入圖表到指定 Excel 工作表

Python 數據可視化進階&#xff1a;精準插入圖表到指定 Excel 工作表 在處理數據的過程中&#xff0c;我們常常需要將生成的圖表精準地插入到已存在數據的 Excel 文件的指定工作表中。借助 Python 的強大庫組合&#xff0c;這一操作得以高效實現。以下是經過優化和注釋補充的代…

集成方案 | Docusign + 甄零科技,賦能企業海外業務高效增長!

本文將詳細介紹 Docusign 與甄零科技的集成步驟及其效果&#xff0c;并通過實際應用場景來展示 Docusign 的強大集成能力&#xff0c;以證明 Docusign 集成功能的高效性和實用性。 甄零科技是一家專注于數字化合同管理系統的 SaaS 解決方案提供商&#xff0c;致力于為企業打造“…

00-算法打卡-目錄

1 數組 01-算法打卡-數組-二分查找-leetcode(704)-第一天-CSDN博客 02-算法打卡-數組-二分查找-leetcode(35)-第二天-CSDN博客 03-算法打卡-數組-二分查找-leetcode(34)-第三天_leetcode 34-CSDN博客 04-算法打卡-數組-二分查找-leetcode(69)-第四天-CSDN博客 05-算法打卡-數組…

劍指Offer(數據結構與算法面試題精講)C++版——day21

劍指Offer&#xff08;數據結構與算法面試題精講&#xff09;C版——day21 題目一&#xff1a;數據流的第k大數字題目二&#xff1a;出現頻率最高的k個數字題目三&#xff1a;和最小的k個數對附錄&#xff1a;源碼gitee倉庫 題目一&#xff1a;數據流的第k大數字 題目&#xff…

NCCL非阻塞non-blocking實現

NCCL (NVIDIA Collective Communications Library) 主要設計用于高性能的集體通信&#xff08;如all-reduce、broadcast等&#xff09;&#xff0c;但其核心函數默認是阻塞式的&#xff08;blocking&#xff09;&#xff0c;即函數返回時操作已完成。不過&#xff0c;你可以通過…

代碼隨想錄算法訓練營第60期第二十天打卡

大家好&#xff0c;今天我們繼續進入二叉樹的章節&#xff0c;二叉樹章節應該已經過半了&#xff0c;大家再堅持一下&#xff0c;那么廢話不多說&#xff0c;我們繼續今天的內容。 第一題對應力扣編號為235的二叉搜索樹的最近公共祖先 其實我們上次任務就接觸過了二叉樹的最近…

8.0 西門子PLC的S7通訊解析

PC與西門子PLC的S7通訊主要有如下幾個步驟: 1. TCP的三次握手(由Socket對象自動完成) 2.發送訪問請求:COTP 3. 交換通訊信息:setup Commnunication 一、發送訪問請求:COTP 比如向PLC請求+以及PLC返回響應的一個實際例子如下: 發送PLC:----> 03 00 00 16 11 E0 …

Nacos-SpringBoot 配置無法自動刷新問題排查

背景 Nacos SpringBoot版本中&#xff0c;提供了NacosValue注解&#xff0c;支持控制臺修改值時&#xff0c;自動刷新&#xff0c;但是今天遇見了無法自動刷新的問題。 環境 SpringBoot 2.2.x nacos-client&#xff1a;2.1.0 nacos-config-spring-boot-starter&#xff1a;0…