CloudflareSpeedTest/utils/csv.go

188 lines
4.9 KiB
Go
Raw Normal View History

2021-11-09 18:44:17 +08:00
package utils
import (
"encoding/csv"
2021-11-10 17:12:12 +08:00
"fmt"
2021-11-09 18:44:17 +08:00
"log"
"net"
"os"
"strconv"
"time"
)
2021-11-10 23:58:40 +08:00
const (
2023-05-31 16:46:16 +08:00
defaultOutput = "result.csv"
maxDelay = 9999 * time.Millisecond
minDelay = 0 * time.Millisecond
maxLossRate float32 = 1.0
2021-11-10 23:58:40 +08:00
)
2021-11-10 17:12:12 +08:00
2021-11-10 12:25:10 +08:00
var (
2023-05-31 16:46:16 +08:00
InputMaxDelay = maxDelay
InputMinDelay = minDelay
InputMaxLossRate = maxLossRate
Output = defaultOutput
PrintNum = 10
2021-11-10 12:25:10 +08:00
)
2021-11-14 12:59:46 +08:00
// 是否打印测试结果
2021-11-14 12:47:57 +08:00
func NoPrintResult() bool {
return PrintNum == 0
}
2021-11-14 12:59:46 +08:00
// 是否输出到文件
func noOutput() bool {
return Output == "" || Output == " "
}
2021-11-09 23:39:42 +08:00
type PingData struct {
2021-11-10 18:47:21 +08:00
IP *net.IPAddr
2021-11-10 12:25:10 +08:00
Sended int
2021-11-09 23:39:42 +08:00
Received int
Delay time.Duration
}
2021-11-09 18:44:17 +08:00
type CloudflareIPData struct {
2021-11-09 23:39:42 +08:00
*PingData
2023-05-31 16:46:16 +08:00
lossRate float32
2021-11-10 17:12:12 +08:00
DownloadSpeed float64
2021-11-09 18:44:17 +08:00
}
2023-05-31 16:46:16 +08:00
// 计算丢包率
func (cf *CloudflareIPData) getLossRate() float32 {
if cf.lossRate == 0 {
2021-11-10 12:25:10 +08:00
pingLost := cf.Sended - cf.Received
2023-05-31 16:46:16 +08:00
cf.lossRate = float32(pingLost) / float32(cf.Sended)
2021-11-09 18:44:17 +08:00
}
2023-05-31 16:46:16 +08:00
return cf.lossRate
2021-11-09 18:44:17 +08:00
}
2021-11-10 12:25:10 +08:00
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)
2023-05-31 16:46:16 +08:00
result[3] = strconv.FormatFloat(float64(cf.getLossRate()), 'f', 2, 32)
2021-11-13 16:49:47 +08:00
result[4] = strconv.FormatFloat(cf.Delay.Seconds()*1000, 'f', 2, 32)
2021-11-10 17:12:12 +08:00
result[5] = strconv.FormatFloat(cf.DownloadSpeed/1024/1024, 'f', 2, 32)
2021-11-10 12:25:10 +08:00
return result
}
2021-11-10 17:12:12 +08:00
func ExportCsv(data []CloudflareIPData) {
2021-11-14 12:59:46 +08:00
if noOutput() || len(data) == 0 {
2021-11-12 11:58:21 +08:00
return
}
2021-11-10 17:12:12 +08:00
fp, err := os.Create(Output)
2021-11-09 18:44:17 +08:00
if err != nil {
2021-11-10 17:12:12 +08:00
log.Fatalf("创建文件[%s]失败:%v", Output, err)
2021-11-09 18:44:17 +08:00
return
}
defer fp.Close()
w := csv.NewWriter(fp) //创建一个新的写入文件流
2021-11-14 12:59:46 +08:00
_ = w.Write([]string{"IP 地址", "已发送", "已接收", "丢包率", "平均延迟", "下载速度 (MB/s)"})
_ = w.WriteAll(convertToString(data))
2021-11-09 18:44:17 +08:00
w.Flush()
}
func convertToString(data []CloudflareIPData) [][]string {
result := make([][]string, 0)
for _, v := range data {
result = append(result, v.toString())
}
return result
}
2021-11-10 12:25:10 +08:00
2023-05-31 16:46:16 +08:00
// 延迟丢包排序
2021-11-10 12:25:10 +08:00
type PingDelaySet []CloudflareIPData
2023-05-31 16:46:16 +08:00
// 延迟条件过滤
2021-11-10 12:25:10 +08:00
func (s PingDelaySet) FilterDelay() (data PingDelaySet) {
if InputMaxDelay > maxDelay || InputMinDelay < minDelay { // 当输入的延迟条件不在默认范围内时,不进行过滤
return s
}
if InputMaxDelay == maxDelay && InputMinDelay == minDelay { // 当输入的延迟条件为默认值时,不进行过滤
2021-11-10 12:25:10 +08:00
return s
}
for _, v := range s {
2023-05-31 16:46:16 +08:00
if v.Delay > InputMaxDelay { // 平均延迟上限,延迟大于条件最大值时,后面的数据都不满足条件,直接跳出循环
2021-11-10 12:25:10 +08:00
break
}
2023-05-31 16:46:16 +08:00
if v.Delay < InputMinDelay { // 平均延迟下限,延迟小于条件最小值时,不满足条件,跳过
2021-11-10 12:25:10 +08:00
continue
}
data = append(data, v) // 延迟满足条件时,添加到新数组中
}
return
}
2023-05-31 16:46:16 +08:00
// 丢包条件过滤
func (s PingDelaySet) FilterLossRate() (data PingDelaySet) {
if InputMaxLossRate >= maxLossRate { // 当输入的丢包条件为默认值时,不进行过滤
return s
}
for _, v := range s {
if v.getLossRate() > InputMaxLossRate { // 丢包几率上限
break
}
data = append(data, v) // 丢包率满足条件时,添加到新数组中
}
return
}
2021-11-10 12:25:10 +08:00
func (s PingDelaySet) Len() int {
return len(s)
}
func (s PingDelaySet) Less(i, j int) bool {
2023-05-31 16:46:16 +08:00
iRate, jRate := s[i].getLossRate(), s[j].getLossRate()
2021-11-10 12:25:10 +08:00
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 {
2021-11-10 17:12:12 +08:00
return s[i].DownloadSpeed > s[j].DownloadSpeed
2021-11-10 12:25:10 +08:00
}
func (s DownloadSpeedSet) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
2021-11-10 17:12:12 +08:00
func (s DownloadSpeedSet) Print() {
2021-11-14 12:47:57 +08:00
if NoPrintResult() {
return
}
2021-11-10 17:12:12 +08:00
if len(s) <= 0 { // IP数组长度(IP数量) 大于 0 时继续
fmt.Println("\n[信息] 完整测速结果 IP 数量为 0跳过输出结果。")
return
}
dateString := convertToString(s) // 转为多维数组 [][]String
if len(dateString) < PrintNum { // 如果IP数组长度(IP数量) 小于 打印次数则次数改为IP数量
PrintNum = len(dateString)
}
headFormat := "%-16s%-5s%-5s%-5s%-6s%-11s\n"
2021-11-13 16:49:47 +08:00
dataFormat := "%-18s%-8s%-8s%-8s%-10s%-15s\n"
for i := 0; i < PrintNum; i++ { // 如果要输出的 IP 中包含 IPv6那么就需要调整一下间隔
if len(dateString[i][0]) > 15 {
headFormat = "%-40s%-5s%-5s%-5s%-6s%-11s\n"
dataFormat = "%-42s%-8s%-8s%-8s%-10s%-15s\n"
break
}
2021-11-10 17:12:12 +08:00
}
fmt.Printf(headFormat, "IP 地址", "已发送", "已接收", "丢包率", "平均延迟", "下载速度 (MB/s)")
for i := 0; i < PrintNum; i++ {
fmt.Printf(dataFormat, dateString[i][0], dateString[i][1], dateString[i][2], dateString[i][3], dateString[i][4], dateString[i][5])
}
2021-11-14 12:59:46 +08:00
if !noOutput() {
2021-11-17 15:40:53 +08:00
fmt.Printf("\n完整测速结果已写入 %v 文件,可使用记事本/表格软件查看。\n", Output)
2021-11-14 12:59:46 +08:00
}
2021-11-10 23:58:40 +08:00
}