Files
CloudflareSpeedTest/task/tcping.go
xiu2 66912dd657 新增 支持显示地区码(机场三字码,仅限 Cloudflare、AWS CloudFront,HTTPing 和 下载测速(无论是哪个测速模式)过程中都会自动获取);
新增 调试模式运行参数(-debug 方便排查下载测速过程中遇到的问题);
新增 彩色输出内容;
调整 当没找到符合速度条件的 IP 时,默认不再直接忽略条件输出所有 IP 测速结果了,而是只有在调试模式下才会输出;
2025-06-29 00:30:05 +08:00

150 lines
3.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package task
import (
"fmt"
"net"
"sort"
"strconv"
"sync"
"time"
"github.com/XIU2/CloudflareSpeedTest/utils"
)
const (
tcpConnectTimeout = time.Second * 1
maxRoutine = 1000
defaultRoutines = 200
defaultPort = 443
defaultPingTimes = 4
)
var (
Routines = defaultRoutines
TCPPort int = defaultPort
PingTimes int = defaultPingTimes
)
type Ping struct {
wg *sync.WaitGroup
m *sync.Mutex
ips []*net.IPAddr
csv utils.PingDelaySet
control chan bool
bar *utils.Bar
}
func checkPingDefault() {
if Routines <= 0 {
Routines = defaultRoutines
}
if TCPPort <= 0 || TCPPort >= 65535 {
TCPPort = defaultPort
}
if PingTimes <= 0 {
PingTimes = defaultPingTimes
}
}
func NewPing() *Ping {
checkPingDefault()
ips := loadIPRanges()
return &Ping{
wg: &sync.WaitGroup{},
m: &sync.Mutex{},
ips: ips,
csv: make(utils.PingDelaySet, 0),
control: make(chan bool, Routines),
bar: utils.NewBar(len(ips), "可用:", ""),
}
}
func (p *Ping) Run() utils.PingDelaySet {
if len(p.ips) == 0 {
return p.csv
}
if Httping {
fmt.Printf("\033[34m开始延迟测速模式HTTP, 端口:%d, 范围:%v ~ %v ms, 丢包:%.2f)\033[0m\n", TCPPort, utils.InputMinDelay.Milliseconds(), utils.InputMaxDelay.Milliseconds(), utils.InputMaxLossRate)
} else {
fmt.Printf("\033[34m开始延迟测速模式TCP, 端口:%d, 范围:%v ~ %v ms, 丢包:%.2f)\033[0m\n", TCPPort, utils.InputMinDelay.Milliseconds(), utils.InputMaxDelay.Milliseconds(), utils.InputMaxLossRate)
}
for _, ip := range p.ips {
p.wg.Add(1)
p.control <- false
go p.start(ip)
}
p.wg.Wait()
p.bar.Done()
sort.Sort(p.csv)
return p.csv
}
func (p *Ping) start(ip *net.IPAddr) {
defer p.wg.Done()
p.tcpingHandler(ip)
<-p.control
}
// bool connectionSucceed float32 time
func (p *Ping) tcping(ip *net.IPAddr) (bool, time.Duration) {
startTime := time.Now()
var fullAddress string
if isIPv4(ip.String()) {
fullAddress = fmt.Sprintf("%s:%d", ip.String(), TCPPort)
} else {
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
func (p *Ping) checkConnection(ip *net.IPAddr) (recv int, totalDelay time.Duration, colo string) {
if Httping {
recv, totalDelay, colo = p.httping(ip)
return
}
colo = "" // TCPing 不获取 colo
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,
})
}
// handle tcping
func (p *Ping) tcpingHandler(ip *net.IPAddr) {
recv, totalDlay, colo := p.checkConnection(ip)
nowAble := len(p.csv)
if recv != 0 {
nowAble++
}
p.bar.Grow(1, strconv.Itoa(nowAble))
if recv == 0 {
return
}
data := &utils.PingData{
IP: ip,
Sended: PingTimes,
Received: recv,
Delay: totalDlay / time.Duration(recv),
Colo: colo,
}
p.appendIPData(data)
}