zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    JUnit常用断言及注解
    centos7 yum快速安装LNMP
    ceph问题汇总
    selinux介绍/状态查看/开启/关闭
    linux 修改主机名
    CentOS 7部署 Ceph分布式存储架构
    如何判断当前系统运行在物理机上还是虚拟机上,返回虚拟机的类型
    Golang操作结构体、Map转化为JSON
    PHP强制修改返回的状态码
    composer问题集锦
  • 原文地址:https://www.cnblogs.com/lanyangsh/p/10928127.html
Copyright © 2011-2022 走看看