• 【xgtcp】Go TCP服务器框架 支持Hook、功能码函数


    Github仓库: https://github.com/xuehu96/go-tcpcat (欢迎★Star)
    国内仓库: https://gitee.com/xuehu96/go-tcpcat

    TCP常应用于物联网数据服务器、游戏服务器等,且通常都是私有格式协议;
    go-tcpcat只需很少的代码就可以实现TCP透传、消息处理功能;
    消息处理支持Go语言Hook将私有协议的解析程序注入框架、Lua脚本处理、PythonGRPC调用处理、HTTP回调处理、Redis缓存数据等。

    安装:

    go get -u github.com/xuehu96/go-tcpcat
    
    • 1

    1.狗子函数(Hooks)

    狗子函数就是回调函数,指定事件发生后,框架会回调提前注入的处理函数,
    默认的处理函数是通过日志打印,设置狗子函数后,会覆盖默认的处理函数

    程序设置了以下狗子函数:

    Hook调用时机用途示例
    OnListenListen成功后回调程序启动 New资源
    OnAccept新客户端连接调用判断客户端来源,限制客户端数量
    OnReadData接收到客户端数据调用判断数据格式,去头尾等
    OnFnCode从数据中解析出功能码功能码和自定义功能处理函数
    OnSendData向客户端发送数据后调用判断是否发送成功,重发或通知调用方
    OnClose客户端主动或被断开后调用断开后通知或标记客户端离线
    OnStopListen关闭后调用清理资源

    狗子使用方法:

    var fnc1 server.OnXXXXXX = func(param) ret{ 
    	// TODO
    }
    var fnc2 server.OnYYYYYY = func(param) ret{
    	// TODO
    }
             ...
    
    hooks := server.Hook{
    	OnXXXXXX: fnc,
    	OnYYYYYY: fnc,
    	...
    }
    s := server.New(
        server.WithHook(hooks),
    	...
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2.功能码和自定义功能处理函数

    私有协议中区分数据包处理方式的一般叫功能码,类似于HTTP的路由

    功能码解析函数OnFnCode(从data中解析出功能码)

    var fnc server.OnFnCode = func(buf []byte) string {
    	s := string(buf)
    	if strings.Contains(s, "ping") {
    		return "A"
    	}
    	if s[0] == 'B' {
    		return "B"
    	}
    	return ""
    }
    
    hooks := server.Hook{
    	OnFnCode: fnc,
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    处理对应功能码的函数(类似于路由)

    s.AddFn("A", func(c *server.Client, code string, buf []byte, len int) {
    	// TODO
    })
    s.AddFn("B", func(c *server.Client, code string, buf []byte, len int) {
        // TODO
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3. Ping-Pong TCP服务器example

    客户端连接后 向服务器发送数据,服务器按以下格式处理

    • “ping” 回复 “pong”
    • “time” 回复当前服务器时间
    • “exit” 服务器主动断开
    • 客户端发送其他格式 不回复
    package main
    
    import (
    	"context"
    	"github.com/xuehu96/go-tcpcat/pkg/logger"
    	"github.com/xuehu96/go-tcpcat/server"
    	"log"
    	"net"
    	"os"
    	"os/signal"
    	"strings"
    	"syscall"
    	"time"
    )
    
    
    func main() {
    	// 创建TCPListener
    	ln, err := net.Listen("tcp", ":9677")
    	if err != nil {
    		log.Fatalln(err.Error())
    		return
    	}
    
    	// 自定义如何从数据包中获取获取功能码
    	var fnc server.OnFnCode = func(buf []byte) string {
    		s := string(buf)
    		if strings.Contains(s, "ping") {
    			return "p"
    		}
    		if strings.Contains(s, "time") {
    			return "t"
    		}
    		if strings.Contains(s, "exit") {
    			return "x"
    		}
    		return ""
    	}
    
    	hooks := server.Hook{
    		OnFnCode: fnc,
    	}
    	// 创建TCP服务实例
    	s := server.New(
    		server.WithHook(hooks),
    		server.WithListener(ln),
    		server.WithLogger(logger.DebugLogger()),
    	)
    
    	// 添加功能码对应的处理函数 类似于HTTP的路由
    	s.AddFn("p", func(c *server.Client, code string, data []byte) {
    		c.ReplyData([]byte("pong"))
    	})
    	s.AddFn("t", func(c *server.Client, code string, data []byte) {
    		currentTime := time.Now()
    		c.ReplyData([]byte(currentTime.Format("2006-01-02 15:04:05.000000000")))
    	})
    	s.AddFn("x", func(c *server.Client, code string, data []byte) {
    		c.Close()
    	})
    
    	// Ctrl-C 结束
    	go func() {
    		signalCh := make(chan os.Signal, 1)
    		signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM)
    		<-signalCh
    		s.Stop(context.Background())
    	}()
    
    	// TCP服务器开始干活
    	s.Serve()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72

    在这里插入图片描述

  • 相关阅读:
    浅谈电力电容器技术的发展及选型
    机器学习:Softmax介绍及代码实现
    【数据结构C/C++】多维数组的原理、访问方式以及作用
    速锐得解码特斯拉Model Y整车网关电路及CAN通信协议DBC控制策略
    90%的软件测试从业者,努力的方向都错了...你呢?
    Git常用命令
    springboot打成war包
    GEO生信数据挖掘(二)下载基因芯片平台文件及注释
    Windows下SpringBoot连接Redis的正确使用姿势
    html菜单的基本制作
  • 原文地址:https://blog.csdn.net/xuehu96/article/details/126855943