main.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package main
  2. import (
  3. "flag"
  4. "fmt"
  5. "os"
  6. "sort"
  7. "strconv"
  8. "sync"
  9. "time"
  10. "github.com/cheggaaa/pb/v3"
  11. )
  12. var version string
  13. var disableDownload bool
  14. var tcpPort int
  15. var ipFile string
  16. var outputFile string
  17. var printResult int
  18. func init() {
  19. var downloadSecond int64
  20. var printVersion bool
  21. const help = `
  22. CloudflareSpeedTest
  23. 测试 Cloudflare CDN 所有 IP 的延迟和速度,获取最快 IP!
  24. https://github.com/XIU2/CloudflareSpeedTest
  25. 参数:
  26. -n 500
  27. 测速线程数量;数值越大速度越快,请勿超过 1000(结果误差大);(默认 500)
  28. -t 4
  29. 延迟测速次数;单个 IP 测速次数,为 1 时将过滤丢包的IP,TCP协议;(默认 4)
  30. -tp 443
  31. 延迟测速端口;延迟测速 TCP 协议的端口;(默认 443)
  32. -dn 20
  33. 下载测速数量;延迟测速并排序后,从最低延迟起下载测速数量,请勿太多(速度慢);(默认 20)
  34. -dt 10
  35. 下载测速时间;单个 IP 测速最长时间,单位:秒;(默认 10)
  36. -p 20
  37. 直接显示结果;测速后直接显示指定数量的结果,为 -1 时不显示结果直接退出;(默认 20)
  38. -f ip.txt
  39. IP 数据文件;相对/绝对路径,如包含空格请加上引号;支持其他 CDN IP段,记得禁用下载测速;(默认 ip.txt)
  40. -o result.csv
  41. 输出结果文件;相对/绝对路径,如包含空格请加上引号;允许 .txt 等后缀;(默认 result.csv)
  42. -dd
  43. 禁用下载测速;如果带上该参数就是禁用下载测速;(默认 启用)
  44. -v
  45. 打印程序版本
  46. -h
  47. 打印帮助说明
  48. 示例:
  49. CloudflareST.exe -n 500 -t 4 -dn 20 -dt 10
  50. CloudflareST.exe -n 500 -t 4 -dn 20 -dt 10 -f "ip.txt" -o "result.csv" -dd
  51. CloudflareST.exe -n 500 -t 4 -dn 20 -dt 10 -f "C:\abc\ip.txt" -o "C:\abc\result.csv" -dd`
  52. flag.IntVar(&pingRoutine, "n", 500, "测速线程数量")
  53. flag.IntVar(&pingTime, "t", 4, "延迟测速次数")
  54. flag.IntVar(&tcpPort, "tp", 443, "延迟测速端口")
  55. flag.IntVar(&downloadTestCount, "dn", 20, "下载测速数量")
  56. flag.Int64Var(&downloadSecond, "dt", 10, "下载测速时间")
  57. flag.IntVar(&printResult, "p", 20, "直接显示结果")
  58. flag.BoolVar(&disableDownload, "dd", false, "禁用下载测速")
  59. flag.StringVar(&ipFile, "f", "ip.txt", "IP 数据文件")
  60. flag.StringVar(&outputFile, "o", "result.csv", "输出结果文件")
  61. flag.BoolVar(&printVersion, "v", false, "打印程序版本")
  62. downloadTestTime = time.Duration(downloadSecond) * time.Second
  63. flag.Usage = func() { fmt.Print(help) }
  64. flag.Parse()
  65. if printVersion {
  66. println(version)
  67. os.Exit(0)
  68. }
  69. if pingRoutine <= 0 {
  70. pingRoutine = 500
  71. }
  72. if pingTime <= 0 {
  73. pingTime = 4
  74. }
  75. if tcpPort < 1 || tcpPort > 65535 {
  76. tcpPort = 443
  77. }
  78. if downloadTestCount <= 0 {
  79. downloadTestCount = 20
  80. }
  81. if downloadSecond <= 0 {
  82. downloadSecond = 10
  83. }
  84. if printResult == 0 {
  85. printResult = 20
  86. }
  87. if ipFile == "" {
  88. ipFile = "ip.txt"
  89. }
  90. if outputFile == "" {
  91. outputFile = "result.csv"
  92. }
  93. }
  94. func main() {
  95. initipEndWith() // 随机数
  96. failTime = pingTime // 设置接收次数
  97. ips := loadFirstIPOfRangeFromFile(ipFile) // 读入IP
  98. pingCount := len(ips) * pingTime // 计算进度条总数(IP*测试次数)
  99. bar := pb.Full.Start(pingCount) // 进度条总数
  100. var wg sync.WaitGroup
  101. var mu sync.Mutex
  102. var data = make([]CloudflareIPData, 0)
  103. fmt.Println("开始延迟测速(模式:TCP,端口:" + strconv.Itoa(tcpPort) + "):")
  104. control := make(chan bool, pingRoutine)
  105. for _, ip := range ips {
  106. wg.Add(1)
  107. control <- false
  108. handleProgress := handleProgressGenerator(bar) // 多线程进度条
  109. go tcpingGoroutine(&wg, &mu, ip, tcpPort, pingTime, &data, control, handleProgress)
  110. }
  111. wg.Wait()
  112. bar.Finish()
  113. sort.Sort(CloudflareIPDataSet(data)) // 排序
  114. // 下载测速
  115. if !disableDownload { // 如果禁用下载测速就跳过
  116. if len(data) > 0 { // IP数组长度(IP数量) 大于 0 时继续
  117. if len(data) < downloadTestCount { // 如果IP数组长度(IP数量) 小于 下载测速次数,则次数改为IP数
  118. downloadTestCount = len(data)
  119. fmt.Println("\n[信息] IP数量小于下载测速次数,下载测速次数改为IP数。\n")
  120. }
  121. bar = pb.Simple.Start(downloadTestCount)
  122. fmt.Println("开始下载测速:")
  123. for i := 0; i < downloadTestCount; i++ {
  124. _, speed := DownloadSpeedHandler(data[i].ip)
  125. data[i].downloadSpeed = speed
  126. bar.Add(1)
  127. }
  128. bar.Finish()
  129. } else {
  130. fmt.Println("\n[信息] IP数量为 0,跳过下载测速。")
  131. }
  132. }
  133. // 直接输出结果
  134. if printResult > 0 { // 如果禁用下载测速就跳过
  135. dateString := convertToString(data) // 转为多维数组 [][]String
  136. if len(dateString) > 0 { // IP数组长度(IP数量) 大于 0 时继续
  137. if len(dateString) < printResult { // 如果IP数组长度(IP数量) 小于 打印次数,则次数改为IP数量
  138. printResult = len(dateString)
  139. fmt.Println("\n[信息] IP数量小于显示结果数量,显示结果数量改为IP数量。\n")
  140. }
  141. fmt.Println("\nIP 地址 \t", "测试次数\t", "成功次数\t", "成功比率\t", "平均延迟\t", "下载速度 (MB/s)")
  142. for i := 0; i < printResult; i++ {
  143. fmt.Println(dateString[i][0], "\t", dateString[i][1], "\t\t", dateString[i][2], "\t\t", dateString[i][3], "\t\t", dateString[i][4], "\t", dateString[i][5])
  144. }
  145. fmt.Printf("\n完整内容请查看 %v 文件。请按 回车键 或 Ctrl+C 退出。", outputFile)
  146. var pause int
  147. fmt.Scanln(&pause)
  148. } else {
  149. fmt.Println("\n[信息] IP数量为 0,跳过输出结果。")
  150. }
  151. }
  152. // 输出结果到文件
  153. ExportCsv(outputFile, data)
  154. }