利用 Winsock 連接 NTP 伺服器(如 time.windows.com:123 端口),接收 64 位時間戳(高 32 位秒數,低 32 位分數秒),轉換為 SYSTEMTIME 並調用 SetSystemTime 校正本地時鐘。需管理員權限。
WSAStartup 初始化 Winsock。SOCK_DGRAM) 連接 NTP 伺服器 123 端口。Transmit Timestamp(偏移 40 字節)。FILETIME 起始於 1601-01-01,需換算:FILETIME = (NTP秒數 - 1900到1601的秒差) * 10^7。FileTimeToSystemTime → SetSystemTime。#include <WinSock2.h>
#include <iostream>
#pragma comment(lib, "ws2_32.lib")
int main() {
WSADATA wsa; WSAStartup(MAKEWORD(2,2), &wsa);
SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
sockaddr_in server; server.sin_family = AF_INET;
server.sin_port = htons(123);
server.sin_addr.s_addr = inet_addr("132.163.96.1"); // time-a.nist.gov
// NTP 請求封包
char pkt[48] = {0}; pkt[0] = 0x1B; // LI=0, VN=3, Mode=3
sendto(s, pkt, 48, 0, (sockaddr*)&server, sizeof(server));
// 接收回應
recvfrom(s, pkt, 48, 0, NULL, NULL);
ULONG ntpSecs = ntohl(*(ULONG*)(pkt + 40)); // Transmit Timestamp 秒部分
// 轉換為 FILETIME
const ULONGLONG SEC_1601_TO_1900 = 11644473600ULL; // 1601 到 1900 的秒數
ULONGLONG ft = (ULONGLONG)(ntpSecs - SEC_1601_TO_1900) * 10000000ULL;
FILETIME fileTime; *(ULONGLONG*)&fileTime = ft;
SYSTEMTIME sysTime; FileTimeToSystemTime(&fileTime, &sysTime);
SetSystemTime(&sysTime);
std::cout << "Time synchronized." << std::endl;
closesocket(s); WSACleanup(); return 0;
}
SetSystemTime 需 SE_SYSTEMTIME_NAME 特權)。w32time 服務已實現完整 NTP 客戶端,一般無需自行開發。