前文中已經介紹了TCP keep alive的作了詳盡說明,本文結合golang,介紹如何使用TCP keep alive。html
目前golang net包不提供TCP keep alive 空閒多長時間開始探測
、 探測總次數
直接設置。git
能夠使用第三方包。github
git clone git@github.com:felixge/tcpkeepalive.git
注意放到GOPATH
目錄下。golang
server端,接受client鏈接請求,創建鏈接後,設置鏈接的空閒多長時間開始探測
、探測時間間隔
、探測總次數
。tcp
本例中,咱們設置的參數以下:.net
空閒多長時間開始探測
keepAliveIdle
: 10s探測時間間隔
keepAliveInterval
: 10s探測總次數
keepAliveCount
:9server端發送一次數據後,停住。等待10s,開始發送tcp keep alive.code
server 代碼以下: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") }
client端很簡單,負責接收數據。htm
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)) } }
server輸出blog
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的數據包發送狀況。