前端之家收集整理的这篇文章主要介绍了
golang tcp heartbeat,
前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
package main
import "log"
import "time"
const TIMEOUT_NS = int64(30e9) // 30 seconds
type Msg struct {
Header uint8 // == 1
SeqNo uint32
Data uint8 // the real case is complex
}
type Reply struct {
Header uint8 // == 2
SeqNo uint32
Status uint8
}
type AskHeartBeat struct {
Header uint8 // == 4
SeqNo uint32
}
type ReplyHeartBeat struct {
Header uint8 // == 4
SeqNo uint32
}
type TCPCh chan interface{} // simulate TCP
type CmdCh chan uint8 // 0:Quit 1:ask HB
var gLastHBTime int64 // heartbeat time
func Sender(tcp TCPCh,cS2R,cR2S,cQuit CmdCh) {
var cmd uint8
seq := uint32(1)
n := 10 // send 10 msgs
L_LOOP:
for {
select {
case cmd = <-cR2S:
if cmd == 0 {
break L_LOOP
}
if cmd == 1 {
gLastHBTime = time.Nanoseconds()
hbr := ReplyHeartBeat{5,seq}
seq++
log.Println("S",hbr)
tcp <- hbr
}
default:
now := time.Nanoseconds()
if now-gLastHBTime > TIMEOUT_NS {
hb := &AskHeartBeat{4,seq}
log.Println("S",hb)
tcp <- hb
seq++
}
gLastHBTime = now
if n < 0 {
time.Sleep(20e9) // wait reply
cS2R <- 0 // ask to quit
break L_LOOP
}
n--
m := &Msg{1,seq,0}
seq++
log.Println("S",m)
tcp <- m
}
}
cQuit <- 0
}
func Receiver(tcp TCPCh,cQuit CmdCh) {
var v interface{}
var cmd uint8
lastSeq := uint32(0)
L_LOOP:
for {
select {
case v = <-tcp:
gLastHBTime = time.Nanoseconds()
switch v.(type) {
case Reply:
r := v.(Reply)
if lastSeq+1 != r.SeqNo {
cR2S <- 0 // force sender quit
}
log.Println("R",r)
case AskHeartBeat:
r := v.(AskHeartBeat)
if lastSeq+1 != r.SeqNo {
cR2S <- 0 // force sender quit
}
log.Println("R",r)
cR2S <- 1 // request send ReplyHeartBeat
case ReplyHeartBeat:
r := v.(ReplyHeartBeat)
if lastSeq+1 != r.SeqNo {
cR2S <- 1 // force sender quit
}
log.Println("R",r)
}
case cmd = <-cS2R:
if cmd == 0 {
break L_LOOP
}
}
}
cQuit <- 0
}
func main() {
cTCP := make(chan interface{},1024)
cQuit := make(chan uint8,2)
cS2R := make(chan uint8)
cR2S := make(chan uint8)
gLastHBTime = time.Nanoseconds()
go Sender(cTCP,cQuit)
go Receiver(cTCP,cQuit)
<-cQuit
<-cQuit
}