• 用go获取IPv4地址,WLAN的IPv4地址,本机公网IP地址详解


    获取IPv4地址

    下面的代码会打印出本机所有的IPv4地址。这个方法可能会返回多个IP地址,因为一台机器可能有多个网络接口,每个接口可能有一个或多个IP地址。

    package main
    
    import (
    	"fmt"
    	"net"
    	"os"
    )
    
    func main() {
    	addrs, err := net.InterfaceAddrs()
    	if err != nil {
    		fmt.Println(err)
    		os.Exit(1)
    	}
    
    	for _, addr := range addrs {
    		if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
    			if ipnet.IP.To4() != nil {
    				fmt.Println("IPv4: ", ipnet.IP.String())
    			}
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    运行结果:

    IPv4:  169.254.157.225
    IPv4:  169.254.28.142
    IPv4:  169.254.211.187
    IPv4:  192.168.144.1
    IPv4:  192.168.253.1
    IPv4:  10.252.64.116
    IPv4:  169.254.106.194
    IPv4:  169.254.109.149
    IPv4:  172.28.240.1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    甚至比我在终端使用ipconfig命令得到的IPv4地址还要多。
    image-20231005095013864

    获取WLAN的IPv4地址

    当然这么多IPv4地址并不一定都是我们想要的,对于用wifi上网的电脑,我们想获取无线局域网适配器 WLAN的IPv4地址可以按下面的代码操作:

    package main
    
    import (
    	"fmt"
    	"net"
    	"os"
    )
    
    func main() {
    	interfaces, err := net.Interfaces()
    	if err != nil {
    		fmt.Println(err)
    		os.Exit(1)
    	}
    
    	for _, i := range interfaces {
    		if i.Name == "WLAN" {
    			addrs, err := i.Addrs()
    			if err != nil {
    				fmt.Println(err)
    				continue
    			}
    
    			for _, addr := range addrs {
    				if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
    					if ipnet.IP.To4() != nil {
    						fmt.Println("IPv4: ", ipnet.IP.String())
    					}
    				}
    			}
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    运行结果:

    IPv4:  10.252.64.116
    
    • 1

    经过和上图比对,结果正确。

    获取本机公网IP地址

    那如果我们想获取本机的公网IP地址,那该怎么操作呢?我这里介绍两种方法:

    第一种方法将通过与Google的公共DNS服务器建立UDP连接来获取公网IP地址。

    package main
    
    import (
    	"fmt"
    	"net"
    )
    
    func main() {
    	conn, err := net.Dial("udp", "8.8.8.8:80")
    	if err != nil {
    		fmt.Println(err)
    		return
    	}
    	defer conn.Close()
    
    	localAddr := conn.LocalAddr().(*net.UDPAddr)
    
    	fmt.Println("My public IP address is:", localAddr.IP.String())
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    运行结果:

    My public IP address is: 10.252.64.116
    
    • 1

    经过比对,结果正确。我们可以发现如果我们的电脑是用WiFi上网的,用此方法得出的结果与WLAN的IPv4地址相同。

    第二种方法依赖于第三方服务,如果该服务不可用,可能无法获取到IP地址。此外,由于这个方法涉及到网络通信,所以可能会比获取本地IP地址慢一些。同时该方法出错的风险也较高。

    package main
    
    import (
    	"fmt"
    	"io/ioutil"
    	"net/http"
    )
    
    func main() {
    	resp, err := http.Get("https://api.ipify.org")
    	if err != nil {
    		fmt.Println(err)
    		return
    	}
    	defer resp.Body.Close()
    
    	ip, err := ioutil.ReadAll(resp.Body)
    	if err != nil {
    		fmt.Println(err)
    		return
    	}
    
    	fmt.Println("My public IP address is: ", string(ip))
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    除了使用 https://api.ipify.org,还有其他一些服务可以提供公网IP地址,例如 https://ifconfig.mehttps://icanhazip.com

    获取本机空闲端口

    此方法可以动态获取本机的空闲端口,比如说你有web应用需要上线,就不用自己手动指定端口了。

    package main
    
    import (
    	"fmt"
    	"net"
    )
    
    func main() {
    	addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
    	if err != nil {
    		panic(err)
    	}
    
    	l, err := net.ListenTCP("tcp", addr)
    	if err != nil {
    		panic(err)
    	}
    	defer l.Close()
    	port := l.Addr().(*net.TCPAddr).Port
    	fmt.Println(port)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    运行结果:

    54791
    
    • 1
  • 相关阅读:
    个人用户如何保证企业邮箱安全?【网易企业邮箱】
    React学习笔记四
    最强大脑记忆曲线(5)——主程序设计
    URP渲染管线实战教程系列 之URP渲染管线实战解密(一)
    docker 安装minio 教程
    iOS大厂面试查漏补缺
    Cloudflare实现反代的两种方式,其中一种支持CNAME域名接入
    IDEA 2022.2.1 Beta 2发布:新增支持Java 18、增强JUnit 5的支持
    王道数据结构笔记03-红黑树/RBT
    【初识JavaScript-03】
  • 原文地址:https://blog.csdn.net/m0_63230155/article/details/133576893