翔云

Just try, don't shy. 最新文章请点击
随笔 - 294, 文章 - 0, 评论 - 27, 阅读 - 49万
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

golang tcp keepalive实践

Posted on   翔云123456  阅读(3313)  评论(0编辑  收藏  举报

前文中已经介绍了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

编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示