golang tcp keepalive實踐


前文中已經介紹了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的數據包發送情況。

在這里插入圖片描述

4.參考

Using TCP keepalive with Go

github tcpkeepalive


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM