Bläddra i källkod

新增 IPv6 支持

xiu2 4 år sedan
förälder
incheckning
4b4426c195
5 ändrade filer med 133 tillägg och 27 borttagningar
  1. 77 11
      IPRangeLoader.go
  2. 9 4
      README.md
  3. 20 6
      main.go
  4. 14 2
      tcping.go
  5. 13 4
      util.go

+ 77 - 11
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
+					}
 				}
 			}
 		}

+ 9 - 4
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),如果包含空格请加上引号

+ 20 - 6
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 退出

+ 14 - 2
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)
 

+ 13 - 4
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 {