Go實戰--golang中擷取公網ip、查看內網ip、檢測ip類型、校正ip區間、ip地址string和int轉換、根據ip判斷地區國家電訊廠商等

來源:互聯網
上載者:User

生命不止,繼續 go go go。。。

之前,有介紹過golang提供的標準庫:net包

Go語言學習之net包(The way to go) 簡要回味net包

func ParseIP

func ParseIP(s string) IP

ParseIP parses s as an IP address, returning the result. The string s can be in dotted decimal (“192.0.2.1”) or IPv6 (“2001:db8::68”) form. If s is not a valid textual representation of an IP address, ParseIP returns nil.

func InterfaceAddrs

func InterfaceAddrs() ([]Addr, error)

InterfaceAddrs returns a list of the system’s unicast interface addresses.

The returned list does not identify the associated interface; use Interfaces and Interface.Addrs for more detail.

type IPNet
An IPNet represents an IP network.

type IPNet struct {        IP   IP     // network number        Mask IPMask // network mask}

type IP

An IP is a single IP address, a slice of bytes. Functions in this package accept either 4-byte (IPv4) or 16-byte (IPv6) slices as input.

Note that in this documentation, referring to an IP address as an IPv4 address or an IPv6 address is a semantic property of the address, not just the length of the byte slice: a 16-byte slice can still be an IPv4 address.

type IP []byte

func IPv4

func IPv4(a, b, c, d byte) IP

IPv4 returns the IP address (in 16-byte form) of the IPv4 address a.b.c.d.

點到為止,更詳細的請看文檔:https://golang.org/pkg/net 什麼是外網IP和內網IP?

tcp/ip協議中,專門保留了三個IP地址地區作為私人地址,其位址範圍如下:
10.0.0.0/8:10.0.0.0~10.255.255.255
172.16.0.0/12:172.16.0.0~172.31.255.255
192.168.0.0/16:192.168.0.0~192.168.255.255

什麼是內網IP

一些小型企業或者學校,通常都是申請一個固定的IP地址,然後通過IP共用(IP Sharing),使用整個公司或學校的機器都能夠訪問互連網。而這些企業或學校的機器使用的IP地址就是內網IP,內網IP是在規劃IPv4協議時,考慮到IP地址資源可能不足,就專門為內部網設計私人IP地址(或稱之為保留地址),一般常用內網IP地址都是這種形式的:10.X.X.X、172.16.X.X-172.31.X.X、192.168.X.X等。需要注意的是,內網的電腦可向Internet上的其他電腦發送串連請求,但Internet上其他的電腦無法向內網的電腦發送串連請求。我們平時可能在內網機器上搭建過網站或者FTP伺服器,而在外網是不能訪問該網站和FTP伺服器的,原因就在於此。

什麼是公網IP

公網IP就是除了保留IP地址以外的IP地址,可以與Internet上的其他電腦隨意互相訪問。我們通常所說的IP地址,其實就是指的公網IP。互連網上的每台電腦都有一個獨立的IP地址,該IP地址唯一確定互連網上的一台電腦。這裡的IP地址就是指的公網IP地址。

怎樣理解互連網上的每台電腦都有一個唯一的IP地址

其實,互連網上的電腦是通過“公網IP+內網IP”來唯一確定的,就像很多大樓都是201房間一樣,房間號可能一樣,但是大樓肯定是唯一的。公網IP地址和內網IP地址也是同樣,不同企業或學校的機器可能有相同的內網IP地址,但是他們的公網IP地址肯定不同。那麼這些企業或學校的電腦是怎樣IP地址共用的呢。這就需要使用NAT(Network Address Translation,網路位址轉譯)功能。當內部電腦要串連互連網時,首先需要通過NAT技術,將內部電腦資料包中有關IP地址的設定都設成NAT主機的公用IP地址,然後再傳送到Internet,雖然內部電腦使用的是私人IP地址,但在串連Internet時,就可以通過NAT主機的NAT技術,將內網我IP地址修改為公網IP地址,如此一來,內網電腦就可以向Internet請求資料了。 擷取公網ip

百度ip,即可查看公網ip

curl命令查看公網ip

curl ipinfo.io/ip

通過http://myexternalip.com/raw擷取公網ip

func get_external() string {    resp, err := http.Get("http://myexternalip.com/raw")    if err != nil {        return ""    }    defer resp.Body.Close()    content, _ := ioutil.ReadAll(resp.Body)    //buf := new(bytes.Buffer)    //buf.ReadFrom(resp.Body)    //s := buf.String()    return string(content)}
擷取本地ip
func GetIntranetIp() {    addrs, err := net.InterfaceAddrs()    if err != nil {        fmt.Println(err)        os.Exit(1)    }    for _, address := range addrs {        // 檢查ip地址判斷是否迴環地址        if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {            if ipnet.IP.To4() != nil {                fmt.Println("ip:", ipnet.IP.String())            }        }    }}

通過dns伺服器8.8.8.8:80擷取使用的ip

func GetPulicIP() string {    conn, _ := net.Dial("udp", "8.8.8.8:80")    defer conn.Close()    localAddr := conn.LocalAddr().String()    idx := strings.LastIndex(localAddr, ":")    return localAddr[0:idx]}
判斷是否是公網ip
func IsPublicIP(IP net.IP) bool {    if IP.IsLoopback() || IP.IsLinkLocalMulticast() || IP.IsLinkLocalUnicast() {        return false    }    if ip4 := IP.To4(); ip4 != nil {        switch true {        case ip4[0] == 10:            return false        case ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31:            return false        case ip4[0] == 192 && ip4[1] == 168:            return false        default:            return true        }    }    return false}
ip地址string轉int
func inet_aton(ipnr net.IP) int64 {    bits := strings.Split(ipnr.String(), ".")    b0, _ := strconv.Atoi(bits[0])    b1, _ := strconv.Atoi(bits[1])    b2, _ := strconv.Atoi(bits[2])    b3, _ := strconv.Atoi(bits[3])    var sum int64    sum += int64(b0) << 24    sum += int64(b1) << 16    sum += int64(b2) << 8    sum += int64(b3)    return sum}
ip地址int轉string
func inet_ntoa(ipnr int64) net.IP {    var bytes [4]byte    bytes[0] = byte(ipnr & 0xFF)    bytes[1] = byte((ipnr >> 8) & 0xFF)    bytes[2] = byte((ipnr >> 16) & 0xFF)    bytes[3] = byte((ipnr >> 24) & 0xFF)    return net.IPv4(bytes[3], bytes[2], bytes[1], bytes[0])}
判斷ip地址區間
func IpBetween(from net.IP, to net.IP, test net.IP) bool {    if from == nil || to == nil || test == nil {        fmt.Println("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 {        fmt.Println("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}
通過淘寶介面根據公網ip擷取國家電訊廠商等資訊

介面:
http://ip.taobao.com/service/getIpInfo.php?ip=

type IPInfo struct {    Code int `json:"code"`    Data IP  `json:"data`}type IP struct {    Country   string `json:"country"`    CountryId string `json:"country_id"`    Area      string `json:"area"`    AreaId    string `json:"area_id"`    Region    string `json:"region"`    RegionId  string `json:"region_id"`    City      string `json:"city"`    CityId    string `json:"city_id"`    Isp       string `json:"isp"`}func TabaoAPI(ip string) *IPInfo {    url := "http://ip.taobao.com/service/getIpInfo.php?ip="    url += ip    resp, err := http.Get(url)    if err != nil {        return nil    }    defer resp.Body.Close()    out, err := ioutil.ReadAll(resp.Body)    if err != nil {        return nil    }    var result IPInfo    if err := json.Unmarshal(out, &result); err != nil {        return nil    }    return &result}
完整代碼
package mainimport (    "bytes"    "encoding/json"    "fmt"    "io/ioutil"    "net"    "net/http"    "os"    "strconv"    "strings")type IPInfo struct {    Code int `json:"code"`    Data IP  `json:"data`}type IP struct {    Country   string `json:"country"`    CountryId string `json:"country_id"`    Area      string `json:"area"`    AreaId    string `json:"area_id"`    Region    string `json:"region"`    RegionId  string `json:"region_id"`    City      string `json:"city"`    CityId    string `json:"city_id"`    Isp       string `json:"isp"`}func main() {    external_ip := get_external()    external_ip = strings.Replace(external_ip, "\n", "", -1)    fmt.Println("公網ip是: ", external_ip)    fmt.Println("------Dividing Line------")    ip := net.ParseIP(external_ip)    if ip == nil {        fmt.Println("您輸入的不是有效IP地址,請重新輸入。")    } else {        result := TabaoAPI(string(external_ip))        if result != nil {            fmt.Println("國家:", result.Data.Country)            fmt.Println("地區:", result.Data.Area)            fmt.Println("城市:", result.Data.City)            fmt.Println("電訊廠商:", result.Data.Isp)        }    }    fmt.Println("------Dividing Line------")    GetIntranetIp()    fmt.Println("------Dividing Line------")    ip_int := inet_aton(net.ParseIP(external_ip))    fmt.Println("Convert IPv4 address to decimal number(base 10) :", ip_int)    ip_result := inet_ntoa(ip_int)    fmt.Println("Convert decimal number(base 10) to IPv4 address:", ip_result)    fmt.Println("------Dividing Line------")    is_between := IpBetween(net.ParseIP("0.0.0.0"), net.ParseIP("255.255.255.255"), net.ParseIP(external_ip))    fmt.Println("check result: ", is_between)    fmt.Println("------Dividing Line------")    is_public_ip := IsPublicIP(net.ParseIP(external_ip))    fmt.Println("It is public ip: ", is_public_ip)    is_public_ip = IsPublicIP(net.ParseIP("169.254.85.131"))    fmt.Println("It is public ip: ", is_public_ip)    fmt.Println("------Dividing Line------")    fmt.Println(GetPulicIP())}func get_external() string {    resp, err := http.Get("http://myexternalip.com/raw")    if err != nil {        return ""    }    defer resp.Body.Close()    content, _ := ioutil.ReadAll(resp.Body)    buf := new(bytes.Buffer)    buf.ReadFrom(resp.Body)    //s := buf.String()    return string(content)}func GetIntranetIp() {    addrs, err := net.InterfaceAddrs()    if err != nil {        fmt.Println(err)        os.Exit(1)    }    for _, address := range addrs {        // 檢查ip地址判斷是否迴環地址        if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {            if ipnet.IP.To4() != nil {                fmt.Println("ip:", ipnet.IP.String())            }        }    }}func TabaoAPI(ip string) *IPInfo {    url := "http://ip.taobao.com/service/getIpInfo.php?ip="    url += ip    resp, err := http.Get(url)    if err != nil {        return nil    }    defer resp.Body.Close()    out, err := ioutil.ReadAll(resp.Body)    if err != nil {        return nil    }    var result IPInfo    if err := json.Unmarshal(out, &result); err != nil {        return nil    }    return &result}func inet_ntoa(ipnr int64) net.IP {    var bytes [4]byte    bytes[0] = byte(ipnr & 0xFF)    bytes[1] = byte((ipnr >> 8) & 0xFF)    bytes[2] = byte((ipnr >> 16) & 0xFF)    bytes[3] = byte((ipnr >> 24) & 0xFF)    return net.IPv4(bytes[3], bytes[2], bytes[1], bytes[0])}func inet_aton(ipnr net.IP) int64 {    bits := strings.Split(ipnr.String(), ".")    b0, _ := strconv.Atoi(bits[0])    b1, _ := strconv.Atoi(bits[1])    b2, _ := strconv.Atoi(bits[2])    b3, _ := strconv.Atoi(bits[3])    var sum int64    sum += int64(b0) << 24    sum += int64(b1) << 16    sum += int64(b2) << 8    sum += int64(b3)    return sum}func IpBetween(from net.IP, to net.IP, test net.IP) bool {    if from == nil || to == nil || test == nil {        fmt.Println("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 {        fmt.Println("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}func IsPublicIP(IP net.IP) bool {    if IP.IsLoopback() || IP.IsLinkLocalMulticast() || IP.IsLinkLocalUnicast() {        return false    }    if ip4 := IP.To4(); ip4 != nil {        switch true {        case ip4[0] == 10:            return false        case ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31:            return false        case ip4[0] == 192 && ip4[1] == 168:            return false        default:            return true        }    }    return false}func GetPulicIP() string {    conn, _ := net.Dial("udp", "8.8.8.8:80")    defer conn.Close()    localAddr := conn.LocalAddr().String()    idx := strings.LastIndex(localAddr, ":")    return localAddr[0:idx]}

輸出:

公網ip是:  222.128.17*.***------Dividing Line------國家: 中國地區: 華北城市: 北京市電訊廠商: 聯通------Dividing Line------ip: 169.254.85.131ip: 169.254.64.29ip: 169.254.211.178ip: 192.168.106.1ip: 192.168.154.1ip: 169.254.212.223ip: 192.168.10.26ip: 169.254.63.20------Dividing Line------Convert IPv4 address to decimal number(base 10) : 373297****Convert decimal number(base 10) to IPv4 address: 222.128.17*.***------Dividing Line------check result:  true------Dividing Line------It is public ip:  trueIt is public ip:  false------Dividing Line------192.168.10.26

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.