| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 | 
							- package task
 
- import (
 
- 	"fmt"
 
- 	"net"
 
- 	"sort"
 
- 	"strconv"
 
- 	"sync"
 
- 	"time"
 
- 	"github.com/XIU2/CloudflareSpeedTest/utils"
 
- )
 
- const (
 
- 	tcpConnectTimeout = time.Second * 1
 
- 	maxRoutine        = 1000
 
- 	defaultRoutines   = 200
 
- 	defaultPort       = 443
 
- 	defaultPingTimes  = 4
 
- )
 
- var (
 
- 	Routines      = defaultRoutines
 
- 	TCPPort   int = defaultPort
 
- 	PingTimes int = defaultPingTimes
 
- )
 
- type Ping struct {
 
- 	wg      *sync.WaitGroup
 
- 	m       *sync.Mutex
 
- 	ips     []*net.IPAddr
 
- 	csv     utils.PingDelaySet
 
- 	control chan bool
 
- 	bar     *utils.Bar
 
- }
 
- func checkPingDefault() {
 
- 	if Routines <= 0 {
 
- 		Routines = defaultRoutines
 
- 	}
 
- 	if TCPPort <= 0 || TCPPort >= 65535 {
 
- 		TCPPort = defaultPort
 
- 	}
 
- 	if PingTimes <= 0 {
 
- 		PingTimes = defaultPingTimes
 
- 	}
 
- }
 
- func NewPing() *Ping {
 
- 	checkPingDefault()
 
- 	ips := loadIPRanges()
 
- 	return &Ping{
 
- 		wg:      &sync.WaitGroup{},
 
- 		m:       &sync.Mutex{},
 
- 		ips:     ips,
 
- 		csv:     make(utils.PingDelaySet, 0),
 
- 		control: make(chan bool, Routines),
 
- 		bar:     utils.NewBar(len(ips), "可用:", ""),
 
- 	}
 
- }
 
- func (p *Ping) Run() utils.PingDelaySet {
 
- 	if len(p.ips) == 0 {
 
- 		return p.csv
 
- 	}
 
- 	if Httping {
 
- 		utils.Cyan.Printf("开始延迟测速(模式:HTTP, 端口:%d, 范围:%v ~ %v ms, 丢包:%.2f)\n", TCPPort, utils.InputMinDelay.Milliseconds(), utils.InputMaxDelay.Milliseconds(), utils.InputMaxLossRate)
 
- 	} else {
 
- 		utils.Cyan.Printf("开始延迟测速(模式:TCP, 端口:%d, 范围:%v ~ %v ms, 丢包:%.2f)\n", TCPPort, utils.InputMinDelay.Milliseconds(), utils.InputMaxDelay.Milliseconds(), utils.InputMaxLossRate)
 
- 	}
 
- 	for _, ip := range p.ips {
 
- 		p.wg.Add(1)
 
- 		p.control <- false
 
- 		go p.start(ip)
 
- 	}
 
- 	p.wg.Wait()
 
- 	p.bar.Done()
 
- 	sort.Sort(p.csv)
 
- 	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()
 
- 	var fullAddress string
 
- 	if isIPv4(ip.String()) {
 
- 		fullAddress = fmt.Sprintf("%s:%d", ip.String(), TCPPort)
 
- 	} else {
 
- 		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, colo string) {
 
- 	if Httping {
 
- 		recv, totalDelay, colo = p.httping(ip)
 
- 		return
 
- 	}
 
- 	colo = "" // TCPing 不获取 colo
 
- 	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,
 
- 	})
 
- }
 
- // handle tcping
 
- func (p *Ping) tcpingHandler(ip *net.IPAddr) {
 
- 	recv, totalDlay, colo := p.checkConnection(ip)
 
- 	nowAble := len(p.csv)
 
- 	if recv != 0 {
 
- 		nowAble++
 
- 	}
 
- 	p.bar.Grow(1, strconv.Itoa(nowAble))
 
- 	if recv == 0 {
 
- 		return
 
- 	}
 
- 	data := &utils.PingData{
 
- 		IP:       ip,
 
- 		Sended:   PingTimes,
 
- 		Received: recv,
 
- 		Delay:    totalDlay / time.Duration(recv),
 
- 		Colo:     colo,
 
- 	}
 
- 	p.appendIPData(data)
 
- }
 
 
  |