簡體   English   中英

如何獲取下一個 IP 地址?

[英]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
}

只需增加 IP 地址中的最后一個八位字節

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

然而,這在技術上是不正確的,因為 127.1.0.1/8 子網中的第一個地址是 127.0.0.1。 要獲得真正的“第一個”地址,您還需要一個 IPMask。 由於您沒有指定一個,您可以將 DefaultMask 用於 IPv4 地址(對於 IPv6,您不能假定掩碼,您必須提供它)。

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

如果您只需要計算下一個 IP 地址,下面的 function nextIP() 就可以解決問題。

用法:

// output is 1.0.1.0
fmt.Println(nextIP(net.ParseIP("1.0.0.255"), 1))

下一個IP():

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)
}

游樂場: https://play.golang.org/p/vHrmftkVjn2

要點: https://gist.github.com/udhos/b468fbfd376aa0b655b6b0c539a88c03

在 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("overflowed CIDR while incrementing IP")
    }
    return ip.String(), nil
}

剛才也遇到了這個問題,想分享一下我的解決方法。 它不是那么有效,但只需幾行就解決了問題。

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)
}

使用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)
}

Output:

127.0.0.2
127.0.1.0
::2
<nil>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM