Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

增加Httping和机场三字码筛选功能 #282

Merged
merged 1 commit into from
Jan 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,11 @@ https://github.com/XIU2/CloudflareSpeedTest

参数:
-n 200
测速线程数量;越多测速越快,性能弱的设备 (如路由器) 请勿太高;(默认 200 最多 1000 )
测速线程数量;越多测速越快,性能弱的设备 (如路由器) 请勿太高;(默认 200 最多 1000)
-t 4
延迟测速次数;单个 IP 延迟测速次数,为 1 时将过滤丢包的IP,TCP协议;(默认 4 次)
延迟测速次数;单个 IP 延迟测速次数,为 1 时将过滤丢包的IP;(默认 4 次)
-tp 443
指定测速端口;延迟测速/下载测速时使用的端口;(默认 443 端口)
指定测速端口;延迟测速/下载测速时使用的端口;(默认 443 端口,httping模式下该参数无效)

-dn 10
下载测速数量;延迟测速并排序后,从最低延迟起下载测速的数量;(默认 10 个)
Expand Down Expand Up @@ -154,8 +154,16 @@ https://github.com/XIU2/CloudflareSpeedTest
-allip
测速全部的IP;对 IP 段中的每个 IP (仅支持 IPv4) 进行测速;(默认 每个 IP 段随机测速一个 IP)

-Httping
启用HTTP ping;启用后会将tcping换成httping模式;(默认 不启用)
-HttpingColo DFW,LAX,SEA,SJC,FRA,MAD
匹配机场三字码;需要匹配多个请使用英文逗号分割;(默认 匹配全部机场码,需要启用HTTP ping)
目前已知区域:KIX,HKG,SIN,NRT,ICN,DFW,LAX,SEA,SJC,FRA,MAD
目前已知大概率能扫描到美/法区域
-HttpingTimeout 2000
指定httping超时时间;httping超时毫秒;(默认 2000 ms,需要启用HTTP ping)
-v
打印程序版本+检查版本更新
打印程序版本 + 检查版本更新
-h
打印帮助说明
```
Expand Down
17 changes: 15 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ https://github.com/XIU2/CloudflareSpeedTest
-n 200
测速线程数量;越多测速越快,性能弱的设备 (如路由器) 请勿太高;(默认 200 最多 1000)
-t 4
延迟测速次数;单个 IP 延迟测速次数,为 1 时将过滤丢包的IP,TCP协议;(默认 4 次)
延迟测速次数;单个 IP 延迟测速次数,为 1 时将过滤丢包的IP;(默认 4 次)
-tp 443
指定测速端口;延迟测速/下载测速时使用的端口;(默认 443 端口)
指定测速端口;延迟测速/下载测速时使用的端口;(默认 443 端口,httping模式下该参数无效)

-dn 10
下载测速数量;延迟测速并排序后,从最低延迟起下载测速的数量;(默认 10 个)
Expand Down Expand Up @@ -58,6 +58,14 @@ https://github.com/XIU2/CloudflareSpeedTest
-allip
测速全部的IP;对 IP 段中的每个 IP (仅支持 IPv4) 进行测速;(默认 每个 IP 段随机测速一个 IP)

-Httping
启用HTTP ping;启用后会将tcping换成httping模式;(默认 不启用)
-HttpingColo DFW,LAX,SEA,SJC,FRA,MAD
匹配机场三字码;需要匹配多个请使用英文逗号分割;(默认 匹配全部机场码,需要启用HTTP ping)
目前已知区域:KIX,HKG,SIN,NRT,ICN,DFW,LAX,SEA,SJC,FRA,MAD
目前已知大概率能扫描到美/法区域
-HttpingTimeout 2000
指定httping超时时间;httping超时毫秒;(默认 2000 ms,需要启用HTTP ping)
-v
打印程序版本 + 检查版本更新
-h
Expand All @@ -79,6 +87,9 @@ https://github.com/XIU2/CloudflareSpeedTest
flag.BoolVar(&task.Disable, "dd", false, "禁用下载测速")
flag.BoolVar(&task.TestAll, "allip", false, "测速全部 IP")
flag.BoolVar(&printVersion, "v", false, "打印程序版本")
flag.BoolVar(&task.Httping, "Httping", false, "启用HTTP ping")
flag.StringVar(&task.HttpingColo, "HttpingColo", "", "匹配机场三字码")
flag.IntVar(&task.HttpingTimeout, "HttpingTimeout", 2000, "指定httping超时时间")
flag.Usage = func() { fmt.Print(help) }
flag.Parse()

Expand All @@ -88,6 +99,8 @@ https://github.com/XIU2/CloudflareSpeedTest
utils.InputMaxDelay = time.Duration(maxDelay) * time.Millisecond
utils.InputMinDelay = time.Duration(minDelay) * time.Millisecond
task.Timeout = time.Duration(downloadTime) * time.Second
task.HttpingColomap = task.MapColoMap()
task.HttpingRequest = task.GetRequest()

if printVersion {
println(version)
Expand Down
4 changes: 2 additions & 2 deletions task/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,13 @@ func TestDownloadSpeed(ipSet utils.PingDelaySet) (speedSet utils.DownloadSpeedSe
}

fmt.Printf("开始下载测速(下载速度下限:%.2f MB/s,下载测速数量:%d,下载测速队列:%d):\n", MinSpeed, TestCount, testNum)
bar := utils.NewBar(TestCount)
bar := utils.NewBar(TestCount, "", "")
for i := 0; i < testNum; i++ {
speed := downloadHandler(ipSet[i].IP)
ipSet[i].DownloadSpeed = speed
// 在每个 IP 下载测速后,以 [下载速度下限] 条件过滤结果
if speed >= MinSpeed*1024*1024 {
bar.Grow(1)
bar.Grow(1, "")
speedSet = append(speedSet, ipSet[i]) // 高于下载速度下限时,添加到新数组中
if len(speedSet) == TestCount { // 凑够满足条件的 IP 时(下载测速数量 -dn),就跳出循环
break
Expand Down
140 changes: 140 additions & 0 deletions task/httping.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package task

import (
"crypto/tls"
"fmt"
"io"
"log"
"net"
"net/http"
"strings"
"sync"
"time"

"CloudflareSpeedTest/utils"
)

var (
Httping bool //是否启用httping
HttpingTimeout int //设置超时时间,单位毫秒
HttpingColo string //有值代表筛选机场三字码区域
)

var (
HttpingColomap *sync.Map
HttpingRequest *http.Request
)

// pingReceived pingTotalTime
func (p *Ping) httping(ip *net.IPAddr) (int, time.Duration) {
var fullAddress string
if isIPv4(ip.String()) {
fullAddress = fmt.Sprintf("%s", ip.String())
} else {
fullAddress = fmt.Sprintf("[%s]", ip.String())
}
hc := http.Client{
Timeout: time.Duration(HttpingTimeout) * time.Millisecond,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
} // #nosec

traceURL := fmt.Sprintf("http://%s/cdn-cgi/trace",
fullAddress)

// for connect and get colo
{
requ, err := http.NewRequest(http.MethodHead, traceURL, nil)
if err != nil {
return 0, 0
}
requ.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36")
resp, err := hc.Do(requ)
if err != nil {
return 0, 0
}
defer resp.Body.Close()
io.Copy(io.Discard, resp.Body)

cfRay := resp.Header.Get("CF-RAY")

colo := p.getColo(cfRay)
if colo == "" {
return 0, 0
}

}

// for test delay
success := 0
var delay time.Duration
for i := 0; i < PingTimes; i++ {
requ, err := http.NewRequest(http.MethodHead, traceURL, nil)
if err != nil {
log.Fatal("意外的错误,情报告:", err)
return 0, 0
}
requ.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36")
if i == PingTimes-1 {
requ.Header.Set("Connection", "close")
}
startTime := time.Now()
resp, err := hc.Do(requ)
if err != nil {
continue
}
success++
io.Copy(io.Discard, resp.Body)
_ = resp.Body.Close()
duration := time.Since(startTime)
delay += duration

}

return success, delay

}

func MapColoMap() *sync.Map {
if HttpingColo == "" {
return nil
}

colos := strings.Split(HttpingColo, ",")
colomap := &sync.Map{}
for _, colo := range colos {
colomap.Store(colo, colo)
}
return colomap
}

func GetRequest() *http.Request {
req, err := http.NewRequest("GET", URL, nil)
if err != nil {
log.Fatal(err)
}
return req
}

func (p *Ping) getColo(b string) string {
if b == "" {
return ""
}
idColo := strings.Split(b, "-")

out := idColo[1]

utils.ColoAble.Store(out, out)

if HttpingColomap == nil {
return out
}

_, ok := HttpingColomap.Load(out)
if ok {
return out
}

return ""
}
23 changes: 18 additions & 5 deletions task/tcping.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"net"
"sort"
"strconv"
"sync"
"time"

Expand Down Expand Up @@ -54,15 +55,19 @@ func NewPing() *Ping {
ips: ips,
csv: make(utils.PingDelaySet, 0),
control: make(chan bool, Routines),
bar: utils.NewBar(len(ips)),
bar: utils.NewBar(len(ips), "可用IP:", ""),
}
}

func (p *Ping) Run() utils.PingDelaySet {
if len(p.ips) == 0 {
return p.csv
}
fmt.Printf("开始延迟测速(模式:TCP,端口:%d,平均延迟上限:%v ms,平均延迟下限:%v ms)\n", TCPPort, utils.InputMaxDelay.Milliseconds(), utils.InputMinDelay.Milliseconds())
if Httping {
fmt.Printf("开始延迟测速(模式:HTTP,端口:80,平均延迟上限:%v ms,平均延迟下限:%v ms)\n", utils.InputMaxDelay.Milliseconds(), utils.InputMinDelay.Milliseconds())
} else {
fmt.Printf("开始延迟测速(模式:TCP,端口:%d,平均延迟上限:%v ms,平均延迟下限:%v ms)\n", TCPPort, utils.InputMaxDelay.Milliseconds(), utils.InputMinDelay.Milliseconds())
}
for _, ip := range p.ips {
p.wg.Add(1)
p.control <- false
Expand All @@ -80,7 +85,7 @@ func (p *Ping) start(ip *net.IPAddr) {
<-p.control
}

//bool connectionSucceed float32 time
// bool connectionSucceed float32 time
func (p *Ping) tcping(ip *net.IPAddr) (bool, time.Duration) {
startTime := time.Now()
var fullAddress string
Expand All @@ -98,8 +103,12 @@ func (p *Ping) tcping(ip *net.IPAddr) (bool, time.Duration) {
return true, duration
}

//pingReceived pingTotalTime
// pingReceived pingTotalTime
func (p *Ping) checkConnection(ip *net.IPAddr) (recv int, totalDelay time.Duration) {
if Httping {
recv, totalDelay = p.httping(ip)
return
}
for i := 0; i < PingTimes; i++ {
if ok, delay := p.tcping(ip); ok {
recv++
Expand All @@ -120,7 +129,11 @@ func (p *Ping) appendIPData(data *utils.PingData) {
// handle tcping
func (p *Ping) tcpingHandler(ip *net.IPAddr) {
recv, totalDlay := p.checkConnection(ip)
p.bar.Grow(1)
nowAble := len(p.csv)
if recv != 0 {
nowAble++
}
p.bar.Grow(1, strconv.Itoa(nowAble))
if recv == 0 {
return
}
Expand Down
14 changes: 14 additions & 0 deletions utils/csv.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import (
"log"
"net"
"os"
"sort"
"strconv"
"strings"
"sync"
"time"
)

Expand All @@ -21,6 +24,7 @@ var (
InputMinDelay = minDelay
Output = defaultOutput
PrintNum = 10
ColoAble sync.Map
)

// 是否打印测试结果
Expand Down Expand Up @@ -139,6 +143,16 @@ func (s DownloadSpeedSet) Swap(i, j int) {
}

func (s DownloadSpeedSet) Print() {
var colos []string
ColoAble.Range(func(key, value interface{}) bool {
colos = append(colos, key.(string))
return true
})
if len(colos) != 0 {
sort.Strings(colos)
colostrings := strings.Join(colos, ",")
fmt.Println("\n下次可以考虑机场三字码参数:" + colostrings + "\n")
}
if NoPrintResult() {
return
}
Expand Down
18 changes: 12 additions & 6 deletions utils/progress.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
package utils

import "github.com/cheggaaa/pb/v3"
import (
"fmt"

"github.com/cheggaaa/pb/v3"
)

type Bar struct {
pb *pb.ProgressBar
}

func NewBar(count int) *Bar {
return &Bar{pb.Simple.Start(count)}
func NewBar(count int, MyStrStart, MyStrEnd string) *Bar {
tmpl := fmt.Sprintf(`{{counters . }}{{ bar . "[" "-" (cycle . "↖" "↗" "↘" "↙" ) "_" "]"}} %s {{string . "MyStr" | green}} %s `, MyStrStart, MyStrEnd)
bar := pb.ProgressBarTemplate(tmpl).Start(count)
return &Bar{pb: bar}
}

func (b *Bar) Grow(num int) {
b.pb.Add(num)
func (b *Bar) Grow(num int, MyStrVal string) {
b.pb.Set("MyStr", MyStrVal).Add(num)
}

func (b *Bar) Done() {
b.pb.Finish()
}
}