【发布时间】:2019-06-14 08:15:38
【问题描述】:
我在 macOS localhost 上运行用 Go (1.12) 编写的客户端和套接字服务器。
服务器在 net.TCPConn 上设置 SetKeepAlive 和 SetKeepAlivePeriod。
客户端发送一个数据包然后关闭连接(FIN)或客户端突然终止。
Tcpdump 显示即使在客户端关闭连接后,服务器也会继续发送 keep-alive 探测。
它不应该检测到对等体“已死”并关闭连接吗?
这个问题很笼统,如果我缺少一些基本知识,请随时澄清。
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)
}
}
【问题讨论】:
-
请分享一些代码,向我们展示您如何打开和关闭连接以及您的服务器是如何配置的。
-
您永远不会关闭服务器端的连接。
defer c.Close()将在main()返回时运行。 -
@surlac 那你还有什么问题?连接没有关闭,因为您没有关闭它。 “1)它一直发送探针的原因是什么? --- 你没有关闭连接,所以它是打开的并且发送了 keepalive 数据包。 “2)如何在 Go 级别正确终止来自客户端的连接?” --- 双方都应该关闭连接。
-
因为 tcp 就是这样工作的:来自客户端的
FIN表示“我不会发送任何东西但仍然可以接收” -
@surlac “这与保持活动的目的相矛盾”——事实并非如此。你观察到的东西“按设计”工作。
标签: go keep-alive tcp-keepalive