rebuild tcping
This commit is contained in:
parent
6f74e60444
commit
83c63e975e
123
tcping.go
123
tcping.go
|
@ -2,10 +2,10 @@ package main
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
|
@ -13,30 +13,24 @@ import (
|
|||
)
|
||||
|
||||
//bool connectionSucceed float32 time
|
||||
func tcping(ip net.IPAddr, tcpPort int) (bool, float32) {
|
||||
func tcping(ip net.IPAddr, tcpPort int) (bool, time.Duration) {
|
||||
startTime := time.Now()
|
||||
var fullAddress string
|
||||
fullAddress := fmt.Sprintf("%s:%d", ip.String(), tcpPort)
|
||||
//fmt.Println(ip.String())
|
||||
if ipv6Mode { // IPv6 需要加上 []
|
||||
fullAddress = "[" + ip.String() + "]:" + strconv.Itoa(tcpPort)
|
||||
} else {
|
||||
fullAddress = ip.String() + ":" + strconv.Itoa(tcpPort)
|
||||
fullAddress = fmt.Sprintf("[%s]:%d", ip.String(), tcpPort)
|
||||
}
|
||||
conn, err := net.DialTimeout("tcp", fullAddress, tcpConnectTimeout)
|
||||
if err != nil {
|
||||
return false, 0
|
||||
} else {
|
||||
var endTime = time.Since(startTime)
|
||||
var duration = float32(endTime.Microseconds()) / 1000.0
|
||||
_ = conn.Close()
|
||||
return true, duration
|
||||
}
|
||||
defer conn.Close()
|
||||
duration := time.Since(startTime)
|
||||
return true, duration
|
||||
}
|
||||
|
||||
//pingReceived pingTotalTime
|
||||
func checkConnection(ip net.IPAddr, tcpPort int) (int, float32) {
|
||||
pingRecv := 0
|
||||
var pingTime float32 = 0.0
|
||||
func checkConnection(ip net.IPAddr, tcpPort int) (pingRecv int, pingTime time.Duration) {
|
||||
for i := 1; i <= failTime; i++ {
|
||||
pingSucceed, pingTimeCurrent := tcping(ip, tcpPort)
|
||||
if pingSucceed {
|
||||
|
@ -44,14 +38,14 @@ func checkConnection(ip net.IPAddr, tcpPort int) (int, float32) {
|
|||
pingTime += pingTimeCurrent
|
||||
}
|
||||
}
|
||||
return pingRecv, pingTime
|
||||
return
|
||||
}
|
||||
|
||||
//return Success packetRecv averagePingTime specificIPAddr
|
||||
func tcpingHandler(ip net.IPAddr, tcpPort int, pingCount int, progressHandler func(e progressEvent)) (bool, int, float32, net.IPAddr) {
|
||||
func tcpingHandler(ip net.IPAddr, tcpPort, pingCount int, progressHandler func(e progressEvent)) (bool, int, time.Duration, net.IPAddr) {
|
||||
ipCanConnect := false
|
||||
pingRecv := 0
|
||||
var pingTime float32 = 0.0
|
||||
var pingTime time.Duration
|
||||
for !ipCanConnect {
|
||||
pingRecvCurrent, pingTimeCurrent := checkConnection(ip, tcpPort)
|
||||
if pingRecvCurrent != 0 {
|
||||
|
@ -66,21 +60,20 @@ func tcpingHandler(ip net.IPAddr, tcpPort int, pingCount int, progressHandler fu
|
|||
break
|
||||
}
|
||||
}
|
||||
if ipCanConnect {
|
||||
progressHandler(AvailableIPFound)
|
||||
for i := failTime; i < pingCount; i++ {
|
||||
pingSuccess, pingTimeCurrent := tcping(ip, tcpPort)
|
||||
progressHandler(NormalPing)
|
||||
if pingSuccess {
|
||||
pingRecv++
|
||||
pingTime += pingTimeCurrent
|
||||
}
|
||||
}
|
||||
return true, pingRecv, pingTime / float32(pingRecv), ip
|
||||
} else {
|
||||
if !ipCanConnect {
|
||||
progressHandler(NoAvailableIPFound)
|
||||
return false, 0, 0, net.IPAddr{}
|
||||
}
|
||||
progressHandler(AvailableIPFound)
|
||||
for i := failTime; i < pingCount; i++ {
|
||||
pingSuccess, pingTimeCurrent := tcping(ip, tcpPort)
|
||||
progressHandler(NormalPing)
|
||||
if pingSuccess {
|
||||
pingRecv++
|
||||
pingTime += pingTimeCurrent
|
||||
}
|
||||
}
|
||||
return true, pingRecv, pingTime / time.Duration(pingRecv), ip
|
||||
}
|
||||
|
||||
func tcpingGoroutine(wg *sync.WaitGroup, mutex *sync.Mutex, ip net.IPAddr, tcpPort int, pingCount int, csv *[]CloudflareIPData, control chan bool, progressHandler func(e progressEvent)) {
|
||||
|
@ -126,47 +119,47 @@ func DownloadSpeedHandler(ip net.IPAddr) (bool, float32) {
|
|||
response, err := client.Get(url)
|
||||
if err != nil {
|
||||
return false, 0
|
||||
} else {
|
||||
defer func() { _ = response.Body.Close() }()
|
||||
if response.StatusCode == 200 {
|
||||
timeStart := time.Now()
|
||||
timeEnd := timeStart.Add(downloadTestTime)
|
||||
}
|
||||
defer response.Body.Close()
|
||||
if response.StatusCode != 200 {
|
||||
return false, 0
|
||||
}
|
||||
timeStart := time.Now()
|
||||
timeEnd := timeStart.Add(downloadTestTime)
|
||||
|
||||
contentLength := response.ContentLength
|
||||
buffer := make([]byte, downloadBufferSize)
|
||||
contentLength := response.ContentLength
|
||||
buffer := make([]byte, downloadBufferSize)
|
||||
|
||||
var contentRead int64 = 0
|
||||
var timeSlice = downloadTestTime / 100
|
||||
var timeCounter = 1
|
||||
var lastContentRead int64 = 0
|
||||
var (
|
||||
contentRead int64 = 0
|
||||
timeSlice = downloadTestTime / 100
|
||||
timeCounter = 1
|
||||
lastContentRead int64 = 0
|
||||
)
|
||||
|
||||
var nextTime = timeStart.Add(timeSlice * time.Duration(timeCounter))
|
||||
e := ewma.NewMovingAverage()
|
||||
var nextTime = timeStart.Add(timeSlice * time.Duration(timeCounter))
|
||||
e := ewma.NewMovingAverage()
|
||||
|
||||
for contentLength != contentRead {
|
||||
var currentTime = time.Now()
|
||||
if currentTime.After(nextTime) {
|
||||
timeCounter += 1
|
||||
nextTime = timeStart.Add(timeSlice * time.Duration(timeCounter))
|
||||
e.Add(float64(contentRead - lastContentRead))
|
||||
lastContentRead = contentRead
|
||||
}
|
||||
if currentTime.After(timeEnd) {
|
||||
break
|
||||
}
|
||||
bufferRead, err := response.Body.Read(buffer)
|
||||
contentRead += int64(bufferRead)
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
break
|
||||
} else {
|
||||
e.Add(float64(contentRead-lastContentRead) / (float64(nextTime.Sub(currentTime)) / float64(timeSlice)))
|
||||
}
|
||||
}
|
||||
for contentLength != contentRead {
|
||||
var currentTime = time.Now()
|
||||
if currentTime.After(nextTime) {
|
||||
timeCounter++
|
||||
nextTime = timeStart.Add(timeSlice * time.Duration(timeCounter))
|
||||
e.Add(float64(contentRead - lastContentRead))
|
||||
lastContentRead = contentRead
|
||||
}
|
||||
if currentTime.After(timeEnd) {
|
||||
break
|
||||
}
|
||||
bufferRead, err := response.Body.Read(buffer)
|
||||
contentRead += int64(bufferRead)
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
break
|
||||
}
|
||||
return true, float32(e.Value()) / (float32(downloadTestTime.Seconds()) / 120)
|
||||
} else {
|
||||
return false, 0
|
||||
e.Add(float64(contentRead-lastContentRead) / (float64(nextTime.Sub(currentTime)) / float64(timeSlice)))
|
||||
}
|
||||
}
|
||||
return true, float32(e.Value()) / (float32(downloadTestTime.Seconds()) / 120)
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package tcping
|
||||
|
||||
import (
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"CloudflareSpeedTest/utils"
|
||||
)
|
||||
|
||||
type Tcp struct {
|
||||
wg *sync.WaitGroup
|
||||
mutex *sync.Mutex
|
||||
ip net.IPAddr
|
||||
tcpPort int
|
||||
pingCount int
|
||||
csv *[]utils.CloudflareIPData
|
||||
control chan bool
|
||||
progressHandler func(e utils.ProgressEvent)
|
||||
}
|
6
util.go
6
util.go
|
@ -18,7 +18,7 @@ type CloudflareIPData struct {
|
|||
pingReceived int
|
||||
recvRate float32
|
||||
downloadSpeed float32
|
||||
pingTime float32
|
||||
pingTime time.Duration
|
||||
}
|
||||
|
||||
func (cf *CloudflareIPData) getRecvRate() float32 {
|
||||
|
@ -32,7 +32,7 @@ func (cf *CloudflareIPData) getRecvRate() float32 {
|
|||
func ExportCsv(filePath string, data []CloudflareIPData) {
|
||||
fp, err := os.Create(filePath)
|
||||
if err != nil {
|
||||
log.Fatalf("创建文件["+filePath+"]句柄失败,%v", err)
|
||||
log.Fatalf("创建文件[%s]失败:%v", filePath, err)
|
||||
return
|
||||
}
|
||||
defer fp.Close()
|
||||
|
@ -48,7 +48,7 @@ func (cf *CloudflareIPData) toString() []string {
|
|||
result[1] = strconv.Itoa(cf.pingCount)
|
||||
result[2] = strconv.Itoa(cf.pingReceived)
|
||||
result[3] = strconv.FormatFloat(float64(cf.getRecvRate()), 'f', 2, 32)
|
||||
result[4] = strconv.FormatFloat(float64(cf.pingTime), 'f', 2, 32)
|
||||
result[4] = cf.pingTime.String()
|
||||
result[5] = strconv.FormatFloat(float64(cf.downloadSpeed)/1024/1024, 'f', 2, 32)
|
||||
return result
|
||||
}
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"encoding/csv"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type CloudflareIPData struct {
|
||||
ip net.IPAddr
|
||||
pingCount int
|
||||
pingReceived int
|
||||
recvRate float32
|
||||
downloadSpeed float32
|
||||
pingTime time.Duration
|
||||
}
|
||||
|
||||
func (cf *CloudflareIPData) getRecvRate() float32 {
|
||||
if cf.recvRate == 0 {
|
||||
pingLost := cf.pingCount - cf.pingReceived
|
||||
cf.recvRate = float32(pingLost) / float32(cf.pingCount)
|
||||
}
|
||||
return cf.recvRate
|
||||
}
|
||||
|
||||
func ExportCsv(filePath string, data []CloudflareIPData) {
|
||||
fp, err := os.Create(filePath)
|
||||
if err != nil {
|
||||
log.Fatalf("创建文件[%s]失败:%v", filePath, err)
|
||||
return
|
||||
}
|
||||
defer fp.Close()
|
||||
w := csv.NewWriter(fp) //创建一个新的写入文件流
|
||||
w.Write([]string{"IP 地址", "已发送", "已接收", "丢包率", "平均延迟", "下载速度 (MB/s)"})
|
||||
w.WriteAll(convertToString(data))
|
||||
w.Flush()
|
||||
}
|
||||
|
||||
func (cf *CloudflareIPData) toString() []string {
|
||||
result := make([]string, 6)
|
||||
result[0] = cf.ip.String()
|
||||
result[1] = strconv.Itoa(cf.pingCount)
|
||||
result[2] = strconv.Itoa(cf.pingReceived)
|
||||
result[3] = strconv.FormatFloat(float64(cf.getRecvRate()), 'f', 2, 32)
|
||||
result[4] = cf.pingTime.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 {
|
||||
result = append(result, v.toString())
|
||||
}
|
||||
return result
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package utils
|
||||
|
||||
type ProgressEvent int
|
||||
|
||||
const (
|
||||
NoAvailableIPFound ProgressEvent = iota
|
||||
AvailableIPFound
|
||||
NormalPing
|
||||
)
|
Loading…
Reference in New Issue