2021-11-10 12:25:10 +08:00
|
|
|
|
package task
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"net"
|
2021-11-10 17:12:12 +08:00
|
|
|
|
"sort"
|
2023-01-31 12:48:28 +08:00
|
|
|
|
"strconv"
|
2021-11-10 12:25:10 +08:00
|
|
|
|
"sync"
|
|
|
|
|
"time"
|
|
|
|
|
|
2023-03-27 11:49:59 +08:00
|
|
|
|
"github.com/XIU2/CloudflareSpeedTest/utils"
|
2021-11-10 12:25:10 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
tcpConnectTimeout = time.Second * 1
|
|
|
|
|
maxRoutine = 1000
|
2021-11-10 17:12:12 +08:00
|
|
|
|
defaultRoutines = 200
|
|
|
|
|
defaultPort = 443
|
|
|
|
|
defaultPingTimes = 4
|
2021-11-10 12:25:10 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var (
|
2021-11-10 17:12:12 +08:00
|
|
|
|
Routines = defaultRoutines
|
|
|
|
|
TCPPort int = defaultPort
|
|
|
|
|
PingTimes int = defaultPingTimes
|
2021-11-10 12:25:10 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Ping struct {
|
|
|
|
|
wg *sync.WaitGroup
|
|
|
|
|
m *sync.Mutex
|
2021-11-10 18:47:21 +08:00
|
|
|
|
ips []*net.IPAddr
|
2021-11-10 12:25:10 +08:00
|
|
|
|
csv utils.PingDelaySet
|
|
|
|
|
control chan bool
|
|
|
|
|
bar *utils.Bar
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-10 17:12:12 +08:00
|
|
|
|
func checkPingDefault() {
|
|
|
|
|
if Routines <= 0 {
|
|
|
|
|
Routines = defaultRoutines
|
|
|
|
|
}
|
|
|
|
|
if TCPPort <= 0 || TCPPort >= 65535 {
|
|
|
|
|
TCPPort = defaultPort
|
|
|
|
|
}
|
|
|
|
|
if PingTimes <= 0 {
|
|
|
|
|
PingTimes = defaultPingTimes
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-10 23:58:40 +08:00
|
|
|
|
func NewPing() *Ping {
|
2021-11-10 17:12:12 +08:00
|
|
|
|
checkPingDefault()
|
2021-11-10 23:58:40 +08:00
|
|
|
|
ips := loadIPRanges()
|
2021-11-10 12:25:10 +08:00
|
|
|
|
return &Ping{
|
|
|
|
|
wg: &sync.WaitGroup{},
|
|
|
|
|
m: &sync.Mutex{},
|
|
|
|
|
ips: ips,
|
|
|
|
|
csv: make(utils.PingDelaySet, 0),
|
2021-11-10 17:12:12 +08:00
|
|
|
|
control: make(chan bool, Routines),
|
2023-01-31 20:11:13 +08:00
|
|
|
|
bar: utils.NewBar(len(ips), "可用:", ""),
|
2021-11-10 12:25:10 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Ping) Run() utils.PingDelaySet {
|
2021-11-12 11:58:21 +08:00
|
|
|
|
if len(p.ips) == 0 {
|
|
|
|
|
return p.csv
|
|
|
|
|
}
|
2023-01-31 12:48:28 +08:00
|
|
|
|
if Httping {
|
2023-11-25 15:18:18 +08:00
|
|
|
|
fmt.Printf("开始延迟测速(模式:HTTP, 端口:%d, 范围:%v ~ %v ms, 丢包:%.2f)\n", TCPPort, utils.InputMinDelay.Milliseconds(), utils.InputMaxDelay.Milliseconds(), utils.InputMaxLossRate)
|
2023-01-31 12:48:28 +08:00
|
|
|
|
} else {
|
2023-11-25 15:18:18 +08:00
|
|
|
|
fmt.Printf("开始延迟测速(模式:TCP, 端口:%d, 范围:%v ~ %v ms, 丢包:%.2f)\n", TCPPort, utils.InputMinDelay.Milliseconds(), utils.InputMaxDelay.Milliseconds(), utils.InputMaxLossRate)
|
2023-01-31 12:48:28 +08:00
|
|
|
|
}
|
2021-11-10 12:25:10 +08:00
|
|
|
|
for _, ip := range p.ips {
|
|
|
|
|
p.wg.Add(1)
|
|
|
|
|
p.control <- false
|
|
|
|
|
go p.start(ip)
|
|
|
|
|
}
|
|
|
|
|
p.wg.Wait()
|
|
|
|
|
p.bar.Done()
|
2021-11-10 17:12:12 +08:00
|
|
|
|
sort.Sort(p.csv)
|
2021-11-10 12:25:10 +08:00
|
|
|
|
return p.csv
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-10 18:47:21 +08:00
|
|
|
|
func (p *Ping) start(ip *net.IPAddr) {
|
2021-11-10 12:25:10 +08:00
|
|
|
|
defer p.wg.Done()
|
|
|
|
|
p.tcpingHandler(ip)
|
|
|
|
|
<-p.control
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-31 12:48:28 +08:00
|
|
|
|
// bool connectionSucceed float32 time
|
2021-11-10 18:47:21 +08:00
|
|
|
|
func (p *Ping) tcping(ip *net.IPAddr) (bool, time.Duration) {
|
2021-11-10 12:25:10 +08:00
|
|
|
|
startTime := time.Now()
|
2022-11-08 15:47:19 +08:00
|
|
|
|
var fullAddress string
|
|
|
|
|
if isIPv4(ip.String()) {
|
|
|
|
|
fullAddress = fmt.Sprintf("%s:%d", ip.String(), TCPPort)
|
|
|
|
|
} else {
|
2021-11-10 12:25:10 +08:00
|
|
|
|
fullAddress = fmt.Sprintf("[%s]:%d", ip.String(), TCPPort)
|
|
|
|
|
}
|
|
|
|
|
conn, err := net.DialTimeout("tcp", fullAddress, tcpConnectTimeout)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return false, 0
|
|
|
|
|
}
|
|
|
|
|
defer conn.Close()
|
|
|
|
|
duration := time.Since(startTime)
|
|
|
|
|
return true, duration
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-31 12:48:28 +08:00
|
|
|
|
// pingReceived pingTotalTime
|
2021-11-10 18:47:21 +08:00
|
|
|
|
func (p *Ping) checkConnection(ip *net.IPAddr) (recv int, totalDelay time.Duration) {
|
2023-01-31 12:48:28 +08:00
|
|
|
|
if Httping {
|
|
|
|
|
recv, totalDelay = p.httping(ip)
|
|
|
|
|
return
|
|
|
|
|
}
|
2021-11-10 12:25:10 +08:00
|
|
|
|
for i := 0; i < PingTimes; i++ {
|
|
|
|
|
if ok, delay := p.tcping(ip); ok {
|
|
|
|
|
recv++
|
|
|
|
|
totalDelay += delay
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Ping) appendIPData(data *utils.PingData) {
|
|
|
|
|
p.m.Lock()
|
|
|
|
|
defer p.m.Unlock()
|
|
|
|
|
p.csv = append(p.csv, utils.CloudflareIPData{
|
|
|
|
|
PingData: data,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-14 14:10:44 +08:00
|
|
|
|
// handle tcping
|
2021-11-10 18:47:21 +08:00
|
|
|
|
func (p *Ping) tcpingHandler(ip *net.IPAddr) {
|
2021-11-14 14:10:44 +08:00
|
|
|
|
recv, totalDlay := p.checkConnection(ip)
|
2023-01-31 12:48:28 +08:00
|
|
|
|
nowAble := len(p.csv)
|
|
|
|
|
if recv != 0 {
|
|
|
|
|
nowAble++
|
|
|
|
|
}
|
|
|
|
|
p.bar.Grow(1, strconv.Itoa(nowAble))
|
2021-11-14 14:10:44 +08:00
|
|
|
|
if recv == 0 {
|
2021-11-10 12:25:10 +08:00
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
data := &utils.PingData{
|
|
|
|
|
IP: ip,
|
2021-11-10 17:12:12 +08:00
|
|
|
|
Sended: PingTimes,
|
2021-11-14 14:10:44 +08:00
|
|
|
|
Received: recv,
|
|
|
|
|
Delay: totalDlay / time.Duration(recv),
|
2021-11-10 12:25:10 +08:00
|
|
|
|
}
|
|
|
|
|
p.appendIPData(data)
|
|
|
|
|
}
|