转载:https://blog.thinkeridea.com/201903/go/ip2long.html
IP 地址库中 IP 地址的保存格式一般有两种,一种是点分十进制形式(192.168.1.1),另一种是数字形式(3232235777),应用中,经常需要在这两种格式之间做转换。
针对这一个问题我在 exnet 扩展包里面实现可两者的转换的快捷方法:
-
func IP2Long(ip net.IP) (uint,error)@H_403_9@ IP2Long 把 net.IP 转为数值
-
func Long2IP(i uint) (net.IP,error)@H_403_9@ Long2IP 把数值转为 net.IP
-
func IPString2Long(ip string) (uint,error)@H_403_9@ IPString2Long 把 ip 字符串转为数值
-
func Long2IPString(i uint) (string,error)@H_403_9@ Long2IPString 把数值转为 ip 字符串
使用示例:
package main
import (
"fmt"
"net"
"reflect"
"github.com/thinkeridea/go-extend/exnet"
)
func main() {
ip := "192.168.1.1"
n,_ := exnet.IPString2Long(ip)
s,_ := exnet.Long2IPString(n)
fmt.Println(n,s == ip)
Ip1 := net.ParseIP(ip) // 会得到一个16字节的byte,主要为了兼容ipv6
n,_ = exnet.IP2Long(Ip1)
Ip2,_ := exnet.Long2IP(n)
fmt.Println(n,reflect.DeepEqual(Ip1[12:],Ip2))
}
@H_403_9@
那么是如何将点分十进制的IP地址转为数字?
IPv4 地址有4个字节,样式如下:
MSB————–LSB
b4 b3 b2 b1
每个字节表示的范围:
- byte4: 4294967296(1<<32)
- byte3: 16777216(1<<24)
- byte2: 65536(1<<16)
- byte1: 256(1<<8)
通用公式:b4<<24 | b3<<16 | b2<<16 | b1@H_403_9@
例如,222.173.108.86
转换方法:222<<24 | 173<<16 | 108<<8 | 86 = 3735907414@H_403_9@
再例如,1.0.1.1
转换方法:1<<24 | 0<<16 | 1<<8 | 1 = 16777473@H_403_9@
exnet 中实现如下:
// IPString2Long 把ip字符串转为数值
func IPString2Long(ip string) (uint,error) {
b := net.ParseIP(ip).To4()
if b == nil {
return 0,errors.New("invalid ipv4 format")
}
return uint(b[3]) | uint(b[2])<<8 | uint(b[1])<<16 | uint(b[0])<<24,nil
}
@H_403_9@
把数值转换为字符串的逻辑翻转过来即可, exnet 中实现如下:
// Long2IPString 把数值转为ip字符串
func Long2IPString(i uint) (string,error) {
if i > math.MaxUint32 {
return "",errors.New("beyond the scope of ipv4")
}
ip := make(net.IP,net.IPv4len)
ip[0] = byte(i >> 24)
ip[1] = byte(i >> 16)
ip[2] = byte(i >> 8)
ip[3] = byte(i)
return ip.String(),nil
}
@H_403_9@
转载:
本文作者: 戚银(thinkeridea)
本文链接: https://blog.thinkeridea.com/201903/go/ip2long.html
版权声明: 本博客所有文章除特别声明外,均采用 CC BY 4.0 CN协议 许可协议。转载请注明出处! (编辑:北几岛)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|