1 Star 0 Fork 0

ixgo/ixUtils

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
net.go 11.28 KB
一键复制 编辑 原始数据 按行查看 历史
lixu 提交于 2025-09-19 17:12 +08:00 . Initial commit
/*
* @Author: lixu lixu@puchigames.com
* @Date: 2025-09-18 10:10:00
* @LastEditors: lixu lixu@puchigames.com
* @LastEditTime: 2025-09-18 10:10:00
* @FilePath: /go-helper/utils/net.go
* @Description: 网络工具函数,包含IP处理、网络检测等功能
*/
package ixUtils
import (
"context"
"fmt"
"io"
"net"
"net/http"
"strconv"
"strings"
"time"
)
// ========== IP处理函数 ==========
// GetLocalIP 获取本机内网IP地址
func GetLocalIP() string {
addrs, err := net.InterfaceAddrs()
if err != nil {
return ""
}
for _, addr := range addrs {
if ipNet, ok := addr.(*net.IPNet); ok && !ipNet.IP.IsLoopback() {
if ipNet.IP.To4() != nil {
return ipNet.IP.String()
}
}
}
return ""
}
// GetLocalIPs 获取本机所有内网IP地址
func GetLocalIPs() []string {
var ips []string
addrs, err := net.InterfaceAddrs()
if err != nil {
return ips
}
for _, addr := range addrs {
if ipNet, ok := addr.(*net.IPNet); ok && !ipNet.IP.IsLoopback() {
if ipNet.IP.To4() != nil {
ips = append(ips, ipNet.IP.String())
}
}
}
return ips
}
// GetPublicIP 获取公网IP地址
func GetPublicIP() string {
// 尝试多个服务,提高成功率
urls := []string{
"https://api.ipify.org",
"https://ifconfig.me",
"https://icanhazip.com",
"https://ident.me",
}
client := &http.Client{
Timeout: 10 * time.Second,
}
for _, url := range urls {
resp, err := client.Get(url)
if err != nil {
continue
}
defer resp.Body.Close()
if resp.StatusCode == http.StatusOK {
body, err := io.ReadAll(resp.Body)
if err != nil {
continue
}
ip := strings.TrimSpace(string(body))
if IsValidIP(ip) {
return ip
}
}
}
return ""
}
// IsPrivateIP 检查是否为私有IP地址
func IsPrivateIP(ip string) bool {
if !IsValidIP(ip) {
return false
}
parsedIP := net.ParseIP(ip)
if parsedIP == nil {
return false
}
// 检查IPv4私有地址范围
if parsedIP.To4() != nil {
// 10.0.0.0/8
if parsedIP[12] == 10 {
return true
}
// 172.16.0.0/12
if parsedIP[12] == 172 && parsedIP[13] >= 16 && parsedIP[13] <= 31 {
return true
}
// 192.168.0.0/16
if parsedIP[12] == 192 && parsedIP[13] == 168 {
return true
}
// 127.0.0.0/8 (loopback)
if parsedIP[12] == 127 {
return true
}
}
return false
}
// IsPublicIP 检查是否为公网IP地址
func IsPublicIP(ip string) bool {
if !IsValidIP(ip) {
return false
}
return !IsPrivateIP(ip)
}
// IPToInt 将IP地址转换为32位无符号整数
func IPToInt(ip string) uint32 {
if !IsValidIP(ip) {
return 0
}
parsedIP := net.ParseIP(ip)
if parsedIP == nil {
return 0
}
// 转换为IPv4
ipv4 := parsedIP.To4()
if ipv4 == nil {
return 0
}
return uint32(ipv4[0])<<24 + uint32(ipv4[1])<<16 + uint32(ipv4[2])<<8 + uint32(ipv4[3])
}
// IntToIP 将32位无符号整数转换为IP地址
func IntToIP(ipInt uint32) string {
return fmt.Sprintf("%d.%d.%d.%d",
byte(ipInt>>24),
byte(ipInt>>16),
byte(ipInt>>8),
byte(ipInt))
}
// IsValidIP 检查IP地址格式是否有效
func IsValidIP(ip string) bool {
return net.ParseIP(ip) != nil
}
// IsValidIPv4 检查是否为有效的IPv4地址
func IsValidIPv4(ip string) bool {
parsedIP := net.ParseIP(ip)
return parsedIP != nil && parsedIP.To4() != nil
}
// IsValidIPv6 检查是否为有效的IPv6地址
func IsValidIPv6(ip string) bool {
parsedIP := net.ParseIP(ip)
return parsedIP != nil && parsedIP.To4() == nil
}
// ========== 网络检测函数 ==========
// Ping 检测主机是否可达(使用TCP连接测试)
func Ping(host string) bool {
return PingWithTimeout(host, 3*time.Second)
}
// PingWithTimeout 带超时的Ping检测
func PingWithTimeout(host string, timeout time.Duration) bool {
// 如果没有指定端口,使用80端口
if !strings.Contains(host, ":") {
host = host + ":80"
}
conn, err := net.DialTimeout("tcp", host, timeout)
if err != nil {
return false
}
defer conn.Close()
return true
}
// IsPortOpen 检查指定主机的端口是否开放
func IsPortOpen(host string, port int) bool {
return IsPortOpenWithTimeout(host, port, 3*time.Second)
}
// IsPortOpenWithTimeout 带超时的端口检测
func IsPortOpenWithTimeout(host string, port int, timeout time.Duration) bool {
address := net.JoinHostPort(host, strconv.Itoa(port))
conn, err := net.DialTimeout("tcp", address, timeout)
if err != nil {
return false
}
defer conn.Close()
return true
}
// ScanPorts 扫描主机的端口范围
func ScanPorts(host string, startPort, endPort int) []int {
return ScanPortsWithTimeout(host, startPort, endPort, 1*time.Second)
}
// ScanPortsWithTimeout 带超时的端口扫描
func ScanPortsWithTimeout(host string, startPort, endPort int, timeout time.Duration) []int {
var openPorts []int
for port := startPort; port <= endPort; port++ {
if IsPortOpenWithTimeout(host, port, timeout) {
openPorts = append(openPorts, port)
}
}
return openPorts
}
// GetDomainIP 获取域名对应的IP地址列表
func GetDomainIP(domain string) []string {
return GetDomainIPWithTimeout(domain, 5*time.Second)
}
// GetDomainIPWithTimeout 带超时的域名解析
func GetDomainIPWithTimeout(domain string, timeout time.Duration) []string {
var ips []string
// 创建带超时的解析器
resolver := &net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
d := net.Dialer{
Timeout: timeout,
}
return d.DialContext(ctx, network, address)
},
}
addrs, err := resolver.LookupIPAddr(context.TODO(), domain)
if err != nil {
return ips
}
for _, addr := range addrs {
ips = append(ips, addr.IP.String())
}
return ips
}
// GetDomainIPv4 获取域名对应的IPv4地址列表
func GetDomainIPv4(domain string) []string {
allIPs := GetDomainIP(domain)
var ipv4s []string
for _, ip := range allIPs {
if IsValidIPv4(ip) {
ipv4s = append(ipv4s, ip)
}
}
return ipv4s
}
// GetDomainIPv6 获取域名对应的IPv6地址列表
func GetDomainIPv6(domain string) []string {
allIPs := GetDomainIP(domain)
var ipv6s []string
for _, ip := range allIPs {
if IsValidIPv6(ip) {
ipv6s = append(ipv6s, ip)
}
}
return ipv6s
}
// ========== 网络信息获取 ==========
// GetMACAddress 获取本机MAC地址
func GetMACAddress() string {
interfaces, err := net.Interfaces()
if err != nil {
return ""
}
for _, inter := range interfaces {
// 跳过loopback和down状态的接口
if inter.Flags&net.FlagLoopback == 0 && inter.Flags&net.FlagUp != 0 {
if len(inter.HardwareAddr) > 0 {
return inter.HardwareAddr.String()
}
}
}
return ""
}
// GetAllMACAddresses 获取所有网络接口的MAC地址
func GetAllMACAddresses() map[string]string {
macAddrs := make(map[string]string)
interfaces, err := net.Interfaces()
if err != nil {
return macAddrs
}
for _, inter := range interfaces {
if len(inter.HardwareAddr) > 0 {
macAddrs[inter.Name] = inter.HardwareAddr.String()
}
}
return macAddrs
}
// GetNetworkInterfaces 获取网络接口信息
func GetNetworkInterfaces() []NetworkInterface {
var interfaces []NetworkInterface
netInterfaces, err := net.Interfaces()
if err != nil {
return interfaces
}
for _, inter := range netInterfaces {
addrs, err := inter.Addrs()
if err != nil {
continue
}
var ips []string
for _, addr := range addrs {
if ipNet, ok := addr.(*net.IPNet); ok {
ips = append(ips, ipNet.IP.String())
}
}
interfaces = append(interfaces, NetworkInterface{
Name: inter.Name,
HardwareAddr: inter.HardwareAddr.String(),
Flags: inter.Flags.String(),
MTU: inter.MTU,
IPs: ips,
})
}
return interfaces
}
// NetworkInterface 网络接口信息结构
type NetworkInterface struct {
Name string `json:"name"`
HardwareAddr string `json:"hardware_addr"`
Flags string `json:"flags"`
MTU int `json:"mtu"`
IPs []string `json:"ips"`
}
// ========== 网络工具函数 ==========
// IsValidPort 检查端口号是否有效
func IsValidPort(port int) bool {
return port > 0 && port <= 65535
}
// IsValidDomain 检查域名格式是否有效(简单检查)
func IsValidDomain(domain string) bool {
if len(domain) == 0 || len(domain) > 253 {
return false
}
// 基本格式检查
if strings.HasPrefix(domain, ".") || strings.HasSuffix(domain, ".") {
return false
}
parts := strings.Split(domain, ".")
if len(parts) < 2 {
return false
}
for _, part := range parts {
if len(part) == 0 || len(part) > 63 {
return false
}
// 简单的字符检查
for _, r := range part {
if !((r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') ||
(r >= '0' && r <= '9') || r == '-') {
return false
}
}
}
return true
}
// GetFreePort 获取一个可用的端口号
func GetFreePort() (int, error) {
addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
if err != nil {
return 0, err
}
l, err := net.ListenTCP("tcp", addr)
if err != nil {
return 0, err
}
defer l.Close()
return l.Addr().(*net.TCPAddr).Port, nil
}
// IsLocalhost 检查是否为本地地址
func IsLocalhost(host string) bool {
return host == "localhost" || host == "127.0.0.1" || host == "::1"
}
// NormalizeHost 标准化主机地址(移除端口)
func NormalizeHost(hostPort string) string {
host, _, err := net.SplitHostPort(hostPort)
if err != nil {
return hostPort // 如果没有端口,直接返回
}
return host
}
// JoinHostPort 组合主机和端口
func JoinHostPort(host string, port int) string {
return net.JoinHostPort(host, strconv.Itoa(port))
}
// ParseHostPort 解析主机和端口
func ParseHostPort(hostPort string) (host string, port int, err error) {
host, portStr, err := net.SplitHostPort(hostPort)
if err != nil {
return "", 0, err
}
port, err = strconv.Atoi(portStr)
if err != nil {
return "", 0, err
}
return host, port, nil
}
// ========== 网络测试工具 ==========
// TestConnection 测试网络连接
type ConnectionTest struct {
Host string `json:"host"`
Port int `json:"port"`
Protocol string `json:"protocol"`
Success bool `json:"success"`
Duration time.Duration `json:"duration"`
Error string `json:"error,omitempty"`
}
// TestTCPConnection 测试TCP连接
func TestTCPConnection(host string, port int) ConnectionTest {
start := time.Now()
test := ConnectionTest{
Host: host,
Port: port,
Protocol: "tcp",
}
conn, err := net.DialTimeout("tcp", JoinHostPort(host, port), 5*time.Second)
test.Duration = time.Since(start)
if err != nil {
test.Success = false
test.Error = err.Error()
} else {
test.Success = true
conn.Close()
}
return test
}
// TestUDPConnection 测试UDP连接
func TestUDPConnection(host string, port int) ConnectionTest {
start := time.Now()
test := ConnectionTest{
Host: host,
Port: port,
Protocol: "udp",
}
conn, err := net.DialTimeout("udp", JoinHostPort(host, port), 5*time.Second)
test.Duration = time.Since(start)
if err != nil {
test.Success = false
test.Error = err.Error()
} else {
test.Success = true
conn.Close()
}
return test
}
// BatchTestConnections 批量测试连接
func BatchTestConnections(hosts []string, ports []int) []ConnectionTest {
var results []ConnectionTest
for _, host := range hosts {
for _, port := range ports {
result := TestTCPConnection(host, port)
results = append(results, result)
}
}
return results
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/ixgo/utils.git
git@gitee.com:ixgo/utils.git
ixgo
utils
ixUtils
v1.0.3

搜索帮助