如何获取下一个IP地址?

huangapple go评论83阅读模式
英文:

How to get the next IP address?

问题

我正在考虑调用net.IP.String()strings.Split(ip, "."),一些代码来计算所有的边界情况,最后使用net.ParseIP(s)。有没有更好的方法来实现这个?以下是我当前实现的代码(没有处理特殊情况)。

package main

import (
	"fmt"
	"net"
	"strconv"
	"strings"
)

func main() {
	ip := net.ParseIP("127.1.0.0")
	next, err := NextIP(ip)
	if err != nil {
		panic(err)
	}
	fmt.Println(ip, next)
}

func NextIP(ip net.IP) (net.IP, error) {
	s := ip.String()
	sa := strings.Split(s, ".")
	i, err := strconv.Atoi(sa[2])
	if err != nil {
		return nil, err
	}
	i++
	sa[3] = strconv.Itoa(i)
	s = strings.Join(sa, ".")
	return net.ParseIP(s), nil
}

请注意,这只是一个简单的实现,没有处理特殊情况。

英文:

I'm considering to call net.IP.String(), strings.Split(ip, "."), some code to calculate all the corner cases and finally net.ParseIP(s). Is there a better way to this?. Below is the code of my current implementation (no special case handled).

package main

import (
	"fmt"
    "net"
	"strconv"
    "strings"
)

func main() {
	ip := net.ParseIP("127.1.0.0")
	next, err := NextIP(ip)
	if err != nil {
		panic(err)
	}
	fmt.Println(ip, next)
}

func NextIP(ip net.IP) (net.IP, error) {
	s := ip.String()
	sa := strings.Split(s, ".")
	i, err := strconv.Atoi(sa[2])
	if err != nil {
		return nil, err
	}
	i++
	sa[3] = strconv.Itoa(i)
	s = strings.Join(sa, ".")
	return net.ParseIP(s), nil
}

答案1

得分: 10

只需将IP地址中的最后一个八位增加即可。

ip := net.ParseIP("127.1.0.0")
// 确保它只有4个字节
ip = ip.To4()
// 检查ip != nil
ip[3]++  // 检查是否溢出
fmt.Println(ip)
// 127.1.0.1

然而,从技术上讲,这是不正确的,因为在127.1.0.1/8子网中,第一个地址是127.0.0.1。要获取真正的“第一个”地址,您还需要一个IPMask。由于您没有指定一个,您可以使用IPv4地址的DefaultMask(对于IPv6,您不能假设一个掩码,必须提供它)。

ip := net.IP{192, 168, 1, 10}
ip = ip.To4()
if ip == nil {
    log.Fatal("非IPv4地址")
}

ip = ip.Mask(ip.DefaultMask())
ip[3]++

fmt.Println(ip)
// 192.168.1.1

链接:http://play.golang.org/p/P_QWwRIBIm

英文:

Just increment the last octet in the IP address

ip := net.ParseIP("127.1.0.0")
// make sure it's only 4 bytes
ip = ip.To4()
// check ip != nil
ip[3]++  // check for rollover
fmt.Println(ip)
//127.1.0.1

That however is technically incorrect, since the first address in the 127.1.0.1/8 subnet is 127.0.0.1. To get the true "first" address, you will also need an IPMask. Since you didn't specify one, you could use DefaultMask for IPv4 addresses (for IPv6 you can't assume a mask, and you must provide it).

http://play.golang.org/p/P_QWwRIBIm

ip := net.IP{192, 168, 1, 10}
ip = ip.To4()
if ip == nil {
	log.Fatal("non ipv4 address")
}

ip = ip.Mask(ip.DefaultMask())
ip[3]++

fmt.Println(ip)
//192.168.1.1

答案2

得分: 4

如果你只需要计算下一个IP地址,下面的nextIP()函数可以完成任务。

用法:

// 输出为 1.0.1.0
fmt.Println(nextIP(net.ParseIP("1.0.0.255"), 1))

nextIP()函数:

func nextIP(ip net.IP, inc uint) net.IP {
    i := ip.To4()
    v := uint(i[0])<<24 + uint(i[1])<<16 + uint(i[2])<<8 + uint(i[3])
    v += inc
    v3 := byte(v & 0xFF)
    v2 := byte((v >> 8) & 0xFF)
    v1 := byte((v >> 16) & 0xFF)
    v0 := byte((v >> 24) & 0xFF)
    return net.IPv4(v0, v1, v2, v3)
}

Playground: https://play.golang.org/p/vHrmftkVjn2

Gist: https://gist.github.com/udhos/b468fbfd376aa0b655b6b0c539a88c03

英文:

If all you need is to compute the next IP address, the function nextIP() below will do the trick.

Usage:

