gpt4 book ai didi

go - Keep-alive:死亡节点检测

转载 作者:数据小太阳 更新时间:2023-10-29 03:33:51 25 4
gpt4 key购买 nike

我在 macOS 本地主机上运行用 Go (1.12) 编写的客户端和套接字服务器。

服务器在 net.TCPConn 上设置 SetKeepAlive 和 SetKeepAlivePeriod。
客户端发送数据包然后关闭连接 (FIN) 或客户端突然终止。

Tcpdump 显示即使在客户端关闭连接后,服务器仍继续发送保持事件探测。
它不应该检测到对等点“死了”并关闭连接吗?

这个问题很笼统,如果我遗漏了一些基础知识,请随时澄清。

package main

import (
"flag"
"fmt"
"net"
"os"
"time"
)

func main() {
var client bool
flag.BoolVar(&client, "client", false, "")
flag.Parse()

if client {
fmt.Println("Client mode")
conn, err := net.Dial("tcp", "127.0.0.1:12345")
checkErr("Dial", err)

written, err := conn.Write([]byte("howdy"))
checkErr("Write", err)

fmt.Printf("Written: %v\n", written)
fmt.Println("Holding conn")

time.Sleep(60 * time.Second)

err = conn.Close()
checkErr("Close", err)

fmt.Println("Closed conn")

return
}

fmt.Println("Server mode")
l, err := net.Listen("tcp", "127.0.0.1:12345")
checkErr("listen", err)
defer l.Close()

for {
c, err := l.Accept()
checkErr("accept", err)
defer c.Close()

tcpConn := c.(*net.TCPConn)
err = tcpConn.SetKeepAlive(true)
checkErr("SetKeepAlive", err)
err = tcpConn.SetKeepAlivePeriod(5 * time.Second)
checkErr("SetKeepAlivePeriod", err)

b := make([]byte, 1024)

n, err := c.Read(b)
checkErr("read", err)

fmt.Printf("Received: %v\n", string(b[:n]))
}
}

func checkErr(location string, err error) {
if err != nil {
fmt.Printf("%v: %v\n", location, err)
os.Exit(-1)
}
}

最佳答案

对该问题的回答:

仅当您需要打开连接但处于空闲状态时才需要发送保活。在这种情况下,存在连接断开的风险,因此 keep alive 将尝试检测断开的连接。

如果您在服务器端使用适当的 con.Close() 关闭连接,则不会触发保持事件状态(您确实将其推迟到主函数的末尾)。

如果您测试您的服务器代码,它将在您设置的超时后开始发送保持事件。

您注意到,只有在所有 keep alive 证明(内核默认为 9)和证明之间的时间(8 倍)之后,您才会在服务器端读取 io.EOF 错误(是的,服务器停止发送)!

目前 Linux 和 OSX 上的 GO 实现是相同的,它将 TCP_KEEPINTVLTCP_KEEPIDLE 设置为您传递给 setKeepAlivePeriod 的值函数,因此,行为将取决于内核版本。

func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
// The kernel expects seconds so round to next highest second.
d += (time.Second - time.Nanosecond)
secs := int(d.Seconds())
if err := fd.pfd.SetsockoptInt(syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, secs); err != nil {
return wrapSyscallError("setsockopt", err)
}
err := fd.pfd.SetsockoptInt(syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, secs)
runtime.KeepAlive(fd)
return wrapSyscallError("setsockopt", err)
}

自 2014 年以来有一个请求打开到 provide a way to set keepalive time and interval separately .

一些引用资料:

关于go - Keep-alive:死亡节点检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56569911/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com