Pārlūkot izejas kodu

tcping add progressbar

mazhuang 4 gadi atpakaļ
vecāks
revīzija
4d64abb94d
7 mainītis faili ar 237 papildinājumiem un 148 dzēšanām
  1. 13 3
      main.go
  2. 6 0
      task/ip.go
  3. 135 0
      task/tcping.go
  4. 1 1
      tcping.go
  5. 0 129
      tcping/ping.go
  6. 73 14
      utils/csv.go
  7. 9 1
      utils/progress.go

+ 13 - 3
main.go

@@ -11,6 +11,8 @@ import (
 	"sync"
 	"time"
 
+	"CloudflareSpeedTest/task"
+
 	"github.com/cheggaaa/pb/v3"
 )
 
@@ -76,12 +78,16 @@ https://github.com/XIU2/CloudflareSpeedTest
 	flag.Float64Var(&speedLimit, "sl", 0, "下载速度下限")
 	flag.IntVar(&printResultNum, "p", 20, "显示结果数量")
 	flag.BoolVar(&disableDownload, "dd", false, "禁用下载测速")
-	flag.BoolVar(&ipv6Mode, "ipv6", false, "禁用下载测速")
+	flag.BoolVar(&ipv6Mode, "ipv6", false, "启用IPv6")
 	flag.BoolVar(&allip, "allip", false, "测速全部 IP")
 	flag.StringVar(&ipFile, "f", "ip.txt", "IP 数据文件")
 	flag.StringVar(&outputFile, "o", "result.csv", "输出结果文件")
 	flag.BoolVar(&printVersion, "v", false, "打印程序版本")
 
+	task.TCPPort = tcpPort
+	task.IPv6 = ipv6Mode
+	task.DefaultRoutine = pingRoutine
+
 	flag.Usage = func() { fmt.Print(help) }
 	flag.Parse()
 	if printVersion {
@@ -155,16 +161,20 @@ func main() {
 		ipVersion = "IPv6"
 	}
 	fmt.Printf("开始延迟测速(模式:TCP %s,端口:%d ,平均延迟上限:%.2f ms,平均延迟下限:%.2f ms):\n", ipVersion, tcpPort, timeLimit, timeLimitLow)
+
+	// ping := task.NewPing(ips)
+	// ping.Run()
 	control := make(chan bool, pingRoutine)
 	for _, ip := range ips {
 		wg.Add(1)
-		// control <- false
+		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)) // 排序(按延迟,从低到高,不同丢包率会分开单独按延迟和丢包率排序)
 
 	// 延迟测速完毕后,以 [平均延迟上限] + [平均延迟下限] 条件过滤结果

+ 6 - 0
task/ip.go

@@ -0,0 +1,6 @@
+package task
+
+var (
+	// IPv6 IP version is 6
+	IPv6 = false
+)

+ 135 - 0
task/tcping.go

