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

问题描述:

我需要读取UDP通信,直到达到超时为止.我可以通过在UDPConn上调用SetDeadline并循环直到出现I/O超时错误来做到这一点,但这似乎有些破绽(基于错误条件的流控制).以下代码段似乎更正确,但不会终止.在生产中,这显然将在goroutine中执行;为了简单起见,它被写为主要功能.

I need to read UDP traffic until a timeout is reached. I can do this by calling SetDeadline on the UDPConn and looping until I get an I/O timeout error, but this seems hack-ish (flow control based on error conditions). The following code snippet seems more correct, but does not terminate. In production, this would obviously be executed in a goroutine; it's written as a main function for simplicity's sake.

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 ,我希望上面的代码能选择一秒钟的默认大小写,然后采用第一种情况并跳出循环.我如何修改上面的代码片段,以达到预期的循环读取效果,直到发生超时?

Why doesn't the given program terminate? Based on https://gobyexample.com/select, https://gobyexample.com/timeouts, and https://gobyexample.com/non-blocking-channel-operations, I would expect the above code to select the default case for one second, then take the first case and break out of the loop. How might I modify the above snippet to achieve the desired effect of looping and reading until a timeout occurs?

只需在for循环之外的time.After中分配通道,否则每次循环时您将只创建一个新计时器.

Simply assign the channel from time.After outside the for loop, otherwise you will just create a new timer each time you loop.

示例:

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
        }
    }
}

请注意,这在操场上不起作用.

Note that this doesn't work on the playground.