package appkit import ( "bytes" "encoding/binary" "errors" "math" ) // 数据协议如下: // // +-----------+--------+--------------+-------+------+ // | 0x01,0x02 | length | topic-length | topic | data | // +-----------+--------+--------------+-------+------+ // 2 2 2 n n // // * 头部有两个模数 0x01、0x02; // * length 表示消息的总长度; // * 然后分别是 topic、data,包含其长度和数据; // * 长度使用 uint16 类型,所以占用 2 个字节; // // todo 实现数据校验码,防止篡改 // Encode 数据编码 func Encode(topic, data []byte) ([]byte, error) { topicLen := len(topic) dataLen := len(data) size := 2 + topicLen + dataLen // 不包括模数和数据长度 if topicLen == 0 { return nil, errors.New("topic too small") } if size+4 > math.MaxUint16 { return nil, errors.New("data too big") } buf := &bytes.Buffer{} // 由于 模数、topic 和 data 都是基本类型,所以当 // 执行 binary.Write() 时是不会出错的 _ = binary.Write(buf, binary.BigEndian, []byte{0x01, 0x02}) _ = binary.Write(buf, binary.BigEndian, uint16(size)) _ = binary.Write(buf, binary.BigEndian, uint16(topicLen)) _ = binary.Write(buf, binary.BigEndian, topic) _ = binary.Write(buf, binary.BigEndian, data) // 如果没有数据会不会报错 return buf.Bytes(), nil } // Decode 数据解码 func Decode(buf []byte) (topic, data []byte, err error) { r := bytes.NewReader(buf) // 读取模数 var v [2]byte err = binary.Read(r, binary.BigEndian, &v) if err != nil { return } if v[0] != 0x01 || v[1] != 0x02 { err = errors.New("protocol error") return } // 读取数据长度 var size uint16 err = binary.Read(r, binary.BigEndian, &size) if err != nil { return } // 读取主题长度 var topicLen uint16 err = binary.Read(r, binary.BigEndian, &topicLen) if err != nil { return } // 读取主题 topic = make([]byte, topicLen) err = binary.Read(r, binary.BigEndian, &topic) if err != nil { return } // 读取数据 data = make([]byte, size-2-topicLen) err = binary.Read(r, binary.BigEndian, &data) return }