diff --git a/README.md b/README.md index a41c7cab..4fa60432 100644 --- a/README.md +++ b/README.md @@ -13,10 +13,10 @@ - [x] 邮件端口测试[自研[portchecker](https://github.com/oneclickvirt/portchecker)] - [x] 三网回程测试[借鉴[zhanghanyun/backtrace](https://github.com/zhanghanyun/backtrace)二次开发至于[oneclickvirt/backtrace](https://github.com/oneclickvirt/backtrace)] - [x] 三网路由测试[借鉴[NTrace-core](https://github.com/nxtrace/NTrace-core)二次开发至于[nt3](https://github.com/oneclickvirt/nt3)] +- [x] 测试网速[基于[speedtest.net-爬虫](https://github.com/spiritLHLS/speedtest.net-CN-ID)、[speedtest.cn-爬虫](https://github.com/spiritLHLS/speedtest.cn-CN-ID)的数据,借鉴[speedtest-go](https://github.com/showwin/speedtest-go)二次开发] ## TODO -- [ ] 测试网速[基于[speedtest.net-爬虫](https://github.com/spiritLHLS/speedtest.net-CN-ID)、[speedtest.cn-爬虫](https://github.com/spiritLHLS/speedtest.cn-CN-ID)的数据,借鉴[speedtest-go](https://github.com/showwin/speedtest-go)二次开发] - [ ] 测试三网Ping值[借鉴[ecsspeed](https://github.com/spiritLHLS/ecsspeed)的逻辑二次开发] ## 说明 diff --git a/go.mod b/go.mod index b3944a2e..5bc744ac 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/oneclickvirt/nt3 v0.0.1-20240627070009 github.com/oneclickvirt/portchecker v0.0.1-20240624155429 github.com/oneclickvirt/security v0.0.1-20240625075931 - github.com/showwin/speedtest-go v1.7.7 + github.com/oneclickvirt/speedtest v0.0.4-20240629100548 ) require ( @@ -70,6 +70,7 @@ require ( github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/schollz/progressbar/v3 v3.14.4 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/showwin/speedtest-go v1.7.7 // indirect github.com/smarty/assertions v1.16.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect diff --git a/go.sum b/go.sum index c73f7a9b..53433942 100644 --- a/go.sum +++ b/go.sum @@ -109,6 +109,10 @@ github.com/oneclickvirt/portchecker v0.0.1-20240624155429 h1:+wapaOcFrg1iWJDhBKT github.com/oneclickvirt/portchecker v0.0.1-20240624155429/go.mod h1:HQxSTrqM8/QFqHMTBZ7S8H9eEO5FkUXU1eb7ZX5Mk+k= github.com/oneclickvirt/security v0.0.1-20240625075931 h1:Vj1Wq/JVcqYpfqUWRtsITbz3zM4HxnLC0iPxxA6akP0= github.com/oneclickvirt/security v0.0.1-20240625075931/go.mod h1:6bjZjpYJ8M3aRIcLP61b0mjYRwvtWbYkvoGjS28Bdy4= +github.com/oneclickvirt/speedtest v0.0.3-20240629093211 h1:SU1aGYLpszp3csg599PjlrI/u32KNlHC/FiCx2ucn6w= +github.com/oneclickvirt/speedtest v0.0.3-20240629093211/go.mod h1:JNIxUbEJD12w81b7754RLHD55fsH6wHj+fCV2PqBDhk= +github.com/oneclickvirt/speedtest v0.0.4-20240629100548 h1:DQA0R/EdtmLJrQBb9JvQBaBpcMgiGDvIHq+0quNZQQM= +github.com/oneclickvirt/speedtest v0.0.4-20240629100548/go.mod h1:JNIxUbEJD12w81b7754RLHD55fsH6wHj+fCV2PqBDhk= github.com/onsi/ginkgo/v2 v2.16.0 h1:7q1w9frJDzninhXxjZd+Y/x54XNjG/UlRLIYPZafsPM= github.com/onsi/ginkgo/v2 v2.16.0/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= diff --git a/main.go b/main.go index 8b877ae9..71a93f38 100644 --- a/main.go +++ b/main.go @@ -12,6 +12,7 @@ import ( "github.com/oneclickvirt/ecs/network" "github.com/oneclickvirt/ecs/ntrace" "github.com/oneclickvirt/ecs/port" + "github.com/oneclickvirt/ecs/speedtest" "github.com/oneclickvirt/ecs/unlocktest" "runtime" "strings" @@ -37,6 +38,7 @@ func main() { diskTestMethod, diskTestPath string diskMultiCheck bool nt3CheckType, nt3Location string + spNum int width = 84 ) flag.BoolVar(&showVersion, "v", false, "Show version information") @@ -52,6 +54,7 @@ func main() { flag.StringVar(&nt3Location, "nt3loc", "GZ", "指定三网回程路由检测的地址,支持 GZ, SH, BJ, CD 对应 广州,上海,北京,成都") flag.StringVar(&nt3CheckType, "nt3t", "ipv4", "指定三网回程路由检测的类型,支持 both, ipv4, ipv6") } + flag.IntVar(&spNum, "spnum", 2, "Specify speedtest each operator servers num") flag.Parse() if showVersion { fmt.Println(ecsVersion) @@ -95,7 +98,13 @@ func main() { nt3CheckType = "ipv4" } ntrace.TraceRoute3(language, nt3Location, nt3CheckType) - //printCenteredTitle("就近节点测速", width) + printCenteredTitle("就近节点测速", width) + speedtest.ShowHead(language) + speedtest.NearbySP() + speedtest.CustomSP("net", "global", 4) + speedtest.CustomSP("net", "cu", spNum) + speedtest.CustomSP("net", "ct", spNum) + speedtest.CustomSP("net", "cmcc", spNum) printCenteredTitle("", width) endTime := time.Now() duration := endTime.Sub(startTime) @@ -127,7 +136,10 @@ func main() { printCenteredTitle("Email Port Check", width) port.EmailCheck() //printCenteredTitle("Return Path Routing", width) - //printCenteredTitle("Nearby Node Speed Test", width) + printCenteredTitle("Nearby Node Speed Test", width) + speedtest.ShowHead(language) + speedtest.NearbySP() + speedtest.CustomSP("net", "global", -1) printCenteredTitle("", width) endTime := time.Now() duration := endTime.Sub(startTime) diff --git a/speedtest/sp.go b/speedtest/sp.go index a576bd76..e2ff3e06 100644 --- a/speedtest/sp.go +++ b/speedtest/sp.go @@ -1,170 +1,57 @@ package speedtest import ( - "encoding/csv" - "fmt" - "github.com/imroc/req/v3" - "github.com/showwin/speedtest-go/speedtest" - "github.com/showwin/speedtest-go/speedtest/transport" - "io" - "log" - "sort" + "github.com/oneclickvirt/speedtest/model" + "github.com/oneclickvirt/speedtest/sp" "strings" - "time" ) -var ( - netCMCC = "https://raw.githubusercontent.com/spiritLHLS/speedtest.net-CN-ID/main/CN_Mobile.csv" - netCT = "https://raw.githubusercontent.com/spiritLHLS/speedtest.net-CN-ID/main/CN_Telecom.csv" - netCU = "https://raw.githubusercontent.com/spiritLHLS/speedtest.net-CN-ID/main/CN_Unicom.csv" - netHK = "https://raw.githubusercontent.com/spiritLHLS/speedtest.net-CN-ID/main/HK.csv" - netJP = "https://raw.githubusercontent.com/spiritLHLS/speedtest.net-CN-ID/main/JP.csv" - netTW = "https://raw.githubusercontent.com/spiritLHLS/speedtest.net-CN-ID/main/TW.csv" - netSG = "https://raw.githubusercontent.com/spiritLHLS/speedtest.net-CN-ID/main/SG.csv" - netGlobal = "https://raw.githubusercontent.com/spiritLHLS/speedtest.net-CN-ID/main/ls_sg_hk_jp.csv" - - cnCMCC = "https://raw.githubusercontent.com/spiritLHLS/speedtest.cn-CN-ID/main/mobile.csv" - cntCT = "https://raw.githubusercontent.com/spiritLHLS/speedtest.cn-CN-ID/main/telecom.csv" - cnCU = "https://raw.githubusercontent.com/spiritLHLS/speedtest.cn-CN-ID/main/unicom.csv" - cnHK = "https://raw.githubusercontent.com/spiritLHLS/speedtest.cn-CN-ID/main/HK.csv" - cnJP = "https://raw.githubusercontent.com/spiritLHLS/speedtest.cn-CN-ID/main/JP.csv" - cnTW = "https://raw.githubusercontent.com/spiritLHLS/speedtest.cn-CN-ID/main/TW.csv" - cnSG = "https://raw.githubusercontent.com/spiritLHLS/speedtest.cn-CN-ID/main/SG.csv" - - cdnList = []string{ - "http://cdn0.spiritlhl.top/", - "http://cdn1.spiritlhl.top/", - "http://cdn1.spiritlhl.net/", - "http://cdn3.spiritlhl.net/", - "http://cdn2.spiritlhl.net/", - } -) - -func checkError(err error) { - if err != nil { - log.Fatal(err) - } +func ShowHead(language string) { + sp.ShowHead(language) } -func NearbySpeedTest(language string) { - if language == "zh" { - fmt.Printf("%-12s\t %-11s\t %-11s\t %-11s\t %-12s\n", - "位置", "上传速度", "下载速度", "延迟", "丢包率") - } else if language == "en" { - fmt.Printf("%-12s\t %-11s\t %-11s\t %-11s\t %-12s\n", - "Location", "Upload Speed", "Download Speed", "Latency", "PacketLoss") - } - var speedtestClient = speedtest.New() - serverList, _ := speedtestClient.FetchServers() - targets, _ := serverList.FindServer([]int{}) - analyzer := speedtest.NewPacketLossAnalyzer(nil) - var LowestLatency time.Duration - var NearbyServer *speedtest.Server - var PacketLoss string - for _, server := range targets { - server.PingTest(nil) - if LowestLatency == 0 && NearbyServer == nil { - LowestLatency = server.Latency - NearbyServer = server - } else if server.Latency < LowestLatency && NearbyServer != nil { - NearbyServer = server +func NearbySP() { + sp.NearbySpeedTest() +} + +func CustomSP(platform, operator string, num int) { + var url, parseType string + if strings.ToLower(platform) == "cn" { + if strings.ToLower(operator) == "cmcc" { + url = model.CnCMCC + } else if strings.ToLower(operator) == "cu" { + url = model.CnCU + } else if strings.ToLower(operator) == "ct" { + url = model.CnCT + } else if strings.ToLower(operator) == "hk" { + url = model.CnHK + } else if strings.ToLower(operator) == "tw" { + url = model.CnTW + } else if strings.ToLower(operator) == "jp" { + url = model.CnJP + } else if strings.ToLower(operator) == "sg" { + url = model.CnSG } - server.Context.Reset() - } - if NearbyServer != nil { - NearbyServer.DownloadTest() - NearbyServer.UploadTest() - err := analyzer.Run(NearbyServer.Host, func(packetLoss *transport.PLoss) { - PacketLoss = strings.ReplaceAll(packetLoss.String(), "Packet Loss: ", "") - }) - checkError(err) - fmt.Printf("%-12s\t %-11s\t %-11s\t %-11s\t %-12s\n", - //NearbyServer.Name, - "Speedtest.net", - fmt.Sprintf("%.2f Mbps", NearbyServer.ULSpeed.Mbps()), - fmt.Sprintf("%.2f Mbps", NearbyServer.DLSpeed.Mbps()), - NearbyServer.Latency, - PacketLoss) - NearbyServer.Context.Reset() - } -} - -func getData(endpoint string) string { - client := req.C() - client.SetTimeout(10 * time.Second) - client.R(). - SetRetryCount(2). - SetRetryBackoffInterval(1*time.Second, 5*time.Second). - SetRetryFixedInterval(2 * time.Second) - for _, baseUrl := range cdnList { - url := baseUrl + endpoint - resp, err := client.R().Get(url) - if err == nil { - defer resp.Body.Close() - b, err := io.ReadAll(resp.Body) - if err == nil { - return string(b) - } - } else { - log.Println("Error accessing URL:", url, err) + parseType = "url" + } else if strings.ToLower(platform) == "net" { + if strings.ToLower(operator) == "cmcc" { + url = model.NetCMCC + } else if strings.ToLower(operator) == "cu" { + url = model.NetCU + } else if strings.ToLower(operator) == "ct" { + url = model.NetCT + } else if strings.ToLower(operator) == "hk" { + url = model.NetHK + } else if strings.ToLower(operator) == "tw" { + url = model.NetTW + } else if strings.ToLower(operator) == "jp" { + url = model.NetJP + } else if strings.ToLower(operator) == "sg" { + url = model.NetSG + } else if strings.ToLower(operator) == "global" { + url = model.NetGlobal } + parseType = "id" } - return "" -} - -func parseData(data string) speedtest.Servers { - var targets speedtest.Servers - reader := csv.NewReader(strings.NewReader(data)) - reader.Comma = ',' - records, err := reader.ReadAll() - if err != nil { - log.Fatal(err) - } - speedtestClient := speedtest.New() - for _, record := range records { - id := record[0] - serverPtr, errFetch := speedtestClient.FetchServerByID(id) - if errFetch != nil { - continue - } - serverPtr.Name = record[3] - targets = append(targets, serverPtr) - } - return targets -} - -func CustomSpeedTest(url string, num int) { - data := getData(url) - targets := parseData(data) - var pingList []time.Duration - var err error - serverMap := make(map[time.Duration]*speedtest.Server) - for _, server := range targets { - err = server.PingTest(nil) - checkError(err) - pingList = append(pingList, server.Latency) - serverMap[server.Latency] = server - server.Context.Reset() - } - sort.Slice(pingList, func(i, j int) bool { - return pingList[i] < pingList[j] - }) - analyzer := speedtest.NewPacketLossAnalyzer(nil) - var PacketLoss string - for i := 0; i < num && i < len(pingList); i++ { - server := serverMap[pingList[i]] - server.DownloadTest() - server.UploadTest() - err = analyzer.Run(server.Host, func(packetLoss *transport.PLoss) { - PacketLoss = strings.ReplaceAll(packetLoss.String(), "Packet Loss: ", "") - }) - checkError(err) - fmt.Printf("%-12s\t %-11s\t %-11s\t %-11s\t %-12s\n", - server.Name, - fmt.Sprintf("%.2f Mbps", server.ULSpeed.Mbps()), - fmt.Sprintf("%.2f Mbps", server.DLSpeed.Mbps()), - server.Latency, - PacketLoss) - server.Context.Reset() - } + sp.CustomSpeedTest(url, parseType, num) } diff --git a/speedtest/sp_test.go b/speedtest/sp_test.go index 55567d13..41151750 100644 --- a/speedtest/sp_test.go +++ b/speedtest/sp_test.go @@ -3,6 +3,6 @@ package speedtest import "testing" func Test(t *testing.T) { - //NearbySpeedTest("en") - CustomSpeedTest("https://raw.githubusercontent.com/spiritLHLS/speedtest.net-CN-ID/main/CN_Telecom.csv", 2) + ShowHead("en") + NearbySP() }