茅侃侃
您可以通过在侦听器上设置套接字选项来实现您想要的。根据您的需要调整值请注意,这是它自己的 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 ( "crypto/rand" "log" "net" "time")func main() { listener, err := net.Listen("tcp", "localhost:8000") if err != nil { log.Fatal(err) } go func() { for { conn, err := listener.Accept() if err != nil { log.Print(err) return } go func(c net.Conn) { defer c.Close() conn.SetDeadline(time.Now().Add(2 * time.Second)) if err != nil { log.Print(err) return } buf := make([]byte, 1<<19) // 512 KB for { _, err := conn.Read(buf) if err != nil { log.Print(err) break } } }(conn) } }()payload := make([]byte, 1<<20)_, err = rand.Read(payload) // generate a random payloadif err != nil { log.Print(err)}conn, err := net.Dial("tcp", listener.Addr().String())if err != nil { log.Fatal(err)}log.Println("Connected to server.")time.Sleep(5 * time.Second)_, err = conn.Write(payload)if err != nil { log.Print(err)}listener.Close()}