diff --git a/IPRangeLoader.go b/IPRangeLoader.go index 9b6c725..8d8e1ea 100644 --- a/IPRangeLoader.go +++ b/IPRangeLoader.go @@ -21,17 +21,83 @@ func loadFirstIPOfRangeFromFile(ipFile string) []net.IPAddr { if err != nil { log.Fatal(err) } - for IPRange.Contains(firstIP) { - randipEndWith() // 随机 IP 的最后一段 - firstIP[15] = ipEndWith - firstIPCopy := make([]byte, len(firstIP)) - copy(firstIPCopy, firstIP) - firstIPs = append(firstIPs, net.IPAddr{IP: firstIPCopy}) - firstIP[14]++ - if firstIP[14] == 0 { - firstIP[13]++ - if firstIP[13] == 0 { - firstIP[12]++ + if ipv6Mode { // IPv6 + var tempIP uint8 + for IPRange.Contains(firstIP) { + //fmt.Println(firstIP) + //fmt.Println(firstIP[0], firstIP[1], firstIP[2], firstIP[3], firstIP[4], firstIP[5], firstIP[6], firstIP[7], firstIP[8], firstIP[9], firstIP[10], firstIP[11], firstIP[12], firstIP[13], firstIP[14], firstIP[15]) + firstIP[15] = randipEndWith() // 随机 IP 的最后一段 + firstIP[14] = randipEndWith() // 随机 IP 的最后一段 + firstIPCopy := make([]byte, len(firstIP)) + copy(firstIPCopy, firstIP) + firstIPs = append(firstIPs, net.IPAddr{IP: firstIPCopy}) + tempIP = firstIP[13] + firstIP[13] += randipEndWith() + if firstIP[13] < tempIP { + tempIP = firstIP[12] + firstIP[12] += randipEndWith() + if firstIP[12] < tempIP { + tempIP = firstIP[11] + firstIP[11] += randipEndWith() + if firstIP[11] < tempIP { + tempIP = firstIP[10] + firstIP[10] += randipEndWith() + if firstIP[10] < tempIP { + tempIP = firstIP[9] + firstIP[9] += randipEndWith() + if firstIP[9] < tempIP { + tempIP = firstIP[8] + firstIP[8] += randipEndWith() + if firstIP[8] < tempIP { + tempIP = firstIP[7] + firstIP[7] += randipEndWith() + if firstIP[7] < tempIP { + tempIP = firstIP[6] + firstIP[6] += randipEndWith() + if firstIP[6] < tempIP { + tempIP = firstIP[5] + firstIP[5] += randipEndWith() + if firstIP[5] < tempIP { + tempIP = firstIP[4] + firstIP[4] += randipEndWith() + if firstIP[4] < tempIP { + tempIP = firstIP[3] + firstIP[3] += randipEndWith() + if firstIP[3] < tempIP { + tempIP = firstIP[2] + firstIP[2] += randipEndWith() + if firstIP[2] < tempIP { + tempIP = firstIP[1] + firstIP[1] += randipEndWith() + if firstIP[1] < tempIP { + tempIP = firstIP[0] + firstIP[0] += randipEndWith() + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } else { //IPv4 + for IPRange.Contains(firstIP) { + firstIP[15] = randipEndWith() // 随机 IP 的最后一段 0.0.0.X + firstIPCopy := make([]byte, len(firstIP)) + copy(firstIPCopy, firstIP) + firstIPs = append(firstIPs, net.IPAddr{IP: firstIPCopy}) + firstIP[14]++ // 0.0.(X+1).X + if firstIP[14] == 0 { + firstIP[13]++ // 0.(X+1).X.X + if firstIP[13] == 0 { + firstIP[12]++ // (X+1).X.X.X + } } } } diff --git a/README.md b/README.md index cb1d255..2284d2e 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,8 @@ https://github.com/XIU2/CloudflareSpeedTest 输出结果文件;如含有空格请加上引号;为空格时不输出结果文件(-o " ");允许其他后缀;(默认 result.csv) -dd 禁用下载测速;如果带上该参数就是禁用下载测速;(默认 启用) + -ipv6 + IPv6 测速模式;请确保 IP 数据文件内只包含 IPv6 IP段,软件不支持同时测速 IPv4+IPv6;(默认 IPv4) -v 打印程序版本 -h @@ -107,16 +109,19 @@ https://github.com/XIU2/CloudflareSpeedTest # 注意:各参数均有默认值,只有不使用默认值时,才需要手动指定参数的值(按需选择),参数不分前后顺序。 # 提示: Linux 系统只需要把下面命令中的 CloudflareST.exe 改为 ./CloudflareST 即可。 -# 指定 IP数据文件,不显示结果直接退出(-p 值为 0) +# 指定 IPv4 数据文件,不显示结果直接退出(-p 值为 0) CloudflareST.exe -p 0 -f ip.txt -dd -# 指定 IP数据文件,不输出结果到文件,直接显示结果(-p 值为 10 条) +# 指定 IPv6 数据文件( ipv6.txt ),不显示结果直接退出(-p 值为 0) +CloudflareST.exe -p 0 -f ipv6.txt -dd -ipv6 + +# 指定 IPv4 数据文件,不输出结果到文件,直接显示结果(-p 值为 10 条) CloudflareST.exe -p 10 -f ip.txt -o " " -dd -# 指定 IP数据文件 及 输出结果到文件(相对路径,即当前目录下,如果包含空格请加上引号) +# 指定 IPv4 数据文件 及 输出结果到文件(相对路径,即当前目录下,如果包含空格请加上引号) CloudflareST.exe -f ip.txt -o result.csv -dd -# 指定 IP数据文件 及 输出结果到文件(绝对路径,即 C:\abc\ 目录下,如果包含空格请加上引号) +# 指定 IPv4 数据文件 及 输出结果到文件(绝对路径,即 C:\abc\ 目录下,如果包含空格请加上引号) CloudflareST.exe -f C:\abc\ip.txt -o C:\abc\result.csv -dd # 指定下载测速地址(要求:可以直接下载、文件大小超过 200MB、用的是 Cloudflare CDN),如果包含空格请加上引号 diff --git a/main.go b/main.go index 7ba0a72..3477eb9 100644 --- a/main.go +++ b/main.go @@ -15,6 +15,7 @@ import ( var version string var disableDownload bool +var ipv6Mode bool var tcpPort int var ipFile string var outputFile string @@ -54,7 +55,9 @@ https://github.com/XIU2/CloudflareSpeedTest -o result.csv 输出结果文件;如含有空格请加上引号;为空格时不输出结果文件(-o " ");允许其他后缀;(默认 result.csv) -dd - 禁用下载测速;如果带上该参数就是禁用下载测速;(默认 启用) + 禁用下载测速;如果带上该参数就是禁用下载测速;(默认 启用下载测速) + -ipv6 + IPv6 测速模式;请确保 IP 数据文件内只包含 IPv6 IP段,软件不支持同时测速 IPv4+IPv6;(默认 IPv4) -v 打印程序版本 -h @@ -70,6 +73,7 @@ https://github.com/XIU2/CloudflareSpeedTest flag.IntVar(&speedLimit, "sl", 0, "下载速度下限") flag.IntVar(&printResultNum, "p", 20, "显示结果数量") flag.BoolVar(&disableDownload, "dd", false, "禁用下载测速") + flag.BoolVar(&ipv6Mode, "ipv6", false, "禁用下载测速") flag.StringVar(&ipFile, "f", "ip.txt", "IP 数据文件") flag.StringVar(&outputFile, "o", "result.csv", "输出结果文件") flag.BoolVar(&printVersion, "v", false, "打印程序版本") @@ -129,7 +133,11 @@ func main() { var data_2 = make([]CloudflareIPData, 0) fmt.Println("# XIU2/CloudflareSpeedTest " + version + "\n") - fmt.Println("开始延迟测速(模式:TCP,端口:" + strconv.Itoa(tcpPort) + "):") + if ipv6Mode { + fmt.Println("开始延迟测速(模式:TCP IPv6,端口:" + strconv.Itoa(tcpPort) + "):") + } else { + fmt.Println("开始延迟测速(模式:TCP IPv4,端口:" + strconv.Itoa(tcpPort) + "):") + } control := make(chan bool, pingRoutine) for _, ip := range ips { wg.Add(1) @@ -148,7 +156,6 @@ func main() { if len(data) < downloadTestCount { // 如果IP数组长度(IP数量) 小于 下载测速次数,则次数改为IP数 //fmt.Println("\n[信息] IP 数量小于下载测速次数(" + strconv.Itoa(downloadTestCount) + " < " + strconv.Itoa(len(data)) + "),下载测速次数改为IP数。\n") downloadTestCount = len(data) - } var downloadTestCount_2 int // 临时的下载测速次数 if timeLimit == 9999 && speedLimit == 0 { @@ -201,9 +208,16 @@ func printResult(data []CloudflareIPData) { //fmt.Println("\n[信息] IP 数量小于显示结果数量(" + strconv.Itoa(printResultNum) + " < " + strconv.Itoa(len(dateString)) + "),显示结果数量改为IP数量。\n") printResultNum = len(dateString) } - fmt.Printf("%-16s%-5s%-5s%-5s%-6s%-11s\n", "IP 地址", "已发送", "已接收", "丢包率", "平均延迟", "下载速度 (MB/s)") - for i := 0; i < printResultNum; i++ { - fmt.Printf("%-18s%-8s%-8s%-8s%-10s%-15s\n", ipPadding(dateString[i][0]), dateString[i][1], dateString[i][2], dateString[i][3], dateString[i][4], dateString[i][5]) + if ipv6Mode { // IPv6 太长了,所以需要调整一下间隔 + fmt.Printf("%-40s%-5s%-5s%-5s%-6s%-11s\n", "IP 地址", "已发送", "已接收", "丢包率", "平均延迟", "下载速度 (MB/s)") + for i := 0; i < printResultNum; i++ { + fmt.Printf("%-42s%-8s%-8s%-8s%-10s%-15s\n", ipPadding(dateString[i][0]), dateString[i][1], dateString[i][2], dateString[i][3], dateString[i][4], dateString[i][5]) + } + } else { + fmt.Printf("%-16s%-5s%-5s%-5s%-6s%-11s\n", "IP 地址", "已发送", "已接收", "丢包率", "平均延迟", "下载速度 (MB/s)") + for i := 0; i < printResultNum; i++ { + fmt.Printf("%-18s%-8s%-8s%-8s%-10s%-15s\n", ipPadding(dateString[i][0]), dateString[i][1], dateString[i][2], dateString[i][3], dateString[i][4], dateString[i][5]) + } } if sysType == "windows" { // 如果是 Windows 系统,则需要按下 回车键 或 Ctrl+C 退出 diff --git a/tcping.go b/tcping.go index 545a465..a4b8b7b 100644 --- a/tcping.go +++ b/tcping.go @@ -15,7 +15,13 @@ import ( //bool connectionSucceed float32 time func tcping(ip net.IPAddr, tcpPort int) (bool, float32) { startTime := time.Now() - conn, err := net.DialTimeout("tcp", ip.String()+":"+strconv.Itoa(tcpPort), tcpConnectTimeout) + var fullAddress string + if ipv6Mode { // IPv6 需要加上 [] + fullAddress = "[" + ip.String() + "]:" + strconv.Itoa(tcpPort) + } else { + fullAddress = ip.String() + ":" + strconv.Itoa(tcpPort) + } + conn, err := net.DialTimeout("tcp", fullAddress, tcpConnectTimeout) if err != nil { return false, 0 } else { @@ -107,8 +113,14 @@ func DownloadSpeedHandler(ip net.IPAddr) (bool, float32) { Jar: nil, Timeout: 0, } + var fullAddress string + if ipv6Mode { // IPv6 需要加上 [] + fullAddress = "[" + ip.String() + "]:443" + } else { + fullAddress = ip.String() + ":443" + } client.Transport = &http.Transport{ - DialContext: GetDialContextByAddr(ip.String() + ":443"), + DialContext: GetDialContextByAddr(fullAddress), } response, err := client.Get(url) diff --git a/util.go b/util.go index 3e197d1..e1b0999 100644 --- a/util.go +++ b/util.go @@ -64,8 +64,6 @@ func convertToString(data []CloudflareIPData) [][]string { var pingTime int var pingRoutine int -var ipEndWith uint8 = 0 - type progressEvent int const ( @@ -93,8 +91,19 @@ func initRandSeed() { rand.Seed(time.Now().UnixNano()) } -func randipEndWith() { - ipEndWith = uint8(rand.Intn(254) + 1) +func randipEndWith() uint8 { + return uint8(rand.Intn(254) + 1) +} + +func GetRandomString() string { + str := "0123456789abcdef" + bytes := []byte(str) + result := []byte{} + r := rand.New(rand.NewSource(time.Now().UnixNano())) + for i := 0; i < 4; i++ { + result = append(result, bytes[r.Intn(len(bytes))]) + } + return string(result) } func ipPadding(ip string) string {