请教关闭TCP监听时的争用问题

visli · 2022-11-30 08:52:17 · 2570 次点击
buscoop
纸上得来终觉浅,绝知此事要躬行!

那最终方案是什么

#13
更多评论
jan-bar
想要拥有,必定付出。

我的写法核心就是让Accept()操作设置超时时间,保证可以执行其他代码。

或者关闭代码就在你的程序里面模拟tcp连接发送特殊字符,然后服务端收到特殊字符就走退出逻辑。

package main

import (
    "context"
    "log"
    "net"
    "os"
    "os/signal"
    "syscall"
    "time"
)

// tcp服务
func tcpServer(ctx context.Context) {
    addr, err := net.ResolveTCPAddr("tcp4", ":6666")
    if err != nil {
        log.Fatalln(err)
    }
    listener, err := net.ListenTCP("tcp4", addr)
    if err != nil {
        log.Fatalln(err)
    }

    for {
        select {
        case <-ctx.Done():
            err = listener.Close()
            if err != nil {
                log.Fatalln(err)
            }
            return
        default:
            // 控制超时时间,让代码有机会执行ctx.Done()
            _ = listener.SetDeadline(time.Now().Add(time.Second))
            c, err := listener.AcceptTCP()
            if err != nil {
                if opErr, ok := err.(*net.OpError); ok {
                    if opErr.Timeout() {
                        continue
                    }
                    if opErr.Err == net.ErrClosed {
                        log.Println("listener closed")
                        return
                    }
                }
                log.Println(err)
                continue
            }
            connHandler(c)
        }
    }
}

// 新连接处理
func connHandler(c *net.TCPConn) {
    defer func() {
        c.Close()
        log.Printf("%s closed", c.RemoteAddr().String())
    }()
    log.Printf("New connection: %s", c.RemoteAddr().String())
    buf := make([]byte, 128)
    for {
        n, err := c.Read(buf)
        if err != nil {
            return
        }
        log.Println(buf[:n])
    }
}

func main() {
    sigs := make(chan os.Signal, 1)
    signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
    ctx, cancel := context.WithCancel(context.Background())
    go tcpServer(ctx)
    <-sigs
    cancel()
    time.Sleep(time.Millisecond * 200)
}
#1

@jan-bar 谢谢。目前只有这个办法了。

#2