tcping.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. package task
  2. import (
  3. "fmt"
  4. "net"
  5. "sort"
  6. "sync"
  7. "time"
  8. "CloudflareSpeedTest/utils"
  9. )
  10. const (
  11. tcpConnectTimeout = time.Second * 1
  12. maxRoutine = 1000
  13. defaultRoutines = 200
  14. defaultPort = 443
  15. defaultPingTimes = 4
  16. )
  17. var (
  18. Routines = defaultRoutines
  19. TCPPort int = defaultPort
  20. PingTimes int = defaultPingTimes
  21. )
  22. type Ping struct {
  23. wg *sync.WaitGroup
  24. m *sync.Mutex
  25. ips []*net.IPAddr
  26. csv utils.PingDelaySet
  27. control chan bool
  28. bar *utils.Bar
  29. }
  30. func checkPingDefault() {
  31. if Routines <= 0 {
  32. Routines = defaultRoutines
  33. }
  34. if TCPPort <= 0 || TCPPort >= 65535 {
  35. TCPPort = defaultPort
  36. }
  37. if PingTimes <= 0 {
  38. PingTimes = defaultPingTimes
  39. }
  40. }
  41. func NewPing() *Ping {
  42. checkPingDefault()
  43. ips := loadIPRanges()
  44. return &Ping{
  45. wg: &sync.WaitGroup{},
  46. m: &sync.Mutex{},
  47. ips: ips,
  48. csv: make(utils.PingDelaySet, 0),
  49. control: make(chan bool, Routines),
  50. bar: utils.NewBar(len(ips)),
  51. }
  52. }
  53. func (p *Ping) Run() utils.PingDelaySet {
  54. if len(p.ips) == 0 {
  55. return p.csv
  56. }
  57. ipVersion := "IPv4"
  58. if IPv6 { // IPv6 模式判断
  59. ipVersion = "IPv6"
  60. }
  61. fmt.Printf("开始延迟测速(模式:TCP %s,端口:%d,平均延迟上限:%vms,平均延迟下限:%vms)\n", ipVersion, TCPPort, utils.InputMaxDelay.Milliseconds(), utils.InputMinDelay.Milliseconds())
  62. for _, ip := range p.ips {
  63. p.wg.Add(1)
  64. p.control <- false
  65. go p.start(ip)
  66. }
  67. p.wg.Wait()
  68. p.bar.Done()
  69. sort.Sort(p.csv)
  70. return p.csv
  71. }
  72. func (p *Ping) start(ip *net.IPAddr) {
  73. defer p.wg.Done()
  74. p.tcpingHandler(ip)
  75. <-p.control
  76. }
  77. //bool connectionSucceed float32 time
  78. func (p *Ping) tcping(ip *net.IPAddr) (bool, time.Duration) {
  79. startTime := time.Now()
  80. fullAddress := fmt.Sprintf("%s:%d", ip.String(), TCPPort)
  81. //fmt.Println(ip.String())
  82. if IPv6 { // IPv6 需要加上 []
  83. fullAddress = fmt.Sprintf("[%s]:%d", ip.String(), TCPPort)
  84. }
  85. conn, err := net.DialTimeout("tcp", fullAddress, tcpConnectTimeout)
  86. if err != nil {
  87. return false, 0
  88. }
  89. defer conn.Close()
  90. duration := time.Since(startTime)
  91. return true, duration
  92. }
  93. //pingReceived pingTotalTime
  94. func (p *Ping) checkConnection(ip *net.IPAddr) (recv int, totalDelay time.Duration) {
  95. for i := 0; i < PingTimes; i++ {
  96. if ok, delay := p.tcping(ip); ok {
  97. recv++
  98. totalDelay += delay
  99. }
  100. }
  101. return
  102. }
  103. func (p *Ping) appendIPData(data *utils.PingData) {
  104. p.m.Lock()
  105. defer p.m.Unlock()
  106. p.csv = append(p.csv, utils.CloudflareIPData{
  107. PingData: data,
  108. })
  109. }
  110. //return Success packetRecv averagePingTime specificIPAddr
  111. func (p *Ping) tcpingHandler(ip *net.IPAddr) {
  112. ipCanConnect := false
  113. pingRecv := 0
  114. var delay time.Duration
  115. for !ipCanConnect {
  116. recv, totalDlay := p.checkConnection(ip)
  117. if recv > 0 {
  118. ipCanConnect = true
  119. pingRecv = recv
  120. delay = totalDlay
  121. } else {
  122. ip.IP[15]++
  123. if ip.IP[15] == 0 {
  124. break
  125. }
  126. break
  127. }
  128. }
  129. p.bar.Grow(1)
  130. if !ipCanConnect {
  131. return
  132. }
  133. // for i := 0; i < PingTimes; i++ {
  134. // pingSuccess, pingTimeCurrent := p.tcping(ip)
  135. // progressHandler(utils.NormalPing)
  136. // if pingSuccess {
  137. // pingRecv++
  138. // pingTime += pingTimeCurrent
  139. // }
  140. // }
  141. data := &utils.PingData{
  142. IP: ip,
  143. Sended: PingTimes,
  144. Received: pingRecv,
  145. Delay: delay / time.Duration(pingRecv),
  146. }
  147. p.appendIPData(data)
  148. return
  149. }