Browse Source

rebuild load ip

mazhuang 4 years ago
parent
commit
28d5d89e85
5 changed files with 211 additions and 53 deletions
  1. 2 44
      main.go
  2. 1 1
      task/download.go
  3. 201 1
      task/ip.go
  4. 6 6
      task/tcping.go
  5. 1 1
      utils/csv.go

+ 2 - 44
main.go

@@ -95,8 +95,8 @@ https://github.com/XIU2/CloudflareSpeedTest
 
 func main() {
 	go checkUpdate()                          // 检查版本更新
-	initRandSeed()                            // 置随机数种子
-	ips := loadFirstIPOfRangeFromFile(task.IPFile) // 读入IP
+	ips := task.LoadIPRanges()
+	// ips := loadFirstIPOfRangeFromFile(task.IPFile) // 读入IP
 
 	// 开始延迟测速
 	fmt.Printf("# XIU2/CloudflareSpeedTest %s \n", version)
@@ -123,48 +123,6 @@ func main() {
 		var pause int
 		fmt.Scanln(&pause)
 	}
-
-	// control := make(chan bool, pingRoutine)
-	// for _, ip := range ips {
-	// 	wg.Add(1)
-	// 	control <- false
-	// 	handleProgress := handleProgressGenerator(bar) // 多线程进度条
-	// 	go tcpingGoroutine(&wg, &mu, ip, tcpPort, pingTime, &data, control, handleProgress)
-	// }
-	// wg.Wait()
-	// bar.Finish()
-	// data := ping.Data()
-	// sort.Sort(utils.CloudflareIPDataSet(data))
-	// sort.Sort(CloudflareIPDataSet(data)) // 排序(按延迟,从低到高,不同丢包率会分开单独按延迟和丢包率排序)
-
-	// 延迟测速完毕后,以 [平均延迟上限] + [平均延迟下限] 条件过滤结果
-	// if timeLimit != 9999 || timeLimitLow != 0 {
-	// 	for i := 0; i < len(data); i++ {
-	// 		if float64(data[i].pingTime) > timeLimit { // 平均延迟上限
-	// 			break
-	// 		}
-	// 		if float64(data[i].pingTime) <= timeLimitLow { // 平均延迟下限
-	// 			continue
-	// 		}
-	// 		data2 = append(data2, data[i]) // 延迟满足条件时,添加到新数组中
-	// 	}
-	// 	data = data2
-	// 	data2 = []CloudflareIPData{}
-	// }
-
-	// 开始下载测速
-	// if !disableDownload { // 如果禁用下载测速就跳过
-	// 	testDownloadSpeed(data, data2, bar)
-	// }
-
-	// if len(data2) > 0 { // 如果该数组有内容,说明指定了 [下载测速下限] 条件,且最少有 1 个满足条件的 IP
-	// 	data = data2
-	// }
-	// sort.Sort(CloudflareIPDataSetD(data)) // 排序(按下载速度,从高到低)
-	// if outputFile != "" {
-	// 	ExportCsv(outputFile, data) // 输出结果到文件
-	// }
-	// printResult(data) // 显示最快结果
 }
 
 // 检查更新

+ 1 - 1
task/download.go

