85 lines
1.5 KiB
Go
85 lines
1.5 KiB
Go
package handler
|
||
|
||
import (
|
||
"net"
|
||
"os/exec"
|
||
"sync"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
)
|
||
|
||
func handleFindPing(c *gin.Context, url string, params map[string]interface{}) {
|
||
// url应该是CIDR格式,如 8.8.8.0/24
|
||
cidr := url
|
||
if cidrParam, ok := params["cidr"].(string); ok && cidrParam != "" {
|
||
cidr = cidrParam
|
||
}
|
||
|
||
// 解析CIDR
|
||
_, ipNet, err := net.ParseCIDR(cidr)
|
||
if err != nil {
|
||
c.JSON(200, gin.H{
|
||
"type": "ceFindPing",
|
||
"error": "无效的CIDR格式",
|
||
})
|
||
return
|
||
}
|
||
|
||
// 生成IP列表
|
||
var ipList []string
|
||
for ip := ipNet.IP.Mask(ipNet.Mask); ipNet.Contains(ip); incIP(ip) {
|
||
ipList = append(ipList, ip.String())
|
||
}
|
||
|
||
// 移除网络地址和广播地址
|
||
if len(ipList) > 2 {
|
||
ipList = ipList[1 : len(ipList)-1]
|
||
}
|
||
|
||
// 并发ping测试
|
||
var wg sync.WaitGroup
|
||
var mu sync.Mutex
|
||
aliveIPs := make([]string, 0)
|
||
|
||
// 限制并发数
|
||
semaphore := make(chan struct{}, 50)
|
||
|
||
for _, ip := range ipList {
|
||
wg.Add(1)
|
||
semaphore <- struct{}{}
|
||
go func(ipAddr string) {
|
||
defer wg.Done()
|
||
defer func() { <-semaphore }()
|
||
|
||
// 执行ping(只ping一次,快速检测)
|
||
cmd := exec.Command("ping", "-c", "1", "-W", "1", ipAddr)
|
||
err := cmd.Run()
|
||
if err == nil {
|
||
mu.Lock()
|
||
aliveIPs = append(aliveIPs, ipAddr)
|
||
mu.Unlock()
|
||
}
|
||
}(ip)
|
||
}
|
||
|
||
wg.Wait()
|
||
|
||
c.JSON(200, gin.H{
|
||
"type": "ceFindPing",
|
||
"cidr": cidr,
|
||
"alive_ips": aliveIPs,
|
||
"alive_count": len(aliveIPs),
|
||
"total_ips": len(ipList),
|
||
})
|
||
}
|
||
|
||
func incIP(ip net.IP) {
|
||
for j := len(ip) - 1; j >= 0; j-- {
|
||
ip[j]++
|
||
if ip[j] > 0 {
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|