##前言
最近在研究一些Golang在UDP上的處理,主要是要抓取網路遮罩(network mask)做一些進階使用.就發現要取得正確的網路遮罩,其實是蠻困難的.由於是無法直接使用到裝置上面的網卡設定.
這邊介紹一下相關的流程:
###先來抓取IPv4
這邊先顯示抓取IP的方式:
funcGetIP()net.IP{ifaces,err:=net.Interfaces()// handle erriferr!=nil{log.Println("No network:",err)returnnil}for_,i:=rangeifaces{//只抓取網路卡名稱為"en0", "en1"...ifstrings.Contains(i.Name,"en"){addrs,err:=i.Addrs()// handle erriferr!=nil{log.Println("No IP:",err)returnnil}for_,addr:=rangeaddrs{varipnet.IPswitchv:=addr.(type){case*net.IPNet:log.Println("IPNET")ip=v.IPcase*net.IPAddr:log.Println("IPAddr")ip=v.IP}//這裡會抓取兩種IP,分別是IPv4與IPv6ifip[0]==0{//第一個byte是0為IPv4log.Println("Get device:",i.Name)returnip}}}}returnnil}
透過這個方式可以列舉所有的網路卡並且把第一張具有IPv4資料的net.IP
傳回來.
###再來找Network Mask
其實透過官方的API,原本就有一個IP.DefaultMask()
的函式可以使用.不過抓來的Network Mask是透過計算而來的,而不是跟網卡拿的.透過以下的範例:
packagemainimport("fmt""net")funcmain(){addr:=net.ParseIP("192.168.1.1")mask:=addr.DefaultMask()fmt.Printf("Address : %s \n Network : %s \n",addr.String(),mask)//Mask 255, 255, 255, 0addr=net.ParseIP("172.16.110.123")mask=addr.DefaultMask()fmt.Printf("Address : %s \n Network : %s \n",addr.String(),mask)//Mask 255, 255, 0, 0}
這邊可以看到,如果你的內部網路不是設定192.168.XXX.XXX
的話,你抓到的mask都會是255.255.0.9
.這樣的結果跟你在網路卡上面查到的可能會完全不相同.
###跟網卡拿取資料
比較好也比較不容易有問題的方式,就是直接透過系統的指令(console)去跟OS拿取網卡的資料.這裡貼上兩種方式:
Windows 版本(目前Go 1.5.2 broken,預計Go 1.6會修好)
網路上搜尋到的應該都是透過這個方式,不過在Go 1.5.2似乎broken了,聽說Go 1.6會修好. 可以參考這個Go: issue 12551
Mac OSX的版本,透過Ipconfig指令來抓取
這是我自己尋找的,透過Mac OS X的命令列來抓取資料,其實是比較簡單也比較方便的.不會因為版本有太大的問題. 使用方式就是call GetNetMask("en0")
###結論:
要抓取IP可以透過net
package來抓取,但是需要IPv4的網路遮罩,還是得要跟實體設備直接抓取比較妥當. 不過之後都要使用IPv6了,就不用那麼麻煩啦.