golang tcp keepalive實踐

前文中已經介紹了TCP keep alive的作了詳盡說明,本文結合golang,介紹如何使用TCP keep alive。html

目前golang net包不提供TCP keep alive 空閒多長時間開始探測探測總次數直接設置。git

能夠使用第三方包。github

1.下載第三方包

git clone git@github.com:felixge/tcpkeepalive.git

注意放到GOPATH目錄下。golang

2.例子

2.1 server

server端,接受client鏈接請求,創建鏈接後,設置鏈接的空閒多長時間開始探測探測時間間隔探測總次數tcp

本例中,咱們設置的參數以下:.net

  • 空閒多長時間開始探測 keepAliveIdle: 10s
  • 探測時間間隔 keepAliveInterval: 10s
  • 探測總次數 keepAliveCount:9

server端發送一次數據後,停住。等待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")

}

2.2 client

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))
        }

}

3.查看結果

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的數據包發送狀況。

在這裏插入圖片描述

4.參考

Using TCP keepalive with Go

github tcpkeepalive

相關文章
相關標籤/搜索