go语言心跳响应

来源:互联网 发布:java连接ldap实例 编辑:程序博客网 时间:2024/05/21 12:45

本文实现模拟实现一个简单的心跳响应

 在长连接下,有可能很长一段时间都没有数据往来。理论上说,这个连接是一直保持连接的,但是实际情况中,如果中间节点出现什么故障是难以知道的。更要命的是,有的节点(防火墙)会自动把一定时间之内没有数据交互的连接给断掉。在这个时候,就需要我们的心跳包了,用于维持长连接.

心跳机制

 client每隔几分钟发送一个固定信息给服务端,服务端收到后回复一个固定信息如果服务端几分钟内没有收到客户端信息则视客户端断开。发包方可以是客户也可以是服务端..
 心跳包之所以叫心跳包是因为:它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活着。事实上这是为了保持长连接,至于这个包的内容,是没有什么特别规定的,不过一般都是很小的包,或者只包含包头的一个空包。心跳包主要也就是用于长连接的保活和断线处理。一般的应用下,判定时间在30-40秒比较不错。如果实在要求高,那就在6-9秒。

 本文在server中设置了超时,超时后server端主动关闭连接
conn.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Second))

客户端

generator(conn *net.TCPConn)模拟发送心跳包,期间停了10秒然后继续发送.
代码示例:

/*** @Author:  Sergey Jay* @Email :  zshangan@iCloud.com* @Create:  17/09/2017 14:52* Copyright (c) 2017 Sergey Jay All rights reserved.* Description:*/package mainimport (    "net"    "os"    "strconv"    "time"    "github.com/astaxie/beego")func main() {    /*       1->resolve address       2->connect    */    server := "127.0.0.1:8090"    tcpAddr, err := net.ResolveTCPAddr("tcp", server)    if err != nil {        beego.Warning("Fatal error : ", err.Error())        os.Exit(1)    }    conn, err := net.DialTCP("tcp", nil, tcpAddr)    if err != nil {        beego.Warning("Fatal error : ", err.Error())        os.Exit(1)    }    generator(conn)    beego.Trace("send over")}func generator(conn *net.TCPConn) {    for i := 0; i < 10; i++ {        words := strconv.Itoa(i) + "  times " + " --> heart beating from client "        num, err := conn.Write([]byte(words))        if err != nil {            beego.Warning("Fatal error : ", err.Error())            os.Exit(1)        }        beego.Trace("Server have receive :", num, " bytes")        time.Sleep(1 * time.Second)    }    for i := 0; i < 2; i++ {        beego.Info("client stop 5s")        time.Sleep(5 * time.Second)    }    for i := 0; i < 10; i++ {        words := strconv.Itoa(i) + "times " + "==> heart beat from client"        num, err := conn.Write([]byte(words))        if err != nil {            beego.Warning("Fatal error : ", err.Error())            os.Exit(1)        }        beego.Trace("Server have receive :", num, " bytes")        time.Sleep(1 * time.Second)    }}

Server 端

示例代码:

/*** @Author:  Sergey Jay* @Email :  zshangan@iCloud.com* @Create:  17/09/2017 14:57* Copyright (c) 2017 Sergey Jay All rights reserved.* Description:*/package mainimport (    "net"    "os"    "time"    "github.com/astaxie/beego")func main() {    server := ":8090"    netListen, err := net.Listen("tcp", server)    if err != nil {        beego.Warning("Fatal error : ", err)        os.Exit(1)    }    beego.Info("waiting for client")    for {        conn, err := netListen.Accept()        if err != nil {            beego.Warning("Fatal error : ", err)            return        }        conn.SetReadDeadline(time.Now().Add(time.Duration(8) * time.Second))        beego.Trace(conn.RemoteAddr().String(), "-->>connect success")        go HandleConnection(conn)    }}func HandleConnection(conn net.Conn) {    buffer := make([]byte, 1024)    for {        n, err := conn.Read(buffer)        if err != nil {            beego.Warning("Fatal error : ", err)            return        }        data := buffer[:n]        message := make(chan byte)        go GetMessage(data, message)        go HeartBeat(conn, message, 4)        beego.Trace(conn.RemoteAddr().String(), string(buffer[:n]))    }    defer conn.Close()}func GetMessage(bytes []byte, message chan byte) {    for _, v := range bytes {        message <- v    }    close(message)}func HeartBeat(conn net.Conn, message chan byte, timeout int) {    select {    case <-message:        //beego.Trace(conn.RemoteAddr().String(), string(fk), ": ", "Heart beating ")        conn.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Second))    case <-time.After(time.Second * 5):        beego.Warning(conn.RemoteAddr().String(), "time out")        conn.Close()    }}

模拟效果

 client发送心跳包,发送期间有10s停顿,而server端则设置了超时时间为4s,client后面发送的数据server不在接收….此处server并没有给client提示..

server端

这里写图片描述

client端

这里写图片描述

原创粉丝点击