首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Windows系統時間網絡同步:基於RFC 868時間協議的C++實現

     編輯:關於C語言

背景與協議

本文實現基於RFC 868「Time Protocol」的系統時間同步客戶端。協議極簡:TCP連接端口37,服務器發送4字節大端序無符號長整型,表示自1900-01-01 00:00:00 UTC以來的秒數。無需請求,連接即得時間。

核心技術難點

1. 時間基準轉換:1900紀元 → Windows FILETIME

Windows FILETIME 以1601-01-01為紀元,100納秒為單位。轉換鏈路:

ULONG ulTime (秒, 1900紀元)
  → SYSTEMTIME (1900-01-01 00:00:00)
  → FILETIME (1601紀元, 100ns單位)
  → 加上 ulTime * 10,000,000 (1秒 = 10^7 * 100ns)
  → SYSTEMTIME (目標時間)
  → SetSystemTime()

2. 關鍵代碼實現

void setTimeFromTP(ULONG ulTime) {
    FILETIME ft;
    SYSTEMTIME st = {1900, 1, 0, 1, 0, 0, 0, 0};  // 1900-01-01
    
    SystemTimeToFileTime(&st, &ft);
    LONGLONG* pLLong = (LONGLONG*)&ft;
    *pLLong += (LONGLONG)10000000 * ulTime;  // 秒轉100ns單位
    FileTimeToSystemTime(&ft, &st);
    ::SetSystemTime(&st);
}

3. 網絡通信與字節序

SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in servAddr = {AF_INET, htons(37), inet_addr("69.25.96.13")};
connect(s, (sockaddr*)&servAddr, sizeof(servAddr));

ULONG ulTime = 0;
recv(s, (char*)&ulTime, sizeof(ulTime), 0);
ulTime = ntohl(ulTime);  // 網絡序(大端) → 主機序(小端)
setTimeFromTP(ulTime);

工程踩坑記錄

  • 服務器選擇:註釋明確警告避開210.72.145.44(國內常不返回),推薦69.25.96.13
  • 權限問題:SetSystemTime 需要管理員權限/SE_SYSTEMTIME_NAME特權
  • 精度限制:協議只精確到秒,不適合高精度場景(需用NTP/PTP)
  • Y2.038K問題:32位無符號整型在2036年2月7日溢出,長期項目應遷移NTPv4

現代替代方案對比

協議精度複雜度適用場景
RFC 868 Time1秒極低嵌入式、舊系統、簡單同步
NTP (RFC 5905)毫秒級中等通用服務器/桌面
PTP (IEEE 1588)亞微秒級高金融、電信、工控

總結

這個百行代碼完整演示了「協議理解 → 時間制轉換 → 網絡編程 → 系統調用」的全鏈路。雖然RFC 868已過時,但其簡潔性使其成為學習網絡時間同步、Windows時間API、字節序處理的絕佳教具。生產環境請優先選用NTP庫(如Windows Time Service、chrony、ntpd)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved