消息包处理

    gtcp模块提供了简单轻量级数据交互协议,效率非常高,协议格式如下:

    1. 数据长度:默认为16位(2字节),用于标识该消息体的数据长度,单位为字节,不包含自身的2字节;
    2. 数据字段:变长,根据数据长度可以知道,数据最大长度不能超过0xFFFF = 65535 bytes = 64 KB

    简单协议由gtcp封装实现,如果开发者客户端和服务端如果都使用gtcp模块来通信则无需关心协议实现,专注数据字段封装/解析实现即可。如果涉及和其他开发语言对接,则需要按照该协议实现对接即可,由于简单协议非常简单轻量级,因此对接成本很低。

    https://godoc.org/github.com/gogf/gf/net/gtcp

    1. type Conn
    2. func (c *Conn) SendPkg(data []byte, option ...PkgOption) error
    3. func (c *Conn) SendPkgWithTimeout(data []byte, timeout time.Duration, option ...PkgOption) error
    4. func (c *Conn) SendRecvPkg(data []byte, option ...PkgOption) ([]byte, error)
    5. func (c *Conn) SendRecvPkgWithTimeout(data []byte, timeout time.Duration, option ...PkgOption) ([]byte, error)
    6. func (c *Conn) RecvPkg(option ...PkgOption) (result []byte, err error)
    7. func (c *Conn) RecvPkgWithTimeout(timeout time.Duration, option ...PkgOption) ([]byte, error)

    可以看到,消息包方法命名是在原有的基本连接操作方法中加上了Pkg关键词便于区分。

    1. // 数据读取选项
    2. type PkgOption struct {
    3. HeaderSize int // 自定义头大小(默认为2字节,最大不能超过4字节)
    4. MaxDataSize int // (byte)数据读取的最大包大小,默认最大不能超过2字节(65535 byte)
    5. Retry Retry // 失败重试策略
    6. }

    这个示例比较简单,执行后,输出结果为:

    1. receive: [48]
    2. receive: [49]
    3. receive: [50]
    4. receive: [51]
    5. ...

    大多数场景下,我们需要对发送的消息能自定义数据结构,开发者可以利用字段传递任意的消息内容实现。

    以下是一个简单的自定义数据结构的示例,用于客户端上报当前主机节点的内存及CPU使用情况,示例代码位于:

    在该示例中,数据字段使用了JSON数据格式进行自定义,便于数据的编码/解码。

    实际场景中,开发者往往需要自定义包解析协议,或者采用较通用的protobuf二进制包封装/解析协议。

    1. 数据结构定义。

      1. package types
      2. type NodeInfo struct {
      3. Cpu float32 // CPU百分比(%)
      4. Host string // 主机名称
      5. Ip g.Map // IP地址信息(可能多个)
      6. MemUsed int // 内存使用(byte)
      7. MemTotal int // 内存总量(byte)
      8. Time int // 上报时间(时间戳)
      9. }
    2. gtcp_monitor_server.go

      服务端。

    3. gtcp_monitor_client.go

      客户端。

      1. package main
      2. import (
      3. "encoding/json"
      4. "github.com/gogf/gf/frame/g"
      5. "github.com/gogf/gf/net/gtcp"
      6. "github.com/gogf/gf/os/glog"
      7. "github.com/gogf/gf/os/gtime"
      8. "github.com/gogf/gf/geg/net/gtcp/pkg_operations/monitor/types"
      9. )
      10. // 数据上报客户端
      11. conn, err := gtcp.NewConn("127.0.0.1:8999")
      12. if err != nil {
      13. panic(err)
      14. defer conn.Close()
      15. // 使用JSON格式化数据字段
      16. info, err := json.Marshal(types.NodeInfo{
      17. Cpu : float32(66.66),
      18. Host : "localhost",
      19. Ip : g.Map {
      20. "etho" : "192.168.1.100",
      21. "eth1" : "114.114.10.11",
      22. },
      23. MemUsed : 15560320,
      24. MemTotal : 16333788,
      25. Time : int(gtime.Timestamp()),
      26. })
      27. if err != nil {
      28. panic(err)
      29. }
      30. // 使用 SendRecvPkg 发送消息包并接受返回
      31. if result, err := conn.SendRecvPkg(info); err != nil {
      32. if err.Error() == "EOF" {
      33. glog.Println("server closed")
      34. }
      35. } else {
      36. glog.Println(string(result))
      37. }
    4. 执行后
      • 客户端输出结果为:
        1. 服务端输出结果为: