前文中已经介绍了TCP keep alive的做了详尽说明,本文结合golang,介绍如何使用TCP keep alive。
目前golang net包不提供TCP keep alive 空闲多长时间开始探测
、 探测总次数
直接设置。
可以使用第三方包。
1.下载第三方包
git clone git@github.com:felixge/tcpkeepalive.git
注意放到GOPATH
目录下。
2.例子
2.1 server
server端,接受client连接请求,建立连接后,设置连接的空闲多长时间开始探测
、探测时间间隔
、探测总次数
。
本例中,我们设置的参数如下:
空闲多长时间开始探测
keepAliveIdle
: 10s探测时间间隔
keepAliveInterval
: 10s探测总次数
keepAliveCount
:9
server端发送一次数据后,停住。等待10s,开始发送tcp keep alive.
server 代码如下:
package main import ( "net" "log" "time" "github.com/tcpkeepalive" ) func main() { addr := "0.0.0.0:8080" tcpAddr, err := net.ResolveTCPAddr("tcp",addr) if err != nil { log.Fatalf("net.ResovleTCPAddr fail:%s", addr) } listener, err := net.ListenTCP("tcp", tcpAddr) if err != nil { log.Fatalf("listen %s fail: %s", addr, err) } else { log.Println("rpc listening", addr) } for { conn, err := listener.Accept() if err != nil { log.Println("listener.Accept error:", err) continue } go handleConnection(conn) } } func setTcpKeepAlive(conn net.Conn) (*tcpkeepalive.Conn, error) { newConn, err := tcpkeepalive.EnableKeepAlive(conn) if err != nil { log.Println("EnableKeepAlive failed:", err) return nil, err } err = newConn.SetKeepAliveIdle(10*time.Second) if err != nil { log.Println("SetKeepAliveIdle failed:", err) return nil, err } err = newConn.SetKeepAliveCount(9) if err != nil { log.Println("SetKeepAliveCount failed:", err) return nil, err } err = newConn.SetKeepAliveInterval(10*time.Second) if err != nil { log.Println("SetKeepAliveInterval failed:", err) return nil, err } return newConn, nil } func handleConnection(conn net.Conn) { defer conn.Close() newConn, err := setTcpKeepAlive(conn) if err != nil { log.Println("setTcpKeepAlive failed:", err) return } var buffer []byte = []byte("You are welcome. I'm server.") for { time.Sleep(1*time.Second) n, err := newConn.Write(buffer) if err != nil { log.Println("Write error:", err) break } log.Println("send:", n) select{} } log.Println("connetion end") }
2.2 client
client端很简单,负责接收数据。
package main import ( "fmt" "net" "os" ) func main() { conn, err := net.Dial("tcp", "127.0.0.1:8080") if err != nil { fmt.Println("dial failed:", err) os.Exit(1) } defer conn.Close() buffer := make([]byte, 512) for { n, err := conn.Read(buffer) if err != nil { fmt.Println("Read failed:", err) return } fmt.Println("count:", n, "msg:", string(buffer)) } }
3.查看结果
server输出
019/05/26 22:22:00 rpc listening 0.0.0.0:8080 2019/05/26 22:22:15 send: 28
client输出
count: 28 msg: You are welcome. I'm server.
通过tcpdump 或者wireshark抓包,可以看到TCP Keep-Alive的数据包发送情况。