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, cS2R, cR2S, 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, cS2R, cR2S, cQuit) go Receiver(cTCP, cS2R, cR2S, cQuit) <-cQuit <-cQuit }
有疑问加站长微信联系(非本文作者)