=Start=
缘由:
之前在博客中记录过用Python处理过IP地址相关的操作,比如「Python中如何获取当前机器的IP地址」和「Python的netaddr模块使用记录」;还有Java版本的「Java中如何判断一个IP是否在一个网段里面?」。这里记录一下如何用Go 语言进行处理,方便以后使用和参考。
正文:
参考解答:
判断某个IP是否在某个IP区间里面(先转换成IP类型(也即[]byte类型),然后利用bytes.Compare进行比较即可):
package main import ( "bytes" "fmt" "net" ) var ( // func ParseIP(s string) IP // type IP []byte ip1 = net.ParseIP("216.14.49.184") ip2 = net.ParseIP("216.14.49.191") ) func check(ip string) bool { trial := net.ParseIP(ip) if trial.To4() == nil { fmt.Printf("%v is not an IPv4 address\n", trial) return false } // func Compare(a, b []byte) int if bytes.Compare(trial, ip1) >= 0 && bytes.Compare(trial, ip2) <= 0 { fmt.Printf("%v is between %v and %v\n", trial, ip1, ip2) return true } fmt.Printf("%v is NOT between %v and %v\n", trial, ip1, ip2) return false } func main() { fmt.Printf("value of ip1: %v, type: %T\n", ip1, ip1) check("1.2.3.4") check("216.14.49.185") check("1::16") }
&
下面的一段代码实现了几个功能:
- 借助 http://myexternalip.com/raw 获取当前机器的外网IP;
- 利用 taobao 的API查询IP的地理位置相关信息;
- 获取本机的内网IP;
- 将IP字符串转换成整型&将整型转换成IP字符串;
- 判断IP是否在某个区间内;
package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net" "net/http" "os" "strconv" "strings" ) type IPInfo struct { Code int `json:"code"` Data IP `json:"data` } type IP struct { Country string `json:"country"` CountryId string `json:"country_id"` Area string `json:"area"` AreaId string `json:"area_id"` Region string `json:"region"` RegionId string `json:"region_id"` City string `json:"city"` CityId string `json:"city_id"` Isp string `json:"isp"` } func main() { external_ip := get_external() external_ip = strings.Replace(external_ip, "\n", "", -1) fmt.Println("公网ip是: ", external_ip) fmt.Println("------Dividing Line------") ip := net.ParseIP(external_ip) if ip == nil { fmt.Println("您输入的不是有效的IP地址,请重新输入!") } else { result := TabaoAPI(string(external_ip)) if result != nil { fmt.Println("国家:", result.Data.Country) fmt.Println("地区:", result.Data.Area) fmt.Println("城市:", result.Data.City) fmt.Println("运营商:", result.Data.Isp) } } fmt.Println("------Dividing Line------") GetIntranetIp() fmt.Println("------Dividing Line------") ip_int := inet_aton(net.ParseIP(external_ip)) fmt.Println("Convert IPv4 address to decimal number(base 10) :", ip_int) ip_result := inet_ntoa(ip_int) fmt.Println("Convert decimal number(base 10) to IPv4 address:", ip_result) fmt.Println("------Dividing Line------") is_between := IpBetween(net.ParseIP("0.0.0.0"), net.ParseIP("255.255.255.255"), net.ParseIP(external_ip)) fmt.Println("check result: ", is_between) fmt.Println("------Dividing Line------") is_public_ip := IsPublicIP(net.ParseIP(external_ip)) fmt.Println("It is public ip: ", is_public_ip) is_public_ip = IsPublicIP(net.ParseIP("169.254.85.131")) fmt.Println("It is public ip: ", is_public_ip) fmt.Println("------Dividing Line------") fmt.Println(GetPulicIP()) } func get_external() string { resp, err := http.Get("http://myexternalip.com/raw") if err != nil { return "" } defer resp.Body.Close() // buf := new(bytes.Buffer) // buf.ReadFrom(resp.Body) // s := buf.String() // return s content, _ := ioutil.ReadAll(resp.Body) return string(content) } func GetIntranetIp() { addrs, err := net.InterfaceAddrs() if err != nil { fmt.Println(err) os.Exit(1) } for _, address := range addrs { // 检查ip地址判断是否回环地址 if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { if ipnet.IP.To4() != nil { fmt.Println("ip:", ipnet.IP.String()) } } } } func TabaoAPI(ip string) *IPInfo { url := "http://ip.taobao.com/service/getIpInfo.php?ip=" url += ip resp, err := http.Get(url) if err != nil { return nil } defer resp.Body.Close() out, err := ioutil.ReadAll(resp.Body) if err != nil { return nil } var result IPInfo if err := json.Unmarshal(out, &result); err != nil { return nil } return &result } func inet_ntoa(ipnr int64) net.IP { var bytes [4]byte bytes[0] = byte(ipnr & 0xFF) bytes[1] = byte((ipnr >> 8) & 0xFF) bytes[2] = byte((ipnr >> 16) & 0xFF) bytes[3] = byte((ipnr >> 24) & 0xFF) return net.IPv4(bytes[3], bytes[2], bytes[1], bytes[0]) } func inet_aton(ipnr net.IP) int64 { bits := strings.Split(ipnr.String(), ".") b0, _ := strconv.Atoi(bits[0]) b1, _ := strconv.Atoi(bits[1]) b2, _ := strconv.Atoi(bits[2]) b3, _ := strconv.Atoi(bits[3]) var sum int64 sum += int64(b0) << 24 sum += int64(b1) << 16 sum += int64(b2) << 8 sum += int64(b3) return sum } func IpBetween(from net.IP, to net.IP, test net.IP) bool { if from == nil || to == nil || test == nil { fmt.Println("An ip input is nil") // or return an error!? return false } from16 := from.To16() to16 := to.To16() test16 := test.To16() if from16 == nil || to16 == nil || test16 == nil { fmt.Println("An ip did not convert to a 16 byte") // or return an error!? return false } if bytes.Compare(test16, from16) >= 0 && bytes.Compare(test16, to16) <= 0 { return true } return false } func IsPublicIP(IP net.IP) bool { if IP.IsLoopback() || IP.IsLinkLocalMulticast() || IP.IsLinkLocalUnicast() { return false } if ip4 := IP.To4(); ip4 != nil { switch true { case ip4[0] == 10: return false case ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31: return false case ip4[0] == 192 && ip4[1] == 168: return false default: return true } } return false } func GetPulicIP() string { conn, _ := net.Dial("udp", "8.8.8.8:80") defer conn.Close() localAddr := conn.LocalAddr().String() idx := strings.LastIndex(localAddr, ":") return localAddr[0:idx] }
参考链接:
- Go实战–golang中获取公网ip、查看内网ip、检测ip类型、校验ip区间、ip地址string和int转换、根据ip判断地区国家运营商等#nice
- 使用Go语言检查某个IP是否在指定的IP区间范围内#nice
- 使用Go语言计算网络IP地址的CIDR
- Go语言版的ip2long和long2ip
=END=
《“Go语言学习#9-如何操作IP地址”》 有 1 条评论
全球 IPv4 地址耗尽,IPv6 来了!
https://mp.weixin.qq.com/s/wMdDiu0o4JfUiqD8hAB75w
`
就在昨天,2019 年 11 月 26 日,全球 43 亿个 IPv4 地址正式耗尽,很多人表示忧虑。不过不用担心,IPv4 的下一代 IP 协议 IPv6 将会从根本上解决 IPv4 地址耗尽的问题。
下面通过一篇长文来了解下什么是 IPv6。
主要内容包括:
IPv6 的基本概念
IPv6 在 Linux 操作系统下的实现
IPv6 的实验
IPv6 的过渡技术介绍
IPv6 在 Linux 平台下 socket 编程应该注意的问题
实现简易版 TGW 支持 IPv6 雏形 demo
`