我是靠谱客的博主 重要八宝粥,最近开发中收集的这篇文章主要介绍linux心跳包检测代码_golang实现带有心跳检测的tcp长连接,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

package main

// golang实现带有心跳检测的tcp长连接

// server

import (

"fmt"

"net"

"time"

)

// message struct:

// c#d

var (

Req_REGISTER byte = 1 // 1 --- c register cid

Res_REGISTER byte = 2 // 2 --- s response

Req_HEARTBEAT byte = 3 // 3 --- s send heartbeat req

Res_HEARTBEAT byte = 4 // 4 --- c send heartbeat res

Req byte = 5 // 5 --- cs send data

Res byte = 6 // 6 --- cs send ack

)

type CS struct {

Rch chan []byte

Wch chan []byte

Dch chan bool

u string

}

func NewCs(uid string) *CS {

return &CS{Rch: make(chan []byte), Wch: make(chan []byte), u: uid}

}

var CMap map[string]*CS

func main() {

CMap = make(map[string]*CS)

listen, err := net.ListenTCP("tcp", &net.TCPAddr{net.ParseIP("127.0.0.1"), 6666, ""})

if err != nil {

fmt.Println("监听端口失败:", err.Error())

return

}

fmt.Println("已初始化连接,等待客户端连接...")

go PushGRT()

Server(listen)

select {}

}

func PushGRT() {

for {

time.Sleep(15 * time.Second)

for k, v := range CMap {

fmt.Println("push msg to user:" + k)

v.Wch

}

}

}

func Server(listen *net.TCPListener) {

for {

conn, err := listen.AcceptTCP()

if err != nil {

fmt.Println("接受客户端连接异常:", err.Error())

continue

}

fmt.Println("客户端连接来自:", conn.RemoteAddr().String())

// handler goroutine

go Handler(conn)

}

}

func Handler(conn net.Conn) {

defer conn.Close()

data := make([]byte, 128)

var uid string

var C *CS

for {

conn.Read(data)

fmt.Println("客户端发来数据:", string(data))

if data[0] == Req_REGISTER { // register

conn.Write([]byte{Res_REGISTER, '#', 'o', 'k'})

uid = string(data[2:])

C = NewCs(uid)

CMap[uid] = C

//fmt.Println("register client")

//fmt.Println(uid)

break

} else {

conn.Write([]byte{Res_REGISTER, '#', 'e', 'r'})

}

}

//WHandler

go WHandler(conn, C)

//RHandler

go RHandler(conn, C)

//Worker

go Work(C)

select {

case

fmt.Println("close handler goroutine")

}

}

// 正常写数据

// 定时检测 conn die => goroutine die

func WHandler(conn net.Conn, C *CS) {

// 读取业务Work 写入Wch的数据

ticker := time.NewTicker(20 * time.Second)

for {

select {

case d :=

conn.Write(d)

case

if _, ok := CMap[C.u]; !ok {

fmt.Println("conn die, close WHandler")

return

}

}

}

}

// 读客户端数据 + 心跳检测

func RHandler(conn net.Conn, C *CS) {

// 心跳ack

// 业务数据 写入Wch

for {

data := make([]byte, 128)

// setReadTimeout

err := conn.SetReadDeadline(time.Now().Add(10 * time.Second))

if err != nil {

fmt.Println(err)

}

if _, derr := conn.Read(data); derr == nil {

// 可能是来自客户端的消息确认

// 数据消息

fmt.Println(data)

if data[0] == Res {

fmt.Println("recv client data ack")

} else if data[0] == Req {

fmt.Println("recv client data")

fmt.Println(data)

conn.Write([]byte{Res, '#'})

// C.Rch

}

continue

}

conn.Write([]byte{Req_HEARTBEAT, '#'})

fmt.Println("send ht packet")

conn.SetReadDeadline(time.Now().Add(2 * time.Second))

if _, herr := conn.Read(data); herr == nil {

// fmt.Println(string(data))

fmt.Println("resv ht packet ack")

} else {

delete(CMap, C.u)

fmt.Println("delete user!")

return

}

}

}

func Work(C *CS) {

time.Sleep(5 * time.Second)

C.Wch

time.Sleep(15 * time.Second)

C.Wch

// 从读ch读信息

/*ticker := time.NewTicker(20 * time.Second)

for {

select {

case d :=

C.Wch

case

if _, ok := CMap[C.u]; !ok {

return

}

}

}

*/ // 往写ch写信息

}

package main

// golang实现带有心跳检测的tcp长连接

// server

import (

"fmt"

"net"

)

var (

Req_REGISTER byte = 1 // 1 --- c register cid

Res_REGISTER byte = 2 // 2 --- s response

Req_HEARTBEAT byte = 3 // 3 --- s send heartbeat req

Res_HEARTBEAT byte = 4 // 4 --- c send heartbeat res

Req byte = 5 // 5 --- cs send data

Res byte = 6 // 6 --- cs send ack

)

var Dch chan bool

var Rch chan []byte

var Wch chan []byte

func main() {

Dch = make(chan bool)

Rch = make(chan []byte)

Wch = make(chan []byte)

addr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:6666")

conn, err := net.DialTCP("tcp", nil, addr)

//conn, err := net.Dial("tcp", "127.0.0.1:6666")

if err != nil {

fmt.Println("连接服务端失败:", err.Error())

return

}

fmt.Println("已连接服务器")

defer conn.Close()

go Handler(conn)

select {

case

fmt.Println("关闭连接")

}

}

func Handler(conn *net.TCPConn) {

// 直到register ok

data := make([]byte, 128)

for {

conn.Write([]byte{Req_REGISTER, '#', '2'})

conn.Read(data)

//fmt.Println(string(data))

if data[0] == Res_REGISTER {

break

}

}

//fmt.Println("i'm register")

go RHandler(conn)

go WHandler(conn)

go Work()

}

func RHandler(conn *net.TCPConn) {

for {

// 心跳包,回复ack

data := make([]byte, 128)

i,_ := conn.Read(data)

if i == 0 {

Dch

return

}

if data[0] == Req_HEARTBEAT {

fmt.Println("recv ht pack")

conn.Write([]byte{Res_REGISTER,'#','h'})

fmt.Println("send ht pack ack")

} else if data[0] == Req {

fmt.Println("recv data pack")

fmt.Printf("%vn",string(data[2:]))

Rch

conn.Write([]byte{Res,'#'})

}

}

}

func WHandler(conn net.Conn) {

for {

select {

case msg :=

fmt.Println((msg[0]))

fmt.Println("send data after: " + string(msg[1:]))

conn.Write(msg)

}

}

}

func Work() {

for {

select {

case msg :=

fmt.Println("work recv " + string(msg))

Wch

}

}

}

最后

以上就是重要八宝粥为你收集整理的linux心跳包检测代码_golang实现带有心跳检测的tcp长连接的全部内容,希望文章能够帮你解决linux心跳包检测代码_golang实现带有心跳检测的tcp长连接所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部