gpt4 book ai didi

concurrency - 在达到超时之前如何读取 UDP 连接?

转载 作者:IT王子 更新时间:2023-10-29 01:16:43 28 4
gpt4 key购买 nike

我需要读取 UDP 流量直到达到超时。我可以通过在 UDPConn 上调用 SetDeadline 并循环直到我收到 I/O 超时错误来执行此操作,但这似乎有点 hack-ish(基于错误条件的流量控制)。下面的代码片段似乎更正确,但并没有终止。在生产中,这显然会在 goroutine 中执行;为了简单起见,它被写成一个主要功能。

package main

import (
"fmt"
"time"
)

func main() {
for {
select {
case <-time.After(time.Second * 1):
fmt.Printf("Finished listening.\n")
return
default:
fmt.Printf("Listening...\n")
//read from UDPConn here
}
}
}

为什么给定的程序没有终止?基于https://gobyexample.com/select , https://gobyexample.com/timeouts , 和 https://gobyexample.com/non-blocking-channel-operations ,我希望上面的代码选择默认情况一秒钟,然后选择第一种情况并跳出循环。我如何修改上面的代码片段以实现循环和读取直到发生超时的预期效果?

最佳答案

如果您不担心超过 n 秒的读取阻塞,则循环直到截止日期:

 deadline := time.Now().Add(n * time.Second)
for time.Now().Before(deadline) {
fmt.Printf("Listening...\n")
//read from UDPConn here
}
fmt.Printf("Finished listening.\n")

如果你确实想在 n 秒后打破阻塞读取,那么设置一个截止日期并读取直到出现错误:

conn.SetReadDeadline(time.Now().Add(n * time.Second)
for {
n, err := conn.Read(buf)
if err != nil {
if e, ok := err.(net.Error); !ok || !e.Timeout() {
// handle error, it's not a timeout
}
break
}
// do something with packet here
}

使用截止日期并不是 hacky。标准库在读取 UDP 连接时使用截止时间(参见 dns client )。

除了使用截止日期来打破阻塞读取之外,还有其他方法:关闭连接或发送读取器可识别的虚拟数据包。这些替代方案需要启动另一个 goroutine,并且比设置截止日期要复杂得多。

关于concurrency - 在达到超时之前如何读取 UDP 连接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26081073/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com