Wednesday, May 26, 2010

ntp

因為BIOS電池沒電, 所以每次開機, 系統時間都要調一次
windows ntp 又好像怪怪的
所以自己寫了個 windows ntp version 3 client

初始化 WSAStarup()
WSAStartup(MAKEWORD(2,2), &wsaData);

create UDP socket()
sockfd=socket(AF_INET, SOCK_DGRAM, 0);

準備structure of NTP data format
ntpData.theFirstByte = (0x3 << 6) | (0x03 << 3) | 0x03;
ntpData.stratum = 0x02;
ntpData.poll_interval=0x04;
ntpData.precision=0x04;
ntpData.root_delay=1;
ntpData.root_dispersion=1;
ntpData.transtime.i=htonl(time(NULL)+time1970);

傳送給 ntp server
sendto(sockfd, (char *)&ntpData, sizeof(ntpData), 0, (struct sockaddr *)&serverAddr, sizeof(serverAddr));

嘗試接收
iResult=select(sockfd+1, &rfds, NULL, NULL, &timeout);
recvfrom(sockfd, (char *)&ntpData, sizeof(ntpData), 0, (struct sockaddr *)&serverAddr, &serverAddrLength);

收到並解開 ntp server 的回應
ntpData.recvtime.i=difftime(ntpData.recvtime.i, time1970);

寫到系統時間
SetLocalTime(&timeUTC);
SetLocalTime()會將 timeUTC 的轉成系統所設定的 timezone

要注意的地方
NTP的起始時間是從1900年算起, time()回傳時間是從1970年算起
所以在傳送或接收 NTP timestamp 時, 記得做必要的時間轉換
當傳送時
ntpData.transtime.i=htonl(time(NULL)+time1970);
當收到時
ntpData.recvtime.i=difftime(ntpData.recvtime.i, time1970);

time1970 定義成 2208988800, 請參考 RFC 868 Time Protocol 說明