Go语言 如何在`net.Listener`中挂起和恢复接受新连接?

bnl4lu3b  于 2023-06-19  发布在  Go
关注(0)|答案(1)|浏览(128)

通常,你在Go中接受连接是这样的:

l, err := net.Listen("tcp", ":2000")
if err != nil {
  log.Fatal(err)
}

for {
    conn, err := l.Accept() // BLOCKING HERE
    ...
}

我需要一种根据用户输入暂停和恢复for循环的方法。我发现的最接近的是answer,其中接受发生在一个单独的goroutine中,然后conn通过一个通道传递。
但是我不知道如何强制goroutine在挂起时退出,我不想在用户挂起操作时继续接受新的连接。

v7pvogib

v7pvogib1#

基于我所得到的,我把一个小例子,以显示我会怎么做。首先,让我分享代码,然后我会带你通过所有相关的部分。

package main

import (
    "bufio"
    "fmt"
    "log"
    "net"
    "os"
    "strings"
)

func handleConnection(ch chan<- string, c net.Conn) {
    fmt.Println("Serving", c.RemoteAddr().String())
    for {
        netData, err := bufio.NewReader(c).ReadString('\n')
        if err != nil {
            fmt.Println("handleConnection err", err)
            return
        }
        tmp := strings.TrimSpace(string(netData))
        ch <- tmp
        if tmp == "STOP" {
            close(ch)
            break
        }
        fmt.Printf("client: %v writes %q\n", c.RemoteAddr().String(), tmp)
    }
    c.Close()
}

func main() {
    messages := make(chan string)

    listener, err := net.Listen("tcp", ":2000")
    if err != nil {
        log.Fatal(err)
    }
    defer listener.Close()

    go func() {
        for msg := range messages {
            if msg == "STOP" {
                if err := listener.Close(); err != nil {
                    panic(err)
                }
                os.Exit(0)
            }
        }
    }()

    for {
        conn, err := listener.Accept() // BLOCKING HERE
        if err != nil {
            log.Fatal(err)
        }
        go handleConnection(messages, conn)
    }
}

让我们从简单的部分开始,即函数handleConnection

handleConnection函数

这个函数接受一个chan<- string和一个net.Connchan<- string是我们用来写入消息的对象,net.Conn代表了一个到我们监听器的新连接。为了尝试这一点,我从我的终端使用telnet连接。这个函数的作用是:

  • 打印连接的客户端的地址
  • 读取写入连接的内容
  • 发送到频道
  • 检查STOP字是否已写入并最终从函数返回

main函数

这个函数做了几件值得一提的事情:

  • 在端口2000上设置net.Listener
  • 作为一个单独的goroutine运行,一个匿名函数在messages通道上运行
  • 如果已收到STOP,则关闭net.Listener并退出函数
  • 调用Accept方法以侦听传入的TCP客户端连接
  • 当接收到一个新的连接时,它会生成一个新的goroutine,用上面解释的函数来处理它

我希望这能稍微澄清你的问题。如果我没有涵盖的东西,只是让我知道,我会很乐意更新我的答案,谢谢!

相关问题