最近因工作原因,需要客戶端計算機與FTP服務器時間上進行同步,上網蒐集了些時間同步的方法記錄下來, 以備不需之用!
1.時間協議(TIME protocol)
時間協議(TIME protocol)是一個在RFC 868內定義的網絡協議。它用作提供機器可讀的日期時間資訊。
時間協議可以在TCP或UDP上使用。在TCP上,主機會連接支援時間協議的服務器的TCP埠 37。服務器會傳送32位二進制數字然後斷開連接,數字表示由格林威治時間1900年1月1日午夜0時0分0秒至當時的總秒數。主機在接收到時間後斷開連接。
在UDP上,客戶端會每送一個(通常爲空的)數據包到UDP埠 37。服務器會把包含時間的數據包傳回。在過程中沒有進行連線。
現時,時間協議已經被網絡時間協議(Network Time Protocol,NTP)所取代。
使用時間協議需要在服務器端開啓時間服務,目前在windows中我還沒找到系統自帶的開啓時間服務的方法, 但網絡上有些小軟件可以幫助實現(如NetTime網絡時標, 它支持Time,NTP等好幾種協議, 可惜需要註冊使用).
基於時間協議客戶端實現代碼:
2.網絡校時協議(NTP)
Network Time Protocol(NTP)是用來使計算機時間同步化的一種協議,它可以使計算機對其服務器或時鐘源(如石英鐘,GPS等等
)做同步化,它可以提供高精準度的時間校正(LAN上與標準間差小於1毫秒,WAN上幾十毫秒),且可介由加密確認的方式來防止惡毒的
協議攻擊。
NTP協議格式:
NTP packet = NTP header + Four TimeStamps = 48byte
NTP header : 16byte
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
|LI | VN |Mode | Stratum | Poll | Precision |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
LeapYearIndicator : 2bit
VersionNumber : 3bit
Stratum : 8bit
Mode : 3 bit
PollInterval : 8 bit
Percision : 8bit
| Root Delay |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Root delay : 32bit
| Root Dispersion |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Root Dispersion : 32bit
| Reference Identifier |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Reference Identifier : 32bit
Four TimeStamps : 32byte
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
| Reference Timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Reference Timestamp : 64bit
| Originate Timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Originate Timestamp : 64bit
| Receive Timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Receive Timestamp : 64bit
| Transmit Timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Transmit Timestamp : 64bit
| Authenticator (optional) (96) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
* LI:跳躍指示器,警告在當月最後一天的最終時刻插入的迫近閨秒(閨秒)。
* VN:版本號。
* Mode:模式。該字段包括以下值:0-預留;1-對稱行爲;3-客戶機;4-服務器;5-廣播;6-NTP 控制信息
* Stratum:對本地時鐘級別的整體識別。
* Poll:有符號整數表示連續信息間的最大間隔。
* Precision:有符號整數表示本地時鐘精確度。
* Root Delay:有符號固定點序號表示主要參考源的總延遲,很短時間內的位15到16間的分段點。
* Root Dispersion:無符號固定點序號表示相對於主要參考源的正常差錯,很短時間內的位15到16間的分段點。
* Reference Identifier:識別特殊參考源。
* Originate Timestamp:這是向服務器請求分離客戶機的時間,採用64位時標(Timestamp)格式。
* Receive Timestamp:這是向服務器請求到達客戶機的時間,採用64位時標(Timestamp)格式。
* Transmit Timestamp:這是向客戶機答覆分離服務器的時間,採用64位時標(Timestamp)格式。
* Authenticator(Optional):當實現了 NTP 認證模式,主要標識符和信息數字域就包括已定義的信息認證代碼(MAC)信息。
配置NTP服務器:
1)、Linux主機做時間服務器(以RedHat9.0爲例)
第一步:檢查是否已經安裝有ntp軟件包。輸入“rpm -qa|grep ntp”,如果已經安裝應該顯示“ntp-4.1.2-0.rc1”。
第二步:安裝ntp軟件,從ftp://ftp.redhat.com下載rpm包,輸入“rpm -ivh ntp-xxx.rpm”執行安裝。
第三步:配置ntp服務。備份原/etc/ntp.conf文件後,輸入以下內容
server pool.ntp.org
server pool.ntp.org
server pool.ntp.org
driftfile /etc/ntp/drift
三行server都設pool.ntp.org是爲了提供連接冗餘,當第一個地址連接失敗時,後面的地址提供時間服務,注意這裏的
pool.ntp.org對應一組IP地址,由DNS隨機分配。
第四步:啓動ntp服務。輸入“service ntp restart”。
爲了保證以後Linux機啓動後ntp服務能自動啓動,還要輸入“chkconfig ntpd on”。Linux下的ntp軟件不但能自動與互聯網上的時鐘
保持同步,同時本身已經是一臺SNTP服務器了,可以供局域網內的電腦校對時間。建議啓動 NTP服務後,先用date命令手工校正一下時
間,以後系統會自動與互聯網上的主時間服務器保持同步。ntp服務還有一個好處,如果當前系統的時間與標準時間有所誤差,它不是馬
上把時間校正,而是逐步縮小與標準時間的誤差,以免系統內部出現時間突變。
2)、Windows2000、XP做時間服務器
第一步:指定主時間服務器。在DOS方式輸入“net time /setsntp:pool.ntp.org”,這裏我們指定pool.ntp.org是主時間服務器,也
可以是其它地址。
第二步:開始與主時間服務器同步。先關閉windows time服務,再開啓該服務。可以在“管理工具”的“服務”界面下完成,也可以以
DOS方式輸入“net stop w32time”、“net start w32time”。
第三步:設置電腦的Windows time服務的啓動方式爲自動。在“管理工具”的“服務”界面下完成。
注意這臺windows主機不能加入任何域,否則無法啓動windows time服務。此時,這臺windows電腦已經是互聯上主時間服務器的客
戶了,以後每次電腦啓動時,都會自動與主時間服務器校對時間。如果網絡不通,電腦也會過45分鐘後再次自動校對時間。需要注意的
是電腦的時鐘與標準時間誤差不能超過12小時,否則不能自動校對,而要手動校正了。
第四步:使這臺電腦成爲時間服務器,供局域網內部的電腦校對時間。用“regedit”打開註冊表,把
“HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesW32TimeParameters”中的 LocalNTP改爲1即可。
3)、Windows98做時間服務器
一般不推薦Windows98系統做時間服務器,而且win98本身也不含時間服務器功能,需要安裝第三方軟件。
客戶端時間同步代碼:
3.NetRemoteTOD API函數
NetRemoteTOD可以返回指定服務器的時間,具體說明見MSDN.
利用這個API函數有個限制,那就是客戶端必須要有對服務器的訪問權限(你可以先通過局域網訪問這臺服務器,然後記住訪問密碼,
再用這個函數訪問就不會有問題了),否則函數會返回權限拒絕錯誤.
NetRemoteTOD示例:
4.其他方法
如果條件允許的話,我們可以自己寫服務器端程式來返回需要的服務器端時間,然後在客戶端寫socket來接收時間信息.
還有一種更簡單的方法就是向服務器上寫一個文件,然後讀取這個文件的創建日期來獲得服務器的時間,這種方法可能精確性不是很高,而且需要對服務器有寫文件的權限.