@@ -67,7 +67,7 @@ func TestDownloadSpeed(ipSet utils.PingDelaySet) (sppedSet utils.DownloadSpeedSe
 	fmt.Printf("开始下载测速(下载速度下限:%.2f MB/s,下载测速数量:%d,下载测速队列:%d):\n", MinSpeed, TestCount, testNum)
 	bar := utils.NewBar(TestCount)
 	for i := 0; i < testNum; i++ {
-		speed := downloadSpeedHandler(&ipSet[i].IP)
+		speed := downloadSpeedHandler(ipSet[i].IP)
 		ipSet[i].DownloadSpeed = speed
 		// 在每个 IP 下载测速后,以 [下载速度下限] 条件过滤结果
 		if speed >= MinSpeed*1024*1024 {

+ 201 - 1
task/ip.go

@@ -1,10 +1,210 @@
 package task
 
+import (
+	"bufio"
+	"log"
+	"math/rand"
+	"net"
+	"os"
+	"strconv"
+	"strings"
+	"time"
+)
+
+const defaultInputFile = "ip.txt"
+
 var (
 	// IPv6 IP version is 6
 	IPv6 = false
 	// TestAll test all ip
 	TestAll = false
 	// IPFile is the filename of IP Rangs
-	IPFile = "ip.txt"
+	IPFile = defaultInputFile
 )
+
+func randipEndWith(num int) uint8 {
+	rand.Seed(time.Now().UnixNano())
+	return uint8(rand.Intn(num))
+}
+
+func LoadIPRanges() []*net.IPAddr {
+	if IPFile == "" {
+		IPFile = defaultInputFile
+	}
+	file, err := os.Open(IPFile)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer file.Close()
+	firstIPs := make([]*net.IPAddr, 0)
+	scanner := bufio.NewScanner(file)
+	// scanner.Split(bufio.ScanLines)
+	for scanner.Scan() {
+		IPString := scanner.Text()
+		// 如果不含有 '/' 则代表不是 IP 段,而是一个单独的 IP,因此需要加上 /32 /128 子网掩码
+		if !strings.Contains(IPString, "/") {
+			if IPv6 {
+				IPString += "/128"
+			} else {
+				IPString += "/32"
+			}
+		}
+		firstIP, IPRange, err := net.ParseCIDR(IPString)
+		// fmt.Println(firstIP)
+		// fmt.Println(IPRange)
+		if err != nil {
+			log.Fatal(err)
+		}
+		if IPv6 {
+			//IPv6
+			loadIPv6(IPString, IPRange, firstIP, firstIPs)
+			continue
+		}
+		// IPv4
+		minIP, maxIP, mask := getCidrIPRange(IPString) // 获取 IP 最后一段最小值和最大值
+		maxIPNum := getCidrHostNum(mask)               // 根据子网掩码获取主机数量
+		for IPRange.Contains(firstIP) {
+			if TestAll { // 如果是测速全部 IP
+				for i := minIP; i <= maxIP; i++ { // 遍历 IP 最后一段最小值到最大值
+					firstIP[15] = i
+					firstIPCopy := make([]byte, len(firstIP))
+					copy(firstIPCopy, firstIP)
+					firstIPs = append(firstIPs, &net.IPAddr{IP: firstIPCopy})
+				}
+			} else { // 随机 IP 的最后一段 0.0.0.X
+				firstIP[15] = minIP + randipEndWith(maxIPNum)
+				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
+				}
+			}
+		}
+
+	}
+	return firstIPs
+}
+
+func loadIPv6(IPString string, IPRange *net.IPNet, firstIP net.IP, firstIPs []*net.IPAddr) {
+	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])
+		if !strings.Contains(IPString, "/128") {
+			firstIP[15] = randipEndWith(255) // 随机 IP 的最后一段
+			firstIP[14] = randipEndWith(255) // 随机 IP 的最后一段
+		}
+		firstIPCopy := make([]byte, len(firstIP))
+		copy(firstIPCopy, firstIP)
+		firstIPs = append(firstIPs, &net.IPAddr{IP: firstIPCopy})
+		tempIP = firstIP[13]
+		firstIP[13] += randipEndWith(255)
+		if firstIP[13] >= tempIP {
+			continue
+		}
+		tempIP = firstIP[12]
+		firstIP[12] += randipEndWith(255)
+		if firstIP[12] >= tempIP {
+			continue
+		}
+		tempIP = firstIP[11]
+		firstIP[11] += randipEndWith(255)
+		if firstIP[11] >= tempIP {
+			continue
+		}
+		tempIP = firstIP[10]
+		firstIP[10] += randipEndWith(255)
+		if firstIP[10] >= tempIP {
+			continue
+		}
+		tempIP = firstIP[9]
+		firstIP[9] += randipEndWith(255)
+		if firstIP[9] >= tempIP {
+			continue
+		}
+		tempIP = firstIP[8]
+		firstIP[8] += randipEndWith(255)
+		if firstIP[8] >= tempIP {
+			continue
+		}
+		tempIP = firstIP[7]
+		firstIP[7] += randipEndWith(255)
+		if firstIP[7] >= tempIP {
+			continue
+		}
+		tempIP = firstIP[6]
+		firstIP[6] += randipEndWith(255)
+		if firstIP[6] >= tempIP {
+			continue
+		}
+		tempIP = firstIP[5]
+		firstIP[5] += randipEndWith(255)
+		if firstIP[5] >= tempIP {
+			continue
+		}
+		tempIP = firstIP[4]
+		firstIP[4] += randipEndWith(255)
+		if firstIP[4] >= tempIP {
+			continue
+		}
+		tempIP = firstIP[3]
+		firstIP[3] += randipEndWith(255)
+		if firstIP[3] >= tempIP {
+			continue
+		}
+		tempIP = firstIP[2]
+		firstIP[2] += randipEndWith(255)
+		if firstIP[2] >= tempIP {
+			continue
+		}
+		tempIP = firstIP[1]
+		firstIP[1] += randipEndWith(255)
+		if firstIP[1] >= tempIP {
+			continue
+		}
+		tempIP = firstIP[0]
+		firstIP[0] += randipEndWith(255)
+	}
+}
+
+// 根据子网掩码获取主机数量
+func getCidrHostNum(maskLen int) int {
+	cidrIPNum := int(0)
+	if maskLen < 32 {
+		var i int = int(32 - maskLen - 1)
+		for ; i >= 1; i-- {
+			cidrIPNum += 1 << i
+		}
+		cidrIPNum += 2
+	} else {
+		cidrIPNum = 1
+	}
+	if cidrIPNum > 255 {
+		cidrIPNum = 255
+	}
+	return cidrIPNum
+}
+
+// 获取 IP 最后一段最小值和最大值、子网掩码
+func getCidrIPRange(cidr string) (minIP, maxIP uint8, mask int) {
+	ipRange := strings.Split(cidr, "/")
+	ipSegs := strings.Split(ipRange[0], ".")
+	mask, _ = strconv.Atoi(ipRange[1])
+	seg4, _ := strconv.Atoi(ipSegs[3])
+	minIP, maxIP = getIPSegRange(uint8(seg4), uint8(32-mask))
+	return
+}
+
+// 根据输入的基础IP地址和CIDR掩码计算一个IP片段的区间
+func getIPSegRange(userSegIP, offset uint8) (uint8, uint8) {
+	var ipSegMax uint8 = 255
+	netSegIP := ipSegMax << offset
+	segMinIP := netSegIP & userSegIP
+	segMaxIP := userSegIP&(255<<offset) | ^(255 << offset)
+	return segMinIP, segMaxIP
+}

