Files
bl/common/socket/codec/SocketCodec_Tomee.go

84 lines
1.7 KiB
Go
Raw Normal View History

package codec
import (
"encoding/binary"
"errors"
"io"
"github.com/panjf2000/gnet/v2"
)
var ErrIncompletePacket = errors.New("incomplete packet")
const maxBodyLen = 10 * 1024 * 1024 // 业务最大包体长度,按需调整
// TomeeSocketCodec 协议格式:
//
// * 0 4
// * +-----------+
// * | body len |
// * +-----------+
// * | |
// * + +
// * | body bytes|
// * + +
// * | ... ... |
// * +-----------+
type TomeeSocketCodec struct{}
var _ SocketCodec = (*TomeeSocketCodec)(nil)
func NewTomeeSocketCodec() *TomeeSocketCodec {
return &TomeeSocketCodec{}
}
func (codec TomeeSocketCodec) Encode(buf []byte) ([]byte, error) {
bodyLen := len(buf)
data := make([]byte, 4+bodyLen)
// 写入4字节的包长度
binary.BigEndian.PutUint32(data[:4], uint32(bodyLen))
// 写入包体
copy(data[4:], buf)
return data, nil
}
func (codec TomeeSocketCodec) Decode(c gnet.Conn) ([]byte, error) {
// handle(c)
// 先读取4字节的包长度
lenBuf, err := c.Peek(4)
if err != nil {
if errors.Is(err, io.ErrShortBuffer) {
return nil, ErrIncompletePacket
}
return nil, err
}
bodyLen := binary.BigEndian.Uint32(lenBuf)
if bodyLen > maxBodyLen {
return nil, errors.New("packet body exceeds max length")
}
// 检查整个包是否完整
buf, err := c.Peek(int(bodyLen))
if err != nil {
if errors.Is(err, io.ErrShortBuffer) {
return nil, ErrIncompletePacket
}
return nil, err
}
// 提取包体
body := make([]byte, bodyLen)
copy(body, buf)
// 从缓冲区中丢弃已读取的数据
_, _ = c.Discard(int(bodyLen))
return body, nil
}