網路校時服務讓電腦自動同步標準時間。RFC 868 (Time Protocol) 是最簡單的協定:伺服器監聽 Port 37,回傳自 1900-01-01 00:00:00 UTC 至今的秒數 (32-bit 無號整數)。本文示範 VC++ 實作 TCP/UDP 雙模式客戶端,含系統時間設定、多伺服器輪詢容錯。
BOOL GetRemoteTime(char* szServer, unsigned long& ulTime) {
SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0); // UDP
if (sock == INVALID_SOCKET) return FALSE;
sockaddr_in addr; addr.sin_family = AF_INET;
addr.sin_port = htons(37); // RFC 868 Port
addr.sin_addr.s_addr = inet_addr(szServer);
unsigned long dummy = 0;
// 送出空封包 (4 bytes)
if (sendto(sock, (char*)&dummy, 4, 0, (sockaddr*)&addr, sizeof(addr)) != 4) {
closesocket(sock); return FALSE;
}
// 非阻塞等待回應 (Timeout 3 秒)
unsigned long flag = 1;
ioctlsocket(sock, FIONBIO, &flag);
fd_set fds; FD_ZERO(&fds); FD_SET(sock, &fds);
timeval tv = {3, 0};
if (select(0, &fds, NULL, NULL, &tv) == 1) {
if (recv(sock, (char*)&ulTime, 4, 0) == 4) {
ulTime = ntohl(ulTime); // 網路序轉主機序
closesocket(sock); return TRUE;
}
}
closesocket(sock); return FALSE;
}
void MySetTime(unsigned long ulTime) {
FILETIME ft; SYSTEMTIME st;
// 基準時間 1900-01-01
st.wYear = 1900; st.wMonth = 1; st.wDay = 1;
st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
SystemTimeToFileTime(&st, &ft);
LARGE_INTEGER li = *(LARGE_INTEGER*)&ft;
li.QuadPart += (LONGLONG)10000000 * ulTime; // 1 秒 = 10^7 100ns
ft = *(FILETIME*)&li;
FileTimeToSystemTime(&ft, &st);
SetSystemTime(&st); // 需 SE_SYSTEMTIME_NAME 權限
}
char* servers[] = {
"time.nist.gov", "time-a.nist.gov", "time-b.nist.gov",
"ntp1.aliyun.com", "cn.pool.ntp.org", NULL
};
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int) {
WSADATA wsa; WSAStartup(MAKEWORD(2,2), &wsa);
for (int i=0; servers[i]; i++) {
unsigned long t;
if (GetRemoteTime(servers[i], t)) {
MySetTime(t);
char msg[200];
wsprintf(msg, "已與 %s 同步成功", servers[i]);
MessageBox(NULL, msg, "成功", MB_OK|MB_ICONINFORMATION);
WSACleanup(); return 0;
}
}
MessageBox(NULL, "所有伺服器連線失敗或逾時", "錯誤", MB_OK|MB_ICONHAND);
WSACleanup(); return -1;
}
socket(AF_INET, SOCK_STREAM, 0)connect() 後直接 recv(sock, &ulTime, 4, 0),無需送出空封包。SetSystemTime 需要「變更系統時間」權限 (Administrators/Power Users 或透過群組原則授予)。time.nist.gov, time-a.nist.gov, time-b.nist.govtick.stdtime.gov.tw (國家標準時間實驗室)ntp1.aliyun.com, cn.pool.ntp.orgpool.ntp.org (NTP 協定,非 RFC 868)RFC 868 協定簡單易實作,適合嵌入式裝置或輕量級應用快速同步時間。本文提供完整 TCP/UDP 雙模式 VC++ 範例,含錯誤處理、多伺服器容錯、系統時間設定,可直接整合至專案中。