// output is 1.0.1.0
fmt.Println(nextIP(net.ParseIP(&quot;1.0.0.255&quot;), 1))

nextIP():

func nextIP(ip net.IP, inc uint) net.IP {
	i := ip.To4()
	v := uint(i[0])&lt;&lt;24 + uint(i[1])&lt;&lt;16 + uint(i[2])&lt;&lt;8 + uint(i[3])
	v += inc
	v3 := byte(v &amp; 0xFF)
	v2 := byte((v &gt;&gt; 8) &amp; 0xFF)
	v1 := byte((v &gt;&gt; 16) &amp; 0xFF)
	v0 := byte((v &gt;&gt; 24) &amp; 0xFF)
	return net.IPv4(v0, v1, v2, v3)
}

Playground: https://play.golang.org/p/vHrmftkVjn2

Gist: https://gist.github.com/udhos/b468fbfd376aa0b655b6b0c539a88c03

答案3

得分: 3

我会在IP递增后对CIDR进行测试,这样溢出就不会改变预期的子网。

func incrementIP(origIP, cidr string) (string, error) {
    ip := net.ParseIP(origIP)
    _, ipNet, err := net.ParseCIDR(cidr)
    if err != nil {
        return origIP, err
    }
    for i := len(ip) - 1; i >= 0; i-- {
        ip[i]++
        if ip[i] != 0 {
            break
        }
    }
    if !ipNet.Contains(ip) {
        return origIP, errors.New("在递增IP时溢出CIDR")
    }
    return ip.String(), nil
}
英文:

I would test against CIDR after the IP has been incremented, so overflows don't change the expected subnet.

func incrementIP(origIP, cidr string) (string, error) {
	ip := net.ParseIP(origIP)
	_, ipNet, err := net.ParseCIDR(cidr)
	if err != nil {
		return origIP, err
	}
	for i := len(ip) - 1; i &gt;= 0; i-- {
		ip[i]++
		if ip[i] != 0 {
			break
		}
	}
	if !ipNet.Contains(ip) {
		return origIP, errors.New(&quot;overflowed CIDR while incrementing IP&quot;)
	}
	return ip.String(), nil
}

答案4

得分: 1

这是使用IPAddress Go库来实现的简单方法,适用于IPv4和IPv6,并处理了边界情况。免责声明:我是项目经理。

import (
	"fmt"
	"github.com/seancfoley/ipaddress-go/ipaddr"
)

func main() {
	fmt.Println(increment("127.0.0.1"))
	fmt.Println(increment("127.0.0.255"))
	fmt.Println(increment("::1"))
	fmt.Println(increment("255.255.255.255"))
}

func increment(addrString string) *ipaddr.IPAddress {
	addr := ipaddr.NewIPAddressString(addrString).GetAddress()
	return addr.Increment(1)
}

输出:

127.0.0.2
127.0.1.0
::2
<nil>
英文:

This is straightforward using the IPAddress Go library, works for both IPv4 and IPv6, and handles corner cases. Disclaimer: I am the project manager.

import (
	&quot;fmt&quot;
	&quot;github.com/seancfoley/ipaddress-go/ipaddr&quot;
)

func main() {
	fmt.Println(increment(&quot;127.0.0.1&quot;))
	fmt.Println(increment(&quot;127.0.0.255&quot;))
	fmt.Println(increment(&quot;::1&quot;))
	fmt.Println(increment(&quot;255.255.255.255&quot;))
}

func increment(addrString string) *ipaddr.IPAddress {
	addr := ipaddr.NewIPAddressString(addrString).GetAddress()
	return addr.Increment(1)
}

Output:

127.0.0.2
127.0.1.0
::2
&lt;nil&gt;

答案5

得分: 0

我刚刚遇到了这个问题,我想分享一下我的解决方案。虽然不是很高效,但只需要几行代码就可以解决问题。

func nextIP(ip net.IP) net.IP {
    // 转换为 big.Int 并递增
    ipb := big.NewInt(0).SetBytes([]byte(ip))
    ipb.Add(ipb, big.NewInt(1))

    // 添加前导零
    b := ipb.Bytes()
    b = append(make([]byte, len(ip)-len(b)), b...)
    return net.IP(b)
}
英文:

I've encountered this problem just now, and I want to share my solution. It's not that efficient but solves the problem in a few lines.

func nextIP(ip net.IP) net.IP {
    // Convert to big.Int and increment
    ipb := big.NewInt(0).SetBytes([]byte(ip))
    ipb.Add(ipb, big.NewInt(1))

    // Add leading zeros
    b := ipb.Bytes()
    b = append(make([]byte, len(ip)-len(b)), b...)
    return net.IP(b)
}

huangapple
  • 本文由 发表于 2015年7月3日 01:48:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/31191313.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定