如果连接没有每秒收到响应,我该如何使 TCP 连接超时?

我正在尝试创建一个 TCP 服务器,如果客户端在每秒的范围内没有响应,它将超时。


我试过了:


func main() {

    listener, err := net.Listen("tcp", "localhost:8000")

    if err != nil {

        log.Fatal(err)

    }

    for {

        conn, err := listener.Accept()

        conn.SetDeadline(time.Now().Add(timeout))

        if err != nil {

            log.Print(err)

        }

        go handleConn(conn)

    }


}

超时是一秒钟但立即断开连接,甚至不等待回复。


繁花如伊
浏览 108回答 2
2回答

茅侃侃

您可以通过在侦听器上设置套接字选项来实现您想要的。根据您的需要调整值请注意,这是它自己的 KeepAlive,不依赖于应用程序的传入/传出数据func enableTCPKeepAlive(listener *net.TCPListener) error {    rawConn, err := listener.SyscallConn()    if err != nil {        return err    }    cfg := config.TLSServerConfig()    rawConn.Control(        func(fdPtr uintptr) {            // got socket file descriptor. Setting parameters.            fd := int(fdPtr)            //Idle time before sending probe.            err = syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, cfg.TCPKAIdleTime)            if err != nil {                return err            }            //Number of probes.            err := syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPCNT, cfg.TCPKANumProbes)            if err != nil {                return err            }            //Wait time after an unsuccessful probe.            err = syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, cfg.TCPKAInterval)            if err != nil {                return err            }            // go syscall doesn't have the constant 0x12 (18) for TCP_USER_TIMEOUT.            // 0x12 value referenced from linux kernel source code header:            // include/uapi/linux/tcp.h            err = syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, 0x12, cfg.TCPKAUserTimeout)            if err != nil {                return err            }        })    return nil}可用的选项比我上面提到的要多。在 for 循环之前在您的侦听器上调用此函数。func main() {    listener, err := net.Listen("tcp", "localhost:8000")    if err != nil {        log.Fatal(err)    }    err = enableTCPKeepAlive(listener)    if err != nil {        log.Fatal(err)    }    for {        conn, err := listener.Accept()        conn.SetDeadline(time.Now().Add(timeout))        if err != nil {            log.Print(err)        }        go handleConn(conn)    }}

12345678_0001

问题几乎总是出在未在此处发布的代码中。该功能显然很有魅力:package mainimport (&nbsp; &nbsp; "crypto/rand"&nbsp; &nbsp; "log"&nbsp; &nbsp; "net"&nbsp; &nbsp; "time")func main() {&nbsp; &nbsp; listener, err := net.Listen("tcp", "localhost:8000")&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; log.Fatal(err)&nbsp; &nbsp; }&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; conn, err := listener.Accept()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Print(err)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; go func(c net.Conn) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; defer c.Close()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; conn.SetDeadline(time.Now().Add(2 * time.Second))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Print(err)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buf := make([]byte, 1<<19) // 512 KB&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _, err := conn.Read(buf)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Print(err)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }(conn)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }()payload := make([]byte, 1<<20)_, err = rand.Read(payload) // generate a random payloadif err != nil {&nbsp; &nbsp; log.Print(err)}conn, err := net.Dial("tcp", listener.Addr().String())if err != nil {&nbsp; &nbsp; log.Fatal(err)}log.Println("Connected to server.")time.Sleep(5 * time.Second)_, err = conn.Write(payload)if err != nil {&nbsp; &nbsp; log.Print(err)}listener.Close()}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go