CloudflareSpeedTest/task/tcping.go

148 lines
3.0 KiB
Go
Raw Permalink Normal View History

2021-11-10 12:25:10 +08:00
package task
import (
"fmt"
"net"
2021-11-10 17:12:12 +08:00
"sort"
"strconv"
2021-11-10 12:25:10 +08:00
"sync"
"time"
"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),
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
}
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)
} 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)
}
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
}
// 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()
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
}
// pingReceived pingTotalTime
2021-11-10 18:47:21 +08:00
func (p *Ping) checkConnection(ip *net.IPAddr) (recv int, totalDelay time.Duration) {
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)
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)
}