Golang网络拨号相关问题探讨
Golang网络拨号相关问题探讨 我编写了一个测试连接时间的工具,但发现很多连接时间存在错误。 我看到很多连接时间大于最小时间限制,但抓包分析显示实际时间是正常的。 我不清楚问题出在哪里。 有人能帮我看看吗? 我的代码如下:
func main() {
var wg sync.WaitGroup
chV, chR := peashooter.Start(config.Config(), &wg)
wg.Wait()
func Start(config *config.GlobalConfig, wg *sync.WaitGroup) (chan time.Duration, chan time.Duration) {
vAddr := net.JoinHostPort(config.Vip, config.VipPort)
rAddr := net.JoinHostPort(config.Rip, config.RipPort)
chV := make(chan time.Duration, config.PacketCounter)
chR := make(chan time.Duration, config.PacketCounter)
chLimit := make(chan int, config.PackLimit)
timeout := time.Second * time.Duration(config.Timeout)
timemin := time.Second * time.Duration(config.TimeoutMin)
for i := 0; i < config.PacketCounter; i++ {
wg.Add(1)
go shooter(config.PacketType, vAddr, timeout, timemin, chLimit, chV, wg)
}
for i := 0; i < config.PacketCounter; i++ {
wg.Add(1)
go shooter(config.PacketType, rAddr, timeout, timemin, chLimit, chR, wg)
}
return chV, chR
func shooter(QType string, vAddr string, timeout time.Duration, timemin time.Duration, ChLimit chan int, ch chan time.Duration, wg *sync.WaitGroup) {
ChLimit <- 1
defer wg.Done()
start := time.Now()
conn, err := net.DialTimeout(QType, vAddr, timeout)
if err != nil {
fmt.Println(err.Error())
<-ChLimit
return
}
defer conn.Close()
t := time.Now()
elapsed := t.Sub(start)
if elapsed.Seconds() > timemin.Seconds() {
fmt.Println(conn.LocalAddr())
}
ch <- elapsed
<-ChLimit
更多关于Golang网络拨号相关问题探讨的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于Golang网络拨号相关问题探讨的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
问题可能出现在时间比较的逻辑上。在Go语言中,直接比较time.Duration的Seconds()方法返回的浮点数可能导致精度问题。timemin.Seconds()返回的是float64类型,而浮点数比较在边界情况下可能不准确。
更可靠的方式是直接比较time.Duration值:
func shooter(QType string, vAddr string, timeout time.Duration, timemin time.Duration, ChLimit chan int, ch chan time.Duration, wg *sync.WaitGroup) {
ChLimit <- 1
defer wg.Done()
start := time.Now()
conn, err := net.DialTimeout(QType, vAddr, timeout)
if err != nil {
fmt.Println(err.Error())
<-ChLimit
return
}
defer conn.Close()
elapsed := time.Since(start)
// 直接比较time.Duration,而不是比较Seconds()的返回值
if elapsed > timemin {
fmt.Printf("连接超时: %v, 本地地址: %v\n", elapsed, conn.LocalAddr())
}
ch <- elapsed
<-ChLimit
}
另外,确保在main函数中正确读取channel中的数据,否则可能影响计时准确性:
func main() {
var wg sync.WaitGroup
chV, chR := peashooter.Start(config.Config(), &wg)
wg.Wait()
// 读取channel中的数据
close(chV)
close(chR)
for v := range chV {
fmt.Printf("VIP连接时间: %v\n", v)
}
for r := range chR {
fmt.Printf("RIP连接时间: %v\n", r)
}
}
在Start函数中,建议在返回channel前启动goroutine来关闭channel:
func Start(config *config.GlobalConfig, wg *sync.WaitGroup) (chan time.Duration, chan time.Duration) {
vAddr := net.JoinHostPort(config.Vip, config.VipPort)
rAddr := net.JoinHostPort(config.Rip, config.RipPort)
chV := make(chan time.Duration, config.PacketCounter)
chR := make(chan time.Duration, config.PacketCounter)
chLimit := make(chan int, config.PackLimit)
timeout := time.Second * time.Duration(config.Timeout)
timemin := time.Second * time.Duration(config.TimeoutMin)
for i := 0; i < config.PacketCounter; i++ {
wg.Add(1)
go shooter(config.PacketType, vAddr, timeout, timemin, chLimit, chV, wg)
}
for i := 0; i < config.PacketCounter; i++ {
wg.Add(1)
go shooter(config.PacketType, rAddr, timeout, timemin, chLimit, chR, wg)
}
// 等待所有goroutine完成后关闭channel
go func() {
wg.Wait()
close(chV)
close(chR)
}()
return chV, chR
}
这样修改后,时间比较会更加准确,并且channel的处理也会更加规范。

