Concurrency 如何读取UDP连接直到达到超时?

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 {

我需要读取UDP流量,直到达到超时。我可以通过在UDPConn上调用setDaildate并循环直到我得到一个I/O超时错误来做到这一点,但这似乎有点黑客行为(基于错误条件的流控制)。下面的代码片段似乎更正确,但没有终止。在生产中,这显然是在一个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
        }
    }
}
主程序包
进口(
“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”"选择
使其成为非阻塞性的。对特定问题的知识进行了投票。您有没有在标准库中使用截止日期方法的示例?我希望可以将多个答案标记为回答问题!我觉得其中一个答案仍然最接近所问问题的答案,但您的答案是在实践中更有用。感谢您提供详细的问题特定信息。