From a11eac6886a9ff3dd4d80ca6b6278e03a1b77c6f Mon Sep 17 00:00:00 2001 From: yoyo Date: Sat, 22 Nov 2025 18:14:24 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=BF=94=E5=9B=9E=E6=97=B6?= =?UTF-8?q?=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/continuous/ping.go | 46 ++++++++++++++++++++++++++++------- internal/continuous/tcping.go | 17 +++++++++---- internal/handler/dns.go | 26 ++++++++++++++------ 3 files changed, 68 insertions(+), 21 deletions(-) diff --git a/internal/continuous/ping.go b/internal/continuous/ping.go index 03e8641..8360d58 100644 --- a/internal/continuous/ping.go +++ b/internal/continuous/ping.go @@ -40,16 +40,13 @@ func NewPingTask(taskID, target string, interval, maxDuration time.Duration) *Pi } func (t *PingTask) Start(ctx context.Context, resultCallback func(result map[string]interface{})) { - ticker := time.NewTicker(t.Interval) - defer ticker.Stop() - for { select { case <-ctx.Done(): return case <-t.StopCh: return - case <-ticker.C: + default: // 检查是否超过最大运行时长 t.mu.RLock() if time.Since(t.StartTime) > t.MaxDuration { @@ -59,11 +56,21 @@ func (t *PingTask) Start(ctx context.Context, resultCallback func(result map[str } t.mu.RUnlock() - // 执行ping测试 + // 执行单个ping包测试(立即返回结果) result := t.executePing() if resultCallback != nil { resultCallback(result) } + + // 等待间隔时间后继续下一次测试 + select { + case <-ctx.Done(): + return + case <-t.StopCh: + return + case <-time.After(t.Interval): + // 继续下一次循环 + } } } } @@ -84,7 +91,8 @@ func (t *PingTask) UpdateLastRequest() { } func (t *PingTask) executePing() map[string]interface{} { - cmd := exec.Command("ping", "-c", "4", t.Target) + // 发送单个ping包(-c 1),每个包完成后立即返回结果 + cmd := exec.Command("ping", "-c", "1", t.Target) output, err := cmd.CombinedOutput() if err != nil { return map[string]interface{}{ @@ -96,7 +104,7 @@ func (t *PingTask) executePing() map[string]interface{} { } } - // 解析ping输出 + // 解析ping输出(单个包的结果) result := parsePingOutput(string(output)) result["timestamp"] = time.Now().Unix() return result @@ -113,7 +121,26 @@ func parsePingOutput(output string) map[string]interface{} { for _, line := range lines { line = strings.TrimSpace(line) - // 解析丢包率:4 packets transmitted, 4 received, 0% packet loss + // 解析单个ping包的响应时间:64 bytes from 8.8.8.8: icmp_seq=0 ttl=64 time=10.123 ms + if strings.Contains(line, "time=") && strings.Contains(line, "icmp_seq") { + // 提取time=后面的数值 + timeIndex := strings.Index(line, "time=") + if timeIndex != -1 { + timePart := line[timeIndex+5:] + spaceIndex := strings.Index(timePart, " ") + if spaceIndex != -1 { + timeStr := timePart[:spaceIndex] + if latency, err := strconv.ParseFloat(timeStr, 64); err == nil { + result["latency"] = latency + result["success"] = true + result["packet_loss"] = false + return result + } + } + } + } + + // 解析丢包率:1 packets transmitted, 1 received, 0% packet loss if strings.Contains(line, "packets transmitted") { parts := strings.Fields(line) for i, part := range parts { @@ -124,13 +151,14 @@ func parsePingOutput(output string) map[string]interface{} { result["packet_loss"] = loss > 0 if loss > 0 { result["success"] = false + result["latency"] = -1 } } } } } - // 解析延迟:rtt min/avg/max/mdev = 10.123/12.456/15.789/2.345 ms + // 解析延迟:rtt min/avg/max/mdev = 10.123/10.123/10.123/0.000 ms(单个包时min=avg=max) if strings.Contains(line, "min/avg/max") || strings.Contains(line, "rtt") { parts := strings.Fields(line) for _, part := range parts { diff --git a/internal/continuous/tcping.go b/internal/continuous/tcping.go index 31253ca..5b1e67f 100644 --- a/internal/continuous/tcping.go +++ b/internal/continuous/tcping.go @@ -57,16 +57,13 @@ func NewTCPingTask(taskID, target string, interval, maxDuration time.Duration) ( } func (t *TCPingTask) Start(ctx context.Context, resultCallback func(result map[string]interface{})) { - ticker := time.NewTicker(t.Interval) - defer ticker.Stop() - for { select { case <-ctx.Done(): return case <-t.StopCh: return - case <-ticker.C: + default: // 检查是否超过最大运行时长 t.mu.RLock() if time.Since(t.StartTime) > t.MaxDuration { @@ -76,11 +73,21 @@ func (t *TCPingTask) Start(ctx context.Context, resultCallback func(result map[s } t.mu.RUnlock() - // 执行tcping测试 + // 执行tcping测试(每次测试完成后立即返回结果) result := t.executeTCPing() if resultCallback != nil { resultCallback(result) } + + // 等待间隔时间后继续下一次测试 + select { + case <-ctx.Done(): + return + case <-t.StopCh: + return + case <-time.After(t.Interval): + // 继续下一次循环 + } } } } diff --git a/internal/handler/dns.go b/internal/handler/dns.go index 1ce621f..e35f5b0 100644 --- a/internal/handler/dns.go +++ b/internal/handler/dns.go @@ -49,6 +49,7 @@ func handleDns(c *gin.Context, url string, params map[string]interface{}) { "type": "ceDns", "requrl": hostname, "ips": []interface{}{}, + "cnames": []interface{}{}, } // 构建dig命令 @@ -77,6 +78,7 @@ func handleDns(c *gin.Context, url string, params map[string]interface{}) { lines := strings.Split(outputStr, "\n") inAnswerSection := false ipList := make([]map[string]interface{}, 0) + cnameList := make([]map[string]interface{}, 0) for _, line := range lines { line = strings.TrimSpace(line) @@ -97,18 +99,27 @@ func handleDns(c *gin.Context, url string, params map[string]interface{}) { recordValue := "" if len(parts) > 5 { recordValue = strings.Join(parts[5:], " ") - // 移除CNAME值末尾的点(如果有) + // 移除值末尾的点(如果有) recordValue = strings.TrimSuffix(recordValue, ".") } - // 处理A、AAAA和CNAME记录 - if recordClass == "A" || recordClass == "AAAA" || recordClass == "CNAME" { - recordItem := map[string]interface{}{ - "url": strings.TrimSuffix(parts[0], "."), // 移除域名末尾的点 + domain := strings.TrimSuffix(parts[0], ".") // 移除域名末尾的点 + + // 分别处理A/AAAA记录和CNAME记录 + if recordClass == "A" || recordClass == "AAAA" { + ipItem := map[string]interface{}{ + "url": domain, "type": recordClass, - "ip": recordValue, // CNAME记录中,ip字段存储的是CNAME值 + "ip": recordValue, } - ipList = append(ipList, recordItem) + ipList = append(ipList, ipItem) + } else if recordClass == "CNAME" { + cnameItem := map[string]interface{}{ + "url": domain, + "type": recordClass, + "cname": recordValue, // CNAME值 + } + cnameList = append(cnameList, cnameItem) } } } @@ -142,5 +153,6 @@ func handleDns(c *gin.Context, url string, params map[string]interface{}) { } result["ips"] = ipList + result["cnames"] = cnameList c.JSON(200, result) }