+ 6 - 6
task/tcping.go

@@ -27,7 +27,7 @@ var (
 type Ping struct {
 	wg      *sync.WaitGroup
 	m       *sync.Mutex
-	ips     []net.IPAddr
+	ips     []*net.IPAddr
 	csv     utils.PingDelaySet
 	control chan bool
 	bar     *utils.Bar
@@ -45,7 +45,7 @@ func checkPingDefault() {
 	}
 }
 
-func NewPing(ips []net.IPAddr) *Ping {
+func NewPing(ips []*net.IPAddr) *Ping {
 	checkPingDefault()
 	return &Ping{
 		wg:      &sync.WaitGroup{},
@@ -69,14 +69,14 @@ func (p *Ping) Run() utils.PingDelaySet {
 	return p.csv
 }
 
-func (p *Ping) start(ip net.IPAddr) {
+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) {
+func (p *Ping) tcping(ip *net.IPAddr) (bool, time.Duration) {
 	startTime := time.Now()
 	fullAddress := fmt.Sprintf("%s:%d", ip.String(), TCPPort)
 	//fmt.Println(ip.String())
@@ -93,7 +93,7 @@ func (p *Ping) tcping(ip net.IPAddr) (bool, time.Duration) {
 }
 
 //pingReceived pingTotalTime
-func (p *Ping) checkConnection(ip net.IPAddr) (recv int, totalDelay time.Duration) {
+func (p *Ping) checkConnection(ip *net.IPAddr) (recv int, totalDelay time.Duration) {
 	for i := 0; i < PingTimes; i++ {
 		if ok, delay := p.tcping(ip); ok {
 			recv++
@@ -112,7 +112,7 @@ func (p *Ping) appendIPData(data *utils.PingData) {
 }
 
 //return Success packetRecv averagePingTime specificIPAddr
-func (p *Ping) tcpingHandler(ip net.IPAddr) {
+func (p *Ping) tcpingHandler(ip *net.IPAddr) {
 	ipCanConnect := false
 	pingRecv := 0
 	var delay time.Duration

+ 1 - 1
utils/csv.go

@@ -23,7 +23,7 @@ var (
 )
 
 type PingData struct {
-	IP       net.IPAddr
+	IP       *net.IPAddr
 	Sended   int
 	Received int
 	Delay    time.Duration