对于我正在处理的程序,我必须检查IP(连接到Internet的IP)是公共还是私有.为此,我需要区分IP是IPv4还是IPv6.
我想根据IP的长度来检查它:
conn, err := net.Dial("udp", "8.9.10.11:2342")
if err != nil {
fmt.Println("Error", err)
}
localaddr := conn.LocalAddr()
addr, _ := net.ResolveUDPAddr("udp", localaddr.String())
ip := addr.IP
fmt.Println(ip)
fmt.Println(len(ip))
Run Code Online (Sandbox Code Playgroud)
好吧,我的IP是192.168.2.100,所以IPv4,但len(ip)告诉我长度是16,这将是IPv6.我的错是什么?是否存在区分IPv4和IPv6的其他方法?
Eva*_*van 36
吉姆的答案是正确的,但相当复杂.我只想检查一下ip.To4() != nil.由于文档说"如果ip不是IPv4地址,To4返回nil",true当且仅当地址是IPv4地址时,此条件才会返回.
jim*_*imt 11
IP的长度几乎总是16,因为内部表示net.IP对于任何一种情况都是相同的.从文档:
请注意,在本文档中,将IP地址称为IPv4地址或IPv6地址是地址的语义属性,而不仅仅是字节片的长度:16字节片仍然可以是IPv4地址.
分离这两种类型取决于IP的初始化方式.查看代码net.IPv4(),可以看到它被初始化为16个字节,其中前12个字节被设置为值v4InV6Prefix.
// IPv4 returns the IP address (in 16-byte form) of the
// IPv4 address a.b.c.d.
func IPv4(a, b, c, d byte) IP {
p := make(IP, IPv6len)
copy(p, v4InV6Prefix)
p[12] = a
p[13] = b
p[14] = c
p[15] = d
return p
}
Run Code Online (Sandbox Code Playgroud)
在哪里v4InV6Prefix定义为:
var v4InV6Prefix = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}
Run Code Online (Sandbox Code Playgroud)
如果您想要一个可靠的差异化,请查看net.IP.To4处理它的源代码:
// To4 converts the IPv4 address ip to a 4-byte representation.
// If ip is not an IPv4 address, To4 returns nil.
func (ip IP) To4() IP {
if len(ip) == IPv4len {
return ip
}
if len(ip) == IPv6len &&
isZeros(ip[0:10]) &&
ip[10] == 0xff &&
ip[11] == 0xff {
return ip[12:16]
}
return nil
}
Run Code Online (Sandbox Code Playgroud)
isZeros未导出,因此您必须在本地复制该代码.然后,您可以简单地执行与上面相同的操作,以确定您是否具有IPv4或IPv6.
govalidator:检查字符串中是否存在。
func IsIPv6(str string) bool {
ip := net.ParseIP(str)
return ip != nil && strings.Contains(str, ":")
}
Run Code Online (Sandbox Code Playgroud)
该接受的答案由埃文(ip.To4() != nil)解决问题。但是,已经有一些评论和其他答案来检查表示形式是IPv4还是IPv6,并且它们并不总是准确的:
注意:以下分别是几个有效的IPv4和IPv6有效符号列表。每个条目代表第一个基本条目的变体。可以根据需要组合变体,但是出于空间原因,除了消除歧义之外,没有列出任何变体组合。
有效的IPv4表示法:
"192.168.0.1":基本"192.168.0.1:80":带有端口信息有效的IPv6表示法:
"::FFFF:C0A8:1":基本"::FFFF:C0A8:0001":前导零"0000:0000:0000:0000:0000:FFFF:C0A8:1":双冒号扩展"::FFFF:C0A8:1%1":具有区域信息"::FFFF:192.168.0.1":IPv4文字"[::FFFF:C0A8:1]:80":带有端口信息"[::FFFF:C0A8:1%1]:80":带区域和端口信息所有这些情况(同时支持IPv4和IPv6名单)将被考虑IPv4地址的net包。govalidator会将 IPv6列表的IPv4文字变体视为IPv4 。
检查它是IPv4还是IPv6地址的最简单方法是:
import strings
func IsIPv4(address string) bool {
return strings.Count(address, ":") < 2
}
func IsIPv6(address string) bool {
return strings.Count(address, ":") >= 2
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
17243 次 |
| 最近记录: |