丁元
摘要:利用Internet傳送標(biāo)準(zhǔn)時間信息稱做網(wǎng)絡(luò)授時。目前網(wǎng)上有很多授時服務(wù)器,我們可以用高級語言寫一個在線對時器,獲取授時服務(wù)器上的時間并以此來校對本機時間。本文以C語言為工具,實現(xiàn)了一個簡單的在線對時器的開發(fā)。
關(guān)鍵詞:C語言 在線對時
中圖分類號:TP302 文獻(xiàn)標(biāo)識碼:A 文章編號:1672-3791(2012)10(b)-0006-01
在線對時器的作用是從Internet上獲取準(zhǔn)確的時間。它的基本設(shè)計思想是開發(fā)出客戶端工具,以此登錄到網(wǎng)絡(luò)上的授時服務(wù)器并獲取它的準(zhǔn)確時間,然后根據(jù)這個時間來校對本機的系統(tǒng)時間。下面以C語言為開發(fā)工具,介紹一種簡單的在線定時器的實現(xiàn)方法。
1 登錄到授時服務(wù)器
Internet上可用的授時服務(wù)器很多,這里采用香港的官方授時服務(wù)器(IP地址:210.0.235.14)。
核心代碼如下。
//初始化套接字
SOCKETsock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
SOCKADDR_INsa;
sa.sin_family=AF_INET;
//設(shè)置套接字連接服務(wù)器端的端口(客戶端端口由套接字動態(tài)分配,無需指定)
sa.sin_port=htons(IPPORT_TIMESERVER);//IPPORT_TIMESERVER是宏,對應(yīng)的
//值是37,它代表TIMESERVER的端口號
//設(shè)置要連接到的授時服務(wù)器的IP地址
sa.sin_addr.S_un.S_addr=inet_addr("210.0.235.14");
//指定了端口號和IP地址之后,開始登錄到授時服務(wù)器
connect(sock,(SOCKADDR*)&sa,sizeof(sa));
2 接收授時服務(wù)器傳過來的信息
我們這里采用的授時服務(wù)器,返回給客戶端的是1900年1月1日0點0分0秒到現(xiàn)在的秒數(shù),是整型數(shù)字。而我們將要使用的接收服務(wù)器返回的消息的recv函數(shù),它相應(yīng)的參數(shù)是字符指針類型,因此需要進(jìn)行類型轉(zhuǎn)換,這在代碼中將得到體現(xiàn)。具體如下。
//定義用來接收返回的時間秒數(shù)的變量
unsignedlongulTime=0;
//使用recv函數(shù)接收以秒數(shù)代表的當(dāng)前時間
recv(sock,(char*)&ulTime,sizeof(unsignedlong),0);
那么這個秒數(shù)是多少呢?我們可以將它打印出來看一下:
//定義字符緩沖區(qū)
TCHARbuff[256];
//將緩沖區(qū)清零
ZeroMemory(buff,sizeof(buff)/sizeof(TCHAR));
將接收的秒數(shù)寫到定義的緩沖區(qū)中
wsprintf(buff,"%i",ulTime);
//以對話框的形式顯示接收的秒數(shù)
MessageBox(NULL,buff,TEXT("以秒數(shù)代表的當(dāng)前時間"),MB_OK);
我們得到的對話框如圖1所示。
為什么得到的結(jié)果明顯不對呢?這涉及到字節(jié)順序的問題,也就是說我們的客戶機存儲的整數(shù)的字節(jié)順序和授時服務(wù)器不一致,導(dǎo)致傳過來的ulTime沒有得到正確的還原。這個問題很好解決,我們在將ulTime寫到緩沖區(qū)之前,使用ntohl函數(shù)對ulTime做個處理即可(ulTime=ntohl(ulTime))。
3 將秒數(shù)表示的時間轉(zhuǎn)換為字符形式的時間
下面我們要將上面得到的一串?dāng)?shù)字轉(zhuǎn)換為我們看得懂的字符形式的時間,我們用以下代碼實現(xiàn)。
SYSTEMTIMEst;
UINT64uiCurTime,uiBaseTime,uiResult;
uiBaseTime=((UINT64)HIGHTIME<<32)+LOWTIME;
uiCurTime=(UINT64)ulTime*(UINT64)10000000;
uiResult=uiBaseTime+uiCurTime;
FileTimeToSystemTime((LPFILETIME)&uiResult,&st);
以上代碼將接收到的以ulTime代表的秒數(shù)轉(zhuǎn)換為了st這個結(jié)構(gòu)體變量所代表的字符形式的時間(st中包含了年、月、日、時、分、秒的信息)。
我們將st中的內(nèi)容打印出來看一下,用以下代碼實現(xiàn)。
TCHARbuff[256];
ZeroMemory(buff,sizeof(buff)/sizeof(TCHAR));
wsprintf(buff,TEXT("%i年%i月%i日%i:%i:%i"),st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond);//中國時區(qū)在東八區(qū),因此在小時上加8;
MessageBox(NULL,buff,TEXT("字符形式的時間"),MB_OK);
打印出來的結(jié)果如圖2所示。
為什么得到的小時不對呢?很簡單,中國在東八區(qū),應(yīng)該在小時上加上8,也就是將st.wHour改為st.wHour+8。
4 將得到的時間設(shè)成本機系統(tǒng)時間
經(jīng)過以上的測試,我們已經(jīng)得到了授時服務(wù)器上的準(zhǔn)確時間。將這個時間設(shè)置成本地系統(tǒng)時間即可,代碼只需一句。
SetSystemTime(&st);//將st這個結(jié)構(gòu)體變量所對應(yīng)的時間賦給本機。
5 結(jié)語
本文介紹了用C語言實現(xiàn)的在線對時器開發(fā)的基本思路和核心代碼。用其它高級語言開發(fā)在線對時器的基本方法與此類似。希望這樣的客戶端工具的開發(fā),對于想深入學(xué)習(xí)網(wǎng)絡(luò)編程的朋友,能起到一個鋪墊的作用。
參考文獻(xiàn)
[1] 譚浩強.C程序設(shè)計[M].清華大學(xué)出版社,1999.
[2] 佩措爾德.Windows程序設(shè)計[M].清華大學(xué)出版社,2010.