feat(nettest): 自 go-hua 迁入网络连通性探测
- TCP 端口探测 + 原始 ICMP Ping, 持续统计成功率与延迟 - 附测试、examples/nettest 例程与包 README
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
// 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
|
||||
}
|
||||
Reference in New Issue
Block a user