gitee.com/zhongguo168a/gocodes@v0.0.0-20230609140523-e1828349603f/gox/netx/network.go (about)

     1  package netx
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/pkg/errors"
     6  	"io"
     7  	"net"
     8  	"net/http"
     9  	"strings"
    10  )
    11  
    12  const (
    13  	networkSpliter = "@"
    14  )
    15  
    16  func ParseNetwork(str string) (network, addr string, err error) {
    17  	if idx := strings.Index(str, networkSpliter); idx == -1 {
    18  		err = fmt.Errorf("addr: \"%s\" error, must be network@tcp:port or network@unixsocket", str)
    19  		return
    20  	} else {
    21  		network = str[:idx]
    22  		addr = str[idx+1:]
    23  		return
    24  	}
    25  }
    26  
    27  func ConvertAddr(addr string) (r string, err error) {
    28  	iip, geterr := GetIntranetIp()
    29  	if geterr != nil {
    30  		err = errors.Wrap(geterr, "get intranet ip")
    31  		return
    32  	}
    33  	ip := iip.String()
    34  	addr = strings.ReplaceAll(addr, "localnet", ip)
    35  
    36  	return addr, nil
    37  }
    38  
    39  func GetInternalIPByUDP() (string, error) {
    40  	// 思路来自于Python版本的内网IP获取,其他版本不准确
    41  	conn, err := net.Dial("udp", "8.8.8.8:80")
    42  	if err != nil {
    43  		return "", errors.New("internal IP fetch failed, detail:" + err.Error())
    44  	}
    45  	defer conn.Close()
    46  
    47  	// udp 面向无连接,所以这些东西只在你本地捣鼓
    48  	res := conn.LocalAddr().String()
    49  	res = strings.Split(res, ":")[0]
    50  	return res, nil
    51  }
    52  
    53  func GetIntranetIp() (ip net.IP, err error) {
    54  	ifaces, err := net.Interfaces()
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  
    59  	addresses := []net.IP{}
    60  	for _, iface := range ifaces {
    61  
    62  		if iface.Flags&net.FlagUp == 0 {
    63  			continue // interface down
    64  		}
    65  
    66  		if iface.Flags&net.FlagLoopback != 0 {
    67  			continue // loopback interface
    68  		}
    69  
    70  		addrs, adderr := iface.Addrs()
    71  		if adderr != nil {
    72  			continue
    73  		}
    74  
    75  		for _, addr := range addrs {
    76  			var lip net.IP
    77  			switch v := addr.(type) {
    78  			case *net.IPNet:
    79  				lip = v.IP
    80  			case *net.IPAddr:
    81  				lip = v.IP
    82  			}
    83  
    84  			if lip == nil || lip.IsLoopback() {
    85  				continue
    86  			}
    87  			lip = lip.To4()
    88  			if lip == nil {
    89  				continue // not an ipv4 address
    90  			}
    91  			addresses = append(addresses, lip)
    92  		}
    93  	}
    94  	if len(addresses) == 0 {
    95  		return nil, fmt.Errorf("no address Found, net.InterfaceAddrs: %v", addresses)
    96  	}
    97  	//only need first
    98  	return addresses[0], nil
    99  }
   100  func GetExternalIP() (string, error) {
   101  	// 有很多类似网站提供这种服务,这是我知道且正在用的
   102  	// 备用:https://myexternalip.com/raw (cip.cc 应该是够快了,我连手机热点的时候不太稳,其他自己查)
   103  	response, err := http.Get("http://ip.cip.cc")
   104  	if err != nil {
   105  		return "", errors.New("external IP fetch failed, detail:" + err.Error())
   106  	}
   107  
   108  	defer response.Body.Close()
   109  	res := ""
   110  
   111  	// 类似的API应当返回一个纯净的IP地址
   112  	for {
   113  		tmp := make([]byte, 32)
   114  		n, err := response.Body.Read(tmp)
   115  		if err != nil {
   116  			if err != io.EOF {
   117  				return "", errors.New("external IP fetch failed, detail:" + err.Error())
   118  			}
   119  			res += string(tmp[:n])
   120  			break
   121  		}
   122  		res += string(tmp[:n])
   123  	}
   124  
   125  	return strings.TrimSpace(res), nil
   126  }
   127  
   128  func ConvertToZeroIP(addr string) string {
   129  	if addr == "" {
   130  		return addr
   131  	}
   132  	arr := strings.Split(addr, ":")
   133  	port := arr[1]
   134  	return "0.0.0.0:" + port
   135  }
   136  
   137  // 0.0.0.0:port
   138  func ConvertZeroIPToPublic(addr string) string {
   139  	return strings.ReplaceAll(addr, "0.0.0.0", GetPulicIP())
   140  }
   141  
   142  func GetPulicIP() string {
   143  	conn, _ := net.Dial("udp", "8.8.8.8:80")
   144  	defer conn.Close()
   145  	localAddr := conn.LocalAddr().String()
   146  	idx := strings.LastIndex(localAddr, ":")
   147  	return localAddr[0:idx]
   148  }
   149  
   150  func GetPublicAddr(addr string) (x string) {
   151  	arr := strings.Split(addr, ":")
   152  	if len(arr) == 0 {
   153  		return
   154  	}
   155  	if arr[0] == "" {
   156  		x = GetPulicIP() + addr
   157  	} else {
   158  		x = addr
   159  	}
   160  	return
   161  }