簡單有趣:使用Go語言實現“時間服務器”,從此時間你說了算

前言

Go語言自帶的net包,強大而豐富,封裝了大多數網絡編程所使用的方法和庫函數。

今天我們做一個簡單的小實驗,使用Go語言,實現“時間服務器”功能,讓服務器對外提供時間同步校準功能。


簡單有趣:使用Go語言實現“時間服務器”,從此時間你說了算


時間服務器淺說

為什麼需要時間服務器?為了同步。舉一個例子吧。

話說程序員小王,因為工作比較忙,大齡了還沒女朋友,家裡給介紹了個對象小宋。加了微信,要了手機號,一來二去感覺不錯。

“見個面吧!”

“好哇!”

明天下午4:00步行街咖啡廳見吧?”

“好的。”

等到第二天,小宋4:00準時到了咖啡廳。找了一圈沒見小王人影。

“難道這小子寫代碼忘時間了?太不守時了!差評。”小宋心裡不快。

又過了5分鐘,小王輕鬆地來了,說:

“我說準點兒到,想不到你來的更早。”

“你都遲到了!”

“沒有吧,我剛4:00”。

小王拿出自己的手機晃了晃。果然4:00。小宋也拿出手機,看了看,4:05分

(擦汗)

到底誰的時間不準確?

小王和小宋要是能對一下時,或者知道有NTP時間服務器,就不會這樣了。


NTP協議

為了時間同步,指定了一個專門的協議NTP,網絡時間協議。用於同步計算機,手機,手錶等聯網設備的時間。

當前提供此功能的服務器有很多,下面是一張列表。

  • Windows 系統自帶:time.windows.comtime.nist.gov
  • IOS自帶:time.apple.comtime.asia.apple.com
  • 國內免費使用的 cn.ntp.org.cn
  • 阿里公司提供的 ntp.aliyun.com

在windows系統中,通過時間和日期設置中的“Internet時間”選項中設置服務器,即可與遠程服務器同步時間。


簡單有趣:使用Go語言實現“時間服務器”,從此時間你說了算

用Go語言實現

NTP是由RFC 867定義, 默認的端口13, 協議是TCP和UDP。所以我們使用net包進行實現。

主要流程是註冊並監聽一個端口,然後阻塞在 accept 操作,並等待客戶端連接。當一個客戶端連接, accept 調用返回一個連接(connection)對象。時間服務非常簡單,只是將當前時間寫入到客戶端, 關閉該連接,並繼續等待下一個客戶端

我們主要使用一下兩個方法:

<code>func ListenTCP(net string, laddr *TCPAddr) (l *TCPListener, err os.Error)
func (l *TCPListener) Accept() (c Conn, err os.Error)/<code>

對上述函數的參數說明:

net變量

可以設置為字符串”tcp”, “tcp4”或者”tcp6”中的一個。

laddr變量

如果監聽所有端口,IP地址應設置為0。如果是特定端口,則需要制定IP。特別注意的是,在類Unix系統上,用戶程序監聽端口應大於1024。因為該段端口是系統預留的。下方代碼中,我們選擇了沒有使用的1240端口。


簡單有趣:使用Go語言實現“時間服務器”,從此時間你說了算


主要由三大段組成,

  • 一段是err_handler處理錯誤並打印和退出,
  • 一段是綁定IP和端口,
  • 一段是循環監聽,如果收到請求,發送時間字符串,並關閉連接。

本身功能流程也比較直觀。


測試一下

我們在本地運行這個工具,並用telnet工具連接1240端口,看能否獲取到需要的數據。

可以不用編譯,直接運行以下指令:

go run net.go

然後使用telnet連接,

telnet 127.0.0.1 1240

得到類似如下的結果:


簡單有趣:使用Go語言實現“時間服務器”,從此時間你說了算

可以看到程序正常地執行了。也獲取到了結果字符串。


結語

通過時間同步服務這樣的小功能,我們重溫了tcp協議,以及實現NTP的步驟。可見Go語言在網絡編程方面,給程序員提供了非常多的便利,可以使用少量的代碼,實現邏輯功能。

這可能就是Go為什麼高效的一種體現。


【本文由 發佈,持續分享編程與程序員成長相關的內容,歡迎關注】


分享到:


相關文章: