完善tcping

This commit is contained in:
2025-11-23 04:28:29 +08:00
parent 19f224c7fa
commit 2c990ea8a8
2 changed files with 125 additions and 33 deletions

View File

@@ -140,22 +140,49 @@ func (t *TCPingTask) executeTCPing() map[string]interface{} {
conn, err := net.DialTimeout("tcp", net.JoinHostPort(t.Host, strconv.Itoa(t.Port)), 5*time.Second)
latency := time.Since(start).Milliseconds()
// 提取目标IP
var targetIP string
if conn != nil {
if addr, ok := conn.RemoteAddr().(*net.TCPAddr); ok {
targetIP = addr.IP.String()
}
defer conn.Close()
}
// 如果连接失败从host解析
if targetIP == "" {
ips, err := net.LookupIP(t.Host)
if err == nil && len(ips) > 0 {
// 优先使用IPv4
for _, ip := range ips {
if ip.To4() != nil {
targetIP = ip.String()
break
}
}
if targetIP == "" && len(ips) > 0 {
targetIP = ips[0].String()
}
}
}
if err != nil {
return map[string]interface{}{
"timestamp": time.Now().Unix(),
"latency": -1,
"success": false,
"packet_loss": true,
"ip": targetIP,
"error": err.Error(),
}
}
defer conn.Close()
return map[string]interface{}{
"timestamp": time.Now().Unix(),
"latency": float64(latency),
"success": true,
"packet_loss": false,
"ip": targetIP,
}
}

View File

@@ -57,42 +57,107 @@ func handleTCPing(c *gin.Context, url string, params map[string]interface{}) {
}
}
// 执行TCP连接测试
start := time.Now()
conn, err := net.DialTimeout("tcp", net.JoinHostPort(host, portStr), 5*time.Second)
latency := time.Since(start).Milliseconds()
// 执行多次TCP连接测试默认10次和PING一致
const testCount = 10
var latencies []float64
successCount := 0
failureCount := 0
if err != nil {
c.JSON(200, gin.H{
"seq": seq,
"type": "ceTCPing",
"url": url,
"ip": primaryIP,
"host": host,
"port": port,
"latency": -1,
"error": err.Error(),
})
return
}
defer conn.Close()
for i := 0; i < testCount; i++ {
start := time.Now()
conn, err := net.DialTimeout("tcp", net.JoinHostPort(host, portStr), 5*time.Second)
latency := time.Since(start).Milliseconds()
// 如果之前没有获取到IP从连接中获取
if primaryIP == "" {
if addr, ok := conn.RemoteAddr().(*net.TCPAddr); ok {
primaryIP = addr.IP.String()
if err == nil {
// 成功:记录延迟
latencies = append(latencies, float64(latency))
successCount++
conn.Close()
// 如果之前没有获取到IP从连接中获取
if primaryIP == "" {
if addr, ok := conn.RemoteAddr().(*net.TCPAddr); ok {
primaryIP = addr.IP.String()
}
}
} else {
// 失败:记录为丢包
failureCount++
}
}
c.JSON(200, gin.H{
"seq": seq,
"type": "ceTCPing",
"url": url,
"ip": primaryIP,
"host": host,
"port": port,
"latency": latency,
"success": true,
})
// 计算统计信息
packetsTotal := testCount
packetsRecv := successCount
packetsLosrat := float64(failureCount) / float64(testCount) * 100.0
var timeMin, timeMax, timeAvg float64
if len(latencies) > 0 {
timeMin = latencies[0]
timeMax = latencies[0]
sum := 0.0
for _, lat := range latencies {
if lat < timeMin {
timeMin = lat
}
if lat > timeMax {
timeMax = lat
}
sum += lat
}
timeAvg = sum / float64(len(latencies))
} else {
// 全部失败
timeMin = -1
timeMax = -1
timeAvg = -1
}
// 如果之前没有获取到IP尝试从host解析
if primaryIP == "" {
ips, err := net.LookupIP(host)
if err == nil && len(ips) > 0 {
for _, ip := range ips {
if ip.To4() != nil {
primaryIP = ip.String()
break
}
}
if primaryIP == "" && len(ips) > 0 {
primaryIP = ips[0].String()
}
}
}
// 返回格式和PING一致
result := gin.H{
"seq": seq,
"type": "ceTCPing",
"url": url,
"ip": primaryIP,
"host": host,
"port": port,
"packets_total": strconv.Itoa(packetsTotal),
"packets_recv": strconv.Itoa(packetsRecv),
"packets_losrat": packetsLosrat, // float64类型百分比值如10.5表示10.5%
}
// 时间字段:如果是-1全部失败返回字符串"-"否则返回float64
if timeMin < 0 {
result["time_min"] = "-"
result["time_max"] = "-"
result["time_avg"] = "-"
} else {
result["time_min"] = timeMin
result["time_max"] = timeMax
result["time_avg"] = timeAvg
}
// 如果全部失败添加error字段
if successCount == 0 {
result["error"] = "所有TCP连接测试均失败"
}
c.JSON(200, result)
}