Files
zogo/nettest/nettest.go
T
4566704 8a038d4df3 feat(nettest): 自 go-hua 迁入网络连通性探测
- TCP 端口探测 + 原始 ICMP Ping, 持续统计成功率与延迟
- 附测试、examples/nettest 例程与包 README
2026-09-20 12:25:37 +08:00

149 lines
3.0 KiB
Go

// Package nettest 提供网络连通性测试:TCP 端口探测与 ICMP Ping,持续统计成功率与延迟。
package nettest
import (
"fmt"
"sync"
"time"
)
// TestResult 测试结果统计
type TestResult struct {
SuccessCount int // 成功计次
FailCount int // 失败计次
TotalCount int // 总数
TotalTime int // 总耗时
Avg int // 平均耗时 平均值
Min int // 最小耗时 最小值
Max int // 最大耗时 最大值
}
// NetTest 网络测试任务:后台协程周期性探测目标并累计统计
type NetTest struct {
Id int
Name string
Addr string
Port int
Timeout int64
TestResult
Ping *Ping
IsStop bool
IsEcho bool
IsUpdate bool
mux sync.Mutex
}
// NewNetTest 创建网络测试任务
// port 大于 0 时做 TCP 端口探测,等于 0 时做 ICMP Ping(需管理员权限)
// timeout 为超时毫秒数;echo 为 true 时控制台输出每次探测结果
func NewNetTest(id int, name string, addr string, port int, timeout int64, echo bool) *NetTest {
t := new(NetTest)
t.Id = id
t.Name = name
t.Addr = addr
t.Port = port
t.Timeout = timeout
t.IsEcho = echo
t.IsUpdate = false
t.Ping = NewPing(addr, port, timeout)
return t
}
// Set 运行中动态修改测试目标,下一轮探测生效
func (t *NetTest) Set(name string, addr string, port int, timeout int64) {
t.mux.Lock()
t.Name = name
t.Addr = addr
t.Port = port
t.Timeout = timeout
t.IsUpdate = true
t.mux.Unlock()
t.Ping = NewPing(addr, port, timeout)
}
// Start 启动后台测试协程
func (t *NetTest) Start() {
go t.process()
}
// Stop 停止测试协程
func (t *NetTest) Stop() {
t.mux.Lock()
t.IsStop = true
t.mux.Unlock()
}
// process 测试主循环:探测、累计统计、按剩余时间休眠
func (t *NetTest) process() {
isLoop := true
for isLoop {
t.mux.Lock()
timeout := int(t.Timeout)
if t.IsUpdate {
t.Ping.Set(t.Addr, t.Port, t.Timeout)
}
if t.IsStop {
isLoop = false
}
t.mux.Unlock()
if !isLoop {
break
}
et := t.Ping.Test()
if et > 0 {
timeout = timeout - et
}
if timeout > int(timeout) {
timeout = int(timeout)
}
t.mux.Lock()
t.TotalCount++
if et >= 0 {
t.SuccessCount++
} else {
t.FailCount++
}
if et == 0 {
t.TotalTime++
} else if et > 0 {
t.TotalTime += et
}
if t.SuccessCount > 0 {
t.Avg = t.TotalTime / t.SuccessCount
}
if (et < t.Min || t.Min == 0) && et > 0 {
t.Min = et
}
if et > t.Max {
t.Max = et
}
t.mux.Unlock()
if timeout > 0 {
time.Sleep(time.Duration(timeout) * time.Millisecond)
}
if t.IsEcho {
fmt.Printf("来自 %s 的回复: 时间=%dms\n", t.Addr, et)
}
}
}
// GetResult 获取测试结果统计,isReset 为 true 时取完清零
func (t *NetTest) GetResult(isReset bool) TestResult {
t.mux.Lock()
r := TestResult{}
r = t.TestResult
if isReset {
t.SuccessCount = 0
t.FailCount = 0
t.TotalCount = 0
t.TotalTime = 0
t.Avg = 0
t.Min = 0
t.Max = 0
}
t.mux.Unlock()
return r
}