Go/GoLang检查范围内的IP地址
在Go/GoLang中,检查IP地址是否在特定范围内的最快方法是什么Go/GoLang检查范围内的IP地址,go,ip-address,Go,Ip Address,在Go/GoLang中,检查IP地址是否在特定范围内的最快方法是什么 例如,给定范围216.14.49.184到216.14.49.191,如何检查给定的输入IP地址是否在该范围内?IP地址表示为go中的bigendian[]字节片(IP类型),因此将使用字节进行正确比较。比较 例如() 我移植了下面一个C#示例中的代码: 由于某种原因,它比Nick的解决方案快1毫秒 我的问题是“最快”的方式,所以我想我应该发布我的,看看社区怎么想 package iptesting import (
例如,给定范围
216.14.49.184
到216.14.49.191
,如何检查给定的输入IP地址是否在该范围内?IP地址表示为go中的bigendian[]字节片(IP
类型),因此将使用字节进行正确比较。比较
例如()
我移植了下面一个C#示例中的代码:
由于某种原因,它比Nick的解决方案快1毫秒
我的问题是“最快”的方式,所以我想我应该发布我的,看看社区怎么想
package iptesting
import (
"fmt"
"testing"
"net"
"time"
"bytes"
)
func TestIPRangeTime(t *testing.T) {
lowerBytes := net.ParseIP("216.14.49.184").To4()
upperBytes := net.ParseIP("216.14.49.191").To4()
inputBytes := net.ParseIP("216.14.49.184").To4()
startTime := time.Now()
for i := 0; i < 27000; i++ {
IsInRange(inputBytes, lowerBytes, upperBytes)
}
endTime := time.Now()
fmt.Println("ELAPSED time port: ", endTime.Sub(startTime))
lower := net.ParseIP("216.14.49.184")
upper := net.ParseIP("216.14.49.191")
trial := net.ParseIP("216.14.49.184")
startTime = time.Now()
for i := 0; i < 27000; i++ {
IsInRange2(trial, lower, upper)
}
endTime = time.Now()
fmt.Println("ELAPSED time bytescompare: ", endTime.Sub(startTime))
}
func IsInRange2(trial net.IP, lower net.IP, upper net.IP) bool {
if bytes.Compare(trial, lower) >= 0 && bytes.Compare(trial, upper) <= 0 {
return true
}
return false
}
func IsInRange(ip []byte, lower []byte, upper []byte) bool {
//fmt.Printf("given ip len: %d\n", len(ip))
lowerBoundary := true
upperBoundary := true
for i := 0; i < len(lower) && (lowerBoundary || upperBoundary); i++ {
if lowerBoundary && ip[i] < lower[i] || upperBoundary && ip[i] > upper[i] {
return false
}
if ip[i] == lower[i] {
if lowerBoundary {
lowerBoundary = true
} else {
lowerBoundary = false
}
//lowerBoundary &= true
} else {
lowerBoundary = false
//lowerBoundary &= false
}
if ip[i] == upper[i] {
//fmt.Printf("matched upper\n")
if upperBoundary {
upperBoundary = true
} else {
upperBoundary = false
}
//upperBoundary &= true
} else {
upperBoundary = false
//upperBoundary &= false
}
}
return true
}
像inet\u pton这样的实现怎么样?结果易于存储
func IP2Integer(ip *net.IP) (int64, error) {
ip4 := ip.To4()
if ip4 == nil {
return 0, fmt.Errorf("illegal: %v", ip)
}
bin := make([]string, len(ip4))
for i, v := range ip4 {
bin[i] = fmt.Sprintf("%08b", v)
}
return strconv.ParseInt(strings.Join(bin, ""), 2, 64)
}
ipv4/ipv6的通用版本
ip.go:
package ip
import (
"bytes"
"net"
"github.com/golang/glog"
)
//test to determine if a given ip is between two others (inclusive)
func IpBetween(from net.IP, to net.IP, test net.IP) bool {
if from == nil || to == nil || test == nil {
glog.Warning("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 {
glog.Warning("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
}
这已经作为一个名为net.Contains的函数存在于“net”包的stdlib中。你不需要重写已经存在的代码
见文件
要使用它,您只需解析所需的子网
network := "192.168.5.0/24"
clientips := []string{
"192.168.5.1",
"192.168.6.0",
}
_, subnet, _ := net.ParseCIDR(network)
for _, clientip := range clientips {
ip := net.ParseIP(clientip)
if subnet.Contains(ip) {
fmt.Println("IP in subnet", clientip)
}
}
如果上述代码没有意义,这里有一个如何表示您的范围?开始:“216.14.49.184”,结束:“216.14.49.191”。我在网上找到了一个CIDR的解决方案,但这不是我正在处理的数据。我只是想知道,如果你将这些字符串分解为组件,并用数字进行比较,这会产生正确的结果吗?那些整数ms
计时对我来说有点可疑-你会使用基准测试得到更准确的结果
-请参阅:完美工作中的基准测试部分这是真的。。。除非您的IP数据没有整齐地格式化为子网。
func IP2Integer(ip *net.IP) (int64, error) {
ip4 := ip.To4()
if ip4 == nil {
return 0, fmt.Errorf("illegal: %v", ip)
}
bin := make([]string, len(ip4))
for i, v := range ip4 {
bin[i] = fmt.Sprintf("%08b", v)
}
return strconv.ParseInt(strings.Join(bin, ""), 2, 64)
}
package ip
import (
"bytes"
"net"
"github.com/golang/glog"
)
//test to determine if a given ip is between two others (inclusive)
func IpBetween(from net.IP, to net.IP, test net.IP) bool {
if from == nil || to == nil || test == nil {
glog.Warning("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 {
glog.Warning("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
}
package ip
import (
"net"
"testing"
)
func TestIPBetween(t *testing.T) {
HandleIpBetween(t, "0.0.0.0", "255.255.255.255", "128.128.128.128", true)
HandleIpBetween(t, "0.0.0.0", "128.128.128.128", "255.255.255.255", false)
HandleIpBetween(t, "74.50.153.0", "74.50.153.4", "74.50.153.0", true)
HandleIpBetween(t, "74.50.153.0", "74.50.153.4", "74.50.153.4", true)
HandleIpBetween(t, "74.50.153.0", "74.50.153.4", "74.50.153.5", false)
HandleIpBetween(t, "2001:0db8:85a3:0000:0000:8a2e:0370:7334", "74.50.153.4", "74.50.153.2", false)
HandleIpBetween(t, "2001:0db8:85a3:0000:0000:8a2e:0370:7334", "2001:0db8:85a3:0000:0000:8a2e:0370:8334", "2001:0db8:85a3:0000:0000:8a2e:0370:7334", true)
HandleIpBetween(t, "2001:0db8:85a3:0000:0000:8a2e:0370:7334", "2001:0db8:85a3:0000:0000:8a2e:0370:8334", "2001:0db8:85a3:0000:0000:8a2e:0370:7350", true)
HandleIpBetween(t, "2001:0db8:85a3:0000:0000:8a2e:0370:7334", "2001:0db8:85a3:0000:0000:8a2e:0370:8334", "2001:0db8:85a3:0000:0000:8a2e:0370:8334", true)
HandleIpBetween(t, "2001:0db8:85a3:0000:0000:8a2e:0370:7334", "2001:0db8:85a3:0000:0000:8a2e:0370:8334", "2001:0db8:85a3:0000:0000:8a2e:0370:8335", false)
HandleIpBetween(t, "::ffff:192.0.2.128", "::ffff:192.0.2.250", "::ffff:192.0.2.127", false)
HandleIpBetween(t, "::ffff:192.0.2.128", "::ffff:192.0.2.250", "::ffff:192.0.2.128", true)
HandleIpBetween(t, "::ffff:192.0.2.128", "::ffff:192.0.2.250", "::ffff:192.0.2.129", true)
HandleIpBetween(t, "::ffff:192.0.2.128", "::ffff:192.0.2.250", "::ffff:192.0.2.250", true)
HandleIpBetween(t, "::ffff:192.0.2.128", "::ffff:192.0.2.250", "::ffff:192.0.2.251", false)
HandleIpBetween(t, "::ffff:192.0.2.128", "::ffff:192.0.2.250", "192.0.2.130", true)
HandleIpBetween(t, "192.0.2.128", "192.0.2.250", "::ffff:192.0.2.130", true)
HandleIpBetween(t, "idonotparse", "192.0.2.250", "::ffff:192.0.2.130", false)
}
func HandleIpBetween(t *testing.T, from string, to string, test string, assert bool) {
res := IpBetween(net.ParseIP(from), net.ParseIP(to), net.ParseIP(test))
if res != assert {
t.Errorf("Assertion (have: %s should be: %s) failed on range %s-%s with test %s", res, assert, from, to, test)
}
}
network := "192.168.5.0/24"
clientips := []string{
"192.168.5.1",
"192.168.6.0",
}
_, subnet, _ := net.ParseCIDR(network)
for _, clientip := range clientips {
ip := net.ParseIP(clientip)
if subnet.Contains(ip) {
fmt.Println("IP in subnet", clientip)
}
}