首页 Zinx 中配置和使用自定义的encoder和decoder
文章
取消

Zinx 中配置和使用自定义的encoder和decoder

Zinx 中配置和使用自定义的encoder和decoder

zinx 自身提供了编码和解码的相关类,但是在和其他系统对接时,zinx 提供的相关类无法正确的完成工作,这时候就需要使用自定义的encoder和decoder。

自定义decoder

要在 zinx 中实现自定义的 decoder,需要创建一个新的结构体MyDecoder,并为该结构体实现 ziface.IDecoder 接口。

ziface.IDecoder的定义如下

1
2
3
4
5
6
7
8
9
10
type IDecoder interface {
	IInterceptor
	GetLengthField() *LengthField
}

// 其中 IInterceptor 的定义如下
type IInterceptor interface {
	Intercept(IChain) IcResp //拦截器的拦截处理方法(由开发者定义)
}

LengthField在zinx中定义了头部相关字段的长度,具体的细节可以参考文档:https://www.yuque.com/aceld/tsgooa/lsu25bgvqoxeg6nz
IInterceptor是zinx中拦截器的接口定义,具体细节可以参考文档:https://www.yuque.com/aceld/tsgooa/zn0y6xpynrzfd1z5

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
type MyDecoder struct {
	Tag    uint32
	Length uint32
	Data   []byte
}

func NewMyDecoder() ziface.IDecoder {
	return &MyDecoder{}
}

// 实现 GetLengthField 方法,返回相关字段长度
func (decoder *MyDecoder) GetLengthField() *ziface.LengthField {
	return &ziface.LengthField{
		MaxFrameLength:      math.MaxUint32 + 12,
		LengthFieldOffset:   8,
		LengthFieldLength:   4,
		LengthAdjustment:    0,
		InitialBytesToStrip: 0,
	}
}

// 实现 IInterceptor 接口,此处是进行解码的入口
func (decoder *MyDecoder) Intercept(chain ziface.IChain) ziface.IcResp {

	//1. 获取zinx的IMessage
	iMessage := chain.GetIMessage()
	if iMessage == nil {
		//进入责任链下一层
		return chain.ProceedWithIMessage(iMessage, nil)
	}

	//2. 获取数据
	data := iMessage.GetData()

	//3. 读取的数据不超过包头,直接进入下一层
	if len(data) < HEADER_SIZE {
		return chain.ProceedWithIMessage(iMessage, nil)
	}

    mydata := decoder.decode(data)

	//5. 将解码后的数据重新设置到IMessage中, Zinx的Router需要MsgID来寻址
	iMessage.SetMsgID(mydata.Tag)
	iMessage.SetData(mydata.Data)
	iMessage.SetDataLen(mydata.Length)

	//6. 将解码后的数据进入下一层
	return chain.ProceedWithIMessage(iMessage, *mydata)
}

func (decoder *MyDecoder) decode(data []byte) *MyDecoder {
	dc := MyDecoder{}
	//获取T

	dc.Tag = binary.BigEndian.Uint32(data[4:8])
	//获取L
	dc.Length = binary.BigEndian.Uint32(data[8:12])
	//确定V的长度
	dc.Data = make([]byte, dc.Length)

	//5.获取V
	binary.Read(bytes.NewBuffer(data[HEADER_SIZE:HEADER_SIZE+dc.Length]), binary.BigEndian, dc.Data)
	return &dc
}

之后,想server注册刚刚写好的decoder

1
s.SetDecoder(codec.NewMyDecoder()

自定义encoder

zinx中没有Encoder相关的接口定义,要实现相关的逻辑,需要创建自定义的DataPacket结构体,并实现IDataPack接口:

1
2
3
4
5
type IDataPack interface {
	GetHeadLen() uint32                //获取包头长度方法
	Pack(msg IMessage) ([]byte, error) //封包方法
	Unpack([]byte) (IMessage, error)   //拆包方法
}
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
type MyDataPack struct{}

func (dp *MyDataPack) GetHeadLen() uint32 {
	// Returns the length of the message header
	return 12
}

func (dp *MyDataPack) Pack(msg ziface.IMessage) ([]byte, error) {
	// Convert the message to your custom message struct
	// Create a buffer to hold the encoded message
	buf := bytes.NewBuffer(nil)

	// Write the message header
	binary.Write(buf, binary.BigEndian, uint32(0xffffffff))
	binary.Write(buf, binary.BigEndian, msg.GetMsgID())
	binary.Write(buf, binary.BigEndian, msg.GetDataLen())

	// Write the message data
	binary.Write(buf, binary.BigEndian, msg.GetData())

	return buf.Bytes(), nil
}

func (dp *MyDataPack) Unpack(binaryData []byte) (ziface.IMessage, error) {
	// Create a buffer to read the message header
	buf := bytes.NewReader(binaryData[:12])

	// Read the message header
	var start uint32
	var id uint32
	var dataLen uint32
	binary.Read(buf, binary.BigEndian, &start)
	binary.Read(buf, binary.BigEndian, &id)
	binary.Read(buf, binary.BigEndian, &dataLen)

	// Create a buffer to read the message data
	dataBuf := bytes.NewReader(binaryData[12:])

	// Read the message data
	data := make([]byte, dataLen)
	binary.Read(dataBuf, binary.BigEndian, &data)

	// Create a new instance of your custom message struct
	myMsg := zpack.NewMsgPackage(id, data)

	return myMsg, nil
}

同样,在此之后需要向zinx注册DataPacket

1
s.SetPacket(&codec.MyDataPack{})
本文由作者按照 CC BY 4.0 进行授权
文章内容