本文最后更新于 2025-10-29,文章内容可能已经过时。

在Golang中判断网络连接状态有多种方法,以下是几种常用且有效的方式:

1. 使用ping库检测网络连通性

最常用的方法是使用github.com/go-ping/ping库进行ping测试,可以判断目标主机是否可达:

package main

import (
    "fmt"
    "github.com/go-ping/ping"
    "os"
    "time"
)

func CheckHostOnline(ipaddr string) bool {
    pinger, err := ping.NewPinger(ipaddr)
    if err != nil {
        fmt.Printf("创建ping实例失败: %v\n", err)
        return false
    }
    
    pinger.SetPrivileged(true) // 需要root权限
    pinger.Count = 1          // 发送1个ping包
    pinger.Timeout = time.Millisecond * 500 // 超时时间
    pinger.Interval = time.Second // 发送间隔
    
    err = pinger.Run()
    if err != nil {
        fmt.Printf("ping %s 失败: %v\n", ipaddr, err)
        return false
    }
    
    stats := pinger.Statistics()
    return stats.PacketsRecv > 0
}

func main() {
    if len(os.Args) < 2 {
        fmt.Println("请提供目标IP地址")
        return
    }
    
    ipaddr := os.Args[1]
    fmt.Printf("正在ping %s...\n", ipaddr)
    
    if CheckHostOnline(ipaddr) {
        fmt.Printf("主机 %s 在线\n", ipaddr)
    } else {
        fmt.Printf("主机 %s 离线\n", ipaddr)
    }
}

2. 使用标准net包进行简单网络连接测试

可以尝试连接到公共DNS服务器(如8.8.8.8)来判断基本网络连通性:

package main

import (
    "fmt"
    "net"
    "time"
)

func CheckNetworkConnectivity() bool {
    conn, err := net.DialTimeout("tcp", "8.8.8.8:53", 2*time.Second)
    if err != nil {
        return false
    }
    defer conn.Close()
    return true
}

func main() {
    if CheckNetworkConnectivity() {
        fmt.Println("网络连接正常")
    } else {
        fmt.Println("网络连接异常")
    }
}

3. 检测TCP连接是否已关闭

通过设置读取截止时间并尝试读取数据,可以有效判断连接状态:

package main

import (
    "fmt"
    "io"
    "log"
    "net"
    "time"
)

func IsConnectionClosed(conn net.Conn) bool {
    defer conn.Close()
    // 设置读取截止时间为当前时间,立即检查
    conn.SetReadDeadline(time.Now())
    _, err := conn.Read(make([]byte, 1))
    
    if err == nil {
        // 成功读取,连接仍然打开
        return false
    }
    
    if err == io.EOF {
        // 连接已关闭
        return true
    }
    
    if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
        // 超时,连接可能仍然打开
        return false
    }
    
    return false
}

4. 检查网络错误类型

通过判断网络错误类型,可以更精确地了解网络问题:

package main

import (
    "fmt"
    "net"
    "os"
)

func CheckNetworkError(err error) {
    if err == nil {
        return
    }
    
    // 检查是否是网络错误
    netErr, ok := err.(net.Error)
    if !ok {
        fmt.Printf("非网络错误: %v\n", err)
        return
    }
    
    if netErr.Timeout() {
        fmt.Println("网络超时")
    }
    
    if netErr.Temporary() {
        fmt.Println("临时性网络错误")
    }
    
    // 检查底层错误
    if opErr, ok := err.(*net.OpError); ok {
        fmt.Printf("操作错误: %s\n", opErr.Op)
        fmt.Printf("网络类型: %s\n", opErr.Net)
        fmt.Printf("错误详情: %v\n", opErr.Err)
        
        // 检查具体系统错误
        if sysErr, ok := opErr.Err.(*os.SyscallError); ok {
            fmt.Printf("系统调用错误: %s\n", sysErr.Syscall)
            fmt.Printf("错误码: %v\n", sysErr.Err)
        }
    }
}

5. 使用netlink库检查本地网络接口状态

对于Linux系统,可以使用github.com/vishvananda/netlink库检查本地网络接口状态:

package main

import (
    "fmt"
    "github.com/vishvananda/netlink"
)

func CheckNetworkInterfaces() {
    links, err := netlink.LinkList()
    if err != nil {
        fmt.Printf("获取网络接口失败: %v\n", err)
        return
    }
    
    fmt.Println("网络接口状态:")
    for _, link := range links {
        if link.Attrs().Flags&netlink.FlagUp != 0 {
            fmt.Printf("接口 %s 已启用\n", link.Attrs().Name)
        } else {
            fmt.Printf("接口 %s 已禁用\n", link.Attrs().Name)
        }
    }
}

实用建议

  1. 综合使用多种方法:可以组合使用ping测试和连接测试,提高判断准确性
  2. 考虑超时设置:合理设置超时时间,避免长时间等待
  3. 权限问题:使用ping库通常需要root权限,注意处理权限问题
  4. 错误处理:对网络错误进行详细分析,可以更好地诊断问题
  5. 定期检查:对于需要持续监控的场景,可以设置定时检查机制

以上方法可以根据具体需求选择使用,对于大多数场景,使用github.com/go-ping/ping库进行ping测试是最简单有效的网络连通性判断方法。