Concurrency 如何读取UDP连接直到达到超时?
我需要读取UDP流量,直到达到超时。我可以通过在UDPConn上调用setDaildate并循环直到我得到一个I/O超时错误来做到这一点,但这似乎有点黑客行为(基于错误条件的流控制)。下面的代码片段似乎更正确,但没有终止。在生产中,这显然是在一个goroutine中执行的;为了简单起见,它是作为一个主函数编写的Concurrency 如何读取UDP连接直到达到超时?,concurrency,go,network-programming,udp,Concurrency,Go,Network Programming,Udp,我需要读取UDP流量,直到达到超时。我可以通过在UDPConn上调用setDaildate并循环直到我得到一个I/O超时错误来做到这一点,但这似乎有点黑客行为(基于错误条件的流控制)。下面的代码片段似乎更正确,但没有终止。在生产中,这显然是在一个goroutine中执行的;为了简单起见,它是作为一个主函数编写的 package main import ( "fmt" "time" ) func main() { for { select {
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
}
}
}
主程序包
进口(
“fmt”
“时间”
)
func main(){
为了{
挑选{
case只需从时间分配频道。在外的for
循环之后,否则每次循环时只需创建一个新的计时器
例如:
func main() {
ch := time.After(time.Second * 1)
L:
for {
select {
case <-ch:
fmt.Printf("Finished listening.\n")
break L // have to use a label or it will just break select
default:
fmt.Printf("Listening...\n")
//read from UDPConn here
}
}
}
func main(){
ch:=时间后(时间秒*1)
L:
为了{
挑选{
case如果您不担心读阻塞超过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
}
使用截止日期并不难。标准库在读取UDP连接时使用截止日期(请参阅)
除了使用截止日期来中断阻塞读取外,还有其他方法:关闭连接或发送读取器识别的虚拟数据包。这些方法需要启动另一个goroutine,并且比设置截止日期复杂得多。如果将break
更改为return
,则函数将在是的。你现在一直在循环,每秒钟打印一次。@chendesheng我相信时间的使用。After是习惯用法(参见)感谢你们两位对break语句的捕获;我已经更新了代码段。程序仍然没有终止,though@chendesheng我忘了提到:我确实试过使用时间。取而代之的是滴答声,但仍然有无限循环行为。滴答声,这也没用。其中一个答案是正确的。这是有效的!但是为什么有必要?是时间。在为循环的每次迭代计算表达式之后?@cqcallaw是的,您正在为每个循环创建一个新的计时器。有趣。那么为什么此代码按预期运行?请注意“在该示例中,case@cqcallaw会阻塞,直到计时器耗尽或通道返回某个内容,并添加“default”"选择
使其成为非阻塞性的。对特定问题的知识进行了投票。您有没有在标准库中使用截止日期方法的示例?我希望可以将多个答案标记为回答问题!我觉得其中一个答案仍然最接近所问问题的答案,但您的答案是在实践中更有用。感谢您提供详细的问题特定信息。