A Packer is responsible for packing and unpacking the packet's payload. You can provide a custom implementation to the easytcp.ServerOption when creating a server.
By default, EasyTCP uses DefaultPacker, which uses the format Size(4)|ID(4)|Data(n), where Size represents the length of Data only.
To implement a custom Packer, you must satisfy the Packer interface, including bytesOrder(), Pack(*easytcp.Message), and Unpack(io.Reader) *easytcp.Message.
// Configure the server with a custom packer
s := easytcp.NewServer(&easytcp.ServerOption{
Packer: new(MyPacker),
})
// Example implementation of a custom packer
type CustomPacker struct{}
func (p *CustomPacker) bytesOrder() binary.ByteOrder {
return binary.BigEndian
}
func (p *CustomPacker) Pack(msg *easytcp.Message) ([]byte, error) {
size := len(msg.Data())
buffer := make([]byte, 2+2+size)
p.bytesOrder().PutUint16(buffer[:2], uint16(size))
p.bytesOrder().PutUint16(buffer[2:4], msg.ID().(uint16))
copy(buffer[4:], msg.Data())
return buffer, nil
}
func (p *CustomPacker) Unpack(reader io.Reader) (*easytcp.Message, error) {
headerBuffer := make([]byte, 2+2)
if _, err := io.ReadFull(reader, headerBuffer); err != nil {
return nil, fmt.Errorf("read size and id err: %s", err)
}
size := p.bytesOrder().Uint16(headerBuffer[:2])
id := p.bytesOrder().Uint16(headerBuffer[2:])
data := make([]byte, size)
if _, err := io.ReadFull(reader, data); err != nil {
return nil, fmt.Errorf("read data err: %s", err)
}
msg := easytcp.NewMessage(id, data)
return msg, nil
}