如何在 Golang 中接受服务器连接或跳出accept()循环

Jen*_*nov 3 go

我需要在 Golang 中实现一个服务器。我正在使用该net包来实现此目的,但我不明白如何优雅地摆脱循环accept

所以看一下包中的示例net

ln, err := net.Listen("tcp", ":8080")
if err != nil {
    // handle error
}
for {
    conn, err := ln.Accept()
    if err != nil {
        // handle error
    }
    go handleConnection(conn)
}
Run Code Online (Sandbox Code Playgroud)

我想做更多的事情:

for {
    select {
    case <-done:
        break
    case conn, err := <-ln.Accept():
    if err != nil {
        break
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

换句话说,我希望能够以某种方式优雅地终止程序。

col*_*tor 7

对于任何服务,确保干净关闭的最佳实践是确保服务的每个部分都支持取消。添加context.Context支持是实现此目的的推荐方法。

因此,首先,确保您的net.Listener连接不会挂在恶意客户端上。因此要添加context.Context支持:

var lc net.ListenConfig

ln, err := lc.Listen(ctx, "tcp", ":8080")
Run Code Online (Sandbox Code Playgroud)

取消ctx将中断此处可能在握手期间阻塞的任何恶意客户端连接。


编辑: 为了确保我们可以在呼叫阻塞等待时中断呼叫Listen(),可以利用相同的ctx状态并(如之前已删除的答案中所述)在检测到取消事件时关闭连接:

go func() {
    <-ctx.Done()
    log.Println("shutting service down...")
    ln.Close()
}()
Run Code Online (Sandbox Code Playgroud)

工作示例: https: //play.golang.org/p/LO1XS4jBQ02