@@ -0,0 +1,135 @@
+package task
+
+import (
+	"fmt"
+	"net"
+	"sync"
+	"time"
+
+	"CloudflareSpeedTest/utils"
+)
+
+const (
+	tcpConnectTimeout = time.Second * 1
+	maxRoutine        = 1000
+)
+
+var (
+	DefaultRoutine     = 200
+	TCPPort        int = 443
+	PingTimes      int = 4
+)
+
+type Ping struct {
+	wg      *sync.WaitGroup
+	m       *sync.Mutex
+	ips     []net.IPAddr
+	csv     utils.PingDelaySet
+	control chan bool
+	bar     *utils.Bar
+}
+
+func NewPing(ips []net.IPAddr) *Ping {
+	return &Ping{
+		wg:      &sync.WaitGroup{},
+		m:       &sync.Mutex{},
+		ips:     ips,
+		csv:     make(utils.PingDelaySet, 0),
+		control: make(chan bool, DefaultRoutine),
+		bar:     utils.NewBar(len(ips) * PingTimes),
+	}
+}
+
+func (p *Ping) Run() utils.PingDelaySet {
+	for _, ip := range p.ips {
+		p.wg.Add(1)
+		p.control <- false
+		go p.start(ip)
+	}
+	p.wg.Wait()
+	p.bar.Done()
+	return p.csv
+}
+
+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) {
+	startTime := time.Now()
+	fullAddress := fmt.Sprintf("%s:%d", ip.String(), TCPPort)
+	//fmt.Println(ip.String())
+	if IPv6 { // IPv6 需要加上 []
+		fullAddress = fmt.Sprintf("[%s]:%d", ip.String(), TCPPort)
+	}
+	conn, err := net.DialTimeout("tcp", fullAddress, tcpConnectTimeout)
+	if err != nil {
+		return false, 0
+	}
+	defer conn.Close()
+	duration := time.Since(startTime)
+	return true, duration
+}
+
+//pingReceived pingTotalTime
+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++
+			totalDelay += delay
+		}
+	}
+	return
+}
+
+func (p *Ping) appendIPData(data *utils.PingData) {
+	p.m.Lock()
+	defer p.m.Unlock()
+	p.csv = append(p.csv, utils.CloudflareIPData{
+		PingData: data,
+	})
+}
+
+//return Success packetRecv averagePingTime specificIPAddr
+func (p *Ping) tcpingHandler(ip net.IPAddr) {
+	ipCanConnect := false
+	pingRecv := 0
+	var delay time.Duration
+	for !ipCanConnect {
+		recv, totalDlay := p.checkConnection(ip)
+		if recv > 0 {
+			ipCanConnect = true
+			pingRecv = recv
+			delay = totalDlay
+		} else {
+			ip.IP[15]++
+			if ip.IP[15] == 0 {
+				break
+			}
+			break
+		}
+	}
+	p.bar.Grow(PingTimes)
+	if !ipCanConnect {
+		return
+	}
+	// for i := 0; i < PingTimes; i++ {
+	// 	pingSuccess, pingTimeCurrent := p.tcping(ip)
+	// 	progressHandler(utils.NormalPing)
+	// 	if pingSuccess {
+	// 		pingRecv++
+	// 		pingTime += pingTimeCurrent
+	// 	}
+	// }
+	data := &utils.PingData{
+		IP:       ip,
+		Sended:    PingTimes,
+		Received: pingRecv,
+		Delay:    delay / time.Duration(pingRecv),
+	}
+	p.appendIPData(data)
+	return
+}

+ 1 - 1
tcping.go

@@ -91,7 +91,7 @@ func tcpingGoroutine(wg *sync.WaitGroup, mutex *sync.Mutex, ip net.IPAddr, tcpPo
 		*csv = append(*csv, cfdata)
 		mutex.Unlock()
 	}
-	// <-control
+	<-control
 }
 
 func GetDialContextByAddr(fakeSourceAddr string) func(ctx context.Context, network, address string) (net.Conn, error) {

+ 0 - 129
tcping/ping.go

@@ -1,129 +0,0 @@
-package tcp
-
-import (
-	"fmt"
-	"net"
-	"sync"
-	"time"
-
-	"CloudflareSpeedTest/utils"
-)
-
-const tcpConnectTimeout = time.Second * 1
-
-type Ping struct {
-	wg              *sync.WaitGroup
-	m               *sync.Mutex
-	ips             []net.IPAddr
-	isIPv6          bool
-	tcpPort         int
-	pingCount       int
-	csv             []utils.CloudflareIPData
-	control         chan bool
-	progressHandler func(e utils.ProgressEvent)
-}
-
-func NewPing(ips []net.IPAddr, port, pingTime int, ipv6 bool) *Ping {
-	return &Ping{
-		wg:        &sync.WaitGroup{},
-		m:         &sync.Mutex{},
-		ips:       ips,
-		isIPv6:    ipv6,
-		tcpPort:   port,
-		pingCount: pingTime,
-		csv:       make([]utils.CloudflareIPData, 0),
-		control:   make(chan bool),
-	}
-}
-
-func (p *Ping) Run() {
-	for _, ip := range p.ips {
-		p.wg.Add(1)
-		p.control <- false
-		go p.start(ip)
-	}
-}
-
-func (p *Ping) start(ip net.IPAddr) {
-	defer p.wg.Done()
-	if ok, data := p.tcpingHandler(ip, nil); ok {
-		p.appendIPData(data)
-	}
-	<-p.control
-}
-
-func (p *Ping) appendIPData(data *utils.PingData) {
-	p.m.Lock()
-	defer p.m.Unlock()
-	p.csv = append(p.csv, utils.CloudflareIPData{
-		PingData: data,
-	})
-}
-
-//bool connectionSucceed float32 time
-func (p *Ping) tcping(ip net.IPAddr) (bool, time.Duration) {
-	startTime := time.Now()
-	fullAddress := fmt.Sprintf("%s:%d", ip.String(), p.tcpPort)
-	//fmt.Println(ip.String())
-	if p.isIPv6 { // IPv6 需要加上 []
-		fullAddress = fmt.Sprintf("[%s]:%d", ip.String(), p.tcpPort)
-	}
-	conn, err := net.DialTimeout("tcp", fullAddress, tcpConnectTimeout)
-	if err != nil {
-		return false, 0
-	}
-	defer conn.Close()
-	duration := time.Since(startTime)
-	return true, duration
-}
-
-//pingReceived pingTotalTime
-func (p *Ping) checkConnection(ip net.IPAddr) (pingRecv int, pingTime time.Duration) {
-	for i := 0; i < p.pingCount; i++ {
-		if pingSucceed, pingTimeCurrent := p.tcping(ip); pingSucceed {
-			pingRecv++
-			pingTime += pingTimeCurrent
-		}
-	}
-	return
-}
-
-//return Success packetRecv averagePingTime specificIPAddr
-func (p *Ping) tcpingHandler(ip net.IPAddr, progressHandler func(e utils.ProgressEvent)) (bool, *utils.PingData) {
-	ipCanConnect := false
-	pingRecv := 0
-	var pingTime time.Duration
-	for !ipCanConnect {
-		pingRecvCurrent, pingTimeCurrent := p.checkConnection(ip)
-		if pingRecvCurrent != 0 {
-			ipCanConnect = true
-			pingRecv = pingRecvCurrent
-			pingTime = pingTimeCurrent
-		} else {
-			ip.IP[15]++
-			if ip.IP[15] == 0 {
-				break
-			}
-			break
-		}
-	}
-	if !ipCanConnect {
-		progressHandler(utils.NoAvailableIPFound)
-		return false, nil
-	}
-	progressHandler(utils.AvailableIPFound)
-	for i := 0; i < p.pingCount; i++ {
-		pingSuccess, pingTimeCurrent := p.tcping(ip)
-		progressHandler(utils.NormalPing)
-		if pingSuccess {
-			pingRecv++
-			pingTime += pingTimeCurrent
-		}
-	}
-	return true, &utils.PingData{
-		IP:       ip,
-		Count:    p.pingCount,
-		Received: pingRecv,
-		Delay:    pingTime / time.Duration(pingRecv),
-	}
-}

+ 73 - 14
utils/csv.go

@@ -5,13 +5,22 @@ import (
 	"log"
 	"net"
 	"os"
+	"sort"
 	"strconv"
 	"time"
 )
 
+var (
+	MaxDelay = 9999 * time.Millisecond
+	MinDelay = time.Duration(0)
+
+	InputMaxDelay = MaxDelay
+	InputMinDelay = MinDelay
+)
+
 type PingData struct {
 	IP       net.IPAddr
-	Count    int
+	Sended   int
 	Received int
 	Delay    time.Duration
 }
@@ -24,12 +33,23 @@ type CloudflareIPData struct {
 
 func (cf *CloudflareIPData) getRecvRate() float32 {
 	if cf.recvRate == 0 {
-		pingLost := cf.Count - cf.Received
-		cf.recvRate = float32(pingLost) / float32(cf.Count)
+		pingLost := cf.Sended - cf.Received
+		cf.recvRate = float32(pingLost) / float32(cf.Sended)
 	}
 	return cf.recvRate
 }
 
+func (cf *CloudflareIPData) toString() []string {
+	result := make([]string, 6)
+	result[0] = cf.IP.String()
+	result[1] = strconv.Itoa(cf.Sended)
+	result[2] = strconv.Itoa(cf.Received)
+	result[3] = strconv.FormatFloat(float64(cf.getRecvRate()), 'f', 2, 32)
+	result[4] = cf.Delay.String()
+	result[5] = strconv.FormatFloat(float64(cf.downloadSpeed)/1024/1024, 'f', 2, 32)
+	return result
+}
+
 func ExportCsv(filePath string, data []CloudflareIPData) {
 	fp, err := os.Create(filePath)
 	if err != nil {
@@ -43,17 +63,6 @@ func ExportCsv(filePath string, data []CloudflareIPData) {
 	w.Flush()
 }
 
-func (cf *CloudflareIPData) toString() []string {
-	result := make([]string, 6)
-	result[0] = cf.IP.String()
-	result[1] = strconv.Itoa(cf.Count)
-	result[2] = strconv.Itoa(cf.Received)
-	result[3] = strconv.FormatFloat(float64(cf.getRecvRate()), 'f', 2, 32)
-	result[4] = cf.Delay.String()
-	result[5] = strconv.FormatFloat(float64(cf.downloadSpeed)/1024/1024, 'f', 2, 32)
-	return result
-}
-
 func convertToString(data []CloudflareIPData) [][]string {
 	result := make([][]string, 0)
 	for _, v := range data {
@@ -61,3 +70,53 @@ func convertToString(data []CloudflareIPData) [][]string {
 	}
 	return result
 }
+
+type PingDelaySet []CloudflareIPData
+
+func (s PingDelaySet) FilterDelay() (data PingDelaySet) {
+	sort.Sort(s)
+	if InputMaxDelay >= MaxDelay || InputMinDelay <= MinDelay {
+		return s
+	}
+	for _, v := range s {
+		if v.Delay > MaxDelay { // 平均延迟上限
+			break
+		}
+		if v.Delay <= MinDelay { // 平均延迟下限
+			continue
+		}
+		data = append(data, v) // 延迟满足条件时,添加到新数组中
+	}
+	return
+}
+
+func (s PingDelaySet) Len() int {
+	return len(s)
+}
+
+func (s PingDelaySet) Less(i, j int) bool {
+	iRate, jRate := s[i].getRecvRate(), s[j].getRecvRate()
+	if iRate != jRate {
+		return iRate < jRate
+	}
+	return s[i].Delay < s[j].Delay
+}
+
+func (s PingDelaySet) Swap(i, j int) {
+	s[i], s[j] = s[j], s[i]
+}
+
+// 下载速度排序
+type DownloadSpeedSet []CloudflareIPData
+
+func (s DownloadSpeedSet) Len() int {
+	return len(s)
+}
+
+func (s DownloadSpeedSet) Less(i, j int) bool {
+	return s[i].downloadSpeed > s[j].downloadSpeed
+}
+
+func (s DownloadSpeedSet) Swap(i, j int) {
+	s[i], s[j] = s[j], s[i]
+}

+ 9 - 1
utils/progress.go

@@ -11,13 +11,21 @@ const (
 )
 
 type Bar struct {
-	*pb.ProgressBar
+	pb *pb.ProgressBar
 }
 
 func NewBar(count int) *Bar {
 	return &Bar{pb.Simple.Start(count)}
 }
 
+func (b *Bar) Grow(num int) {
+	b.pb.Add(num)
+}
+
+func (b *Bar) Done() {
+	b.pb.Finish()
+}
+
 func handleProgressGenerator(pb *pb.ProgressBar) func(e ProgressEvent) {
 	return func(e ProgressEvent) {
 		switch e {