Skip to content

Commit 21d512a

Browse files
author
MacBookAirM2
committed
Add LTVDecoder.go
1 parent f9a3939 commit 21d512a

File tree

16 files changed

+228
-32
lines changed

16 files changed

+228
-32
lines changed

examples/LTVDecoder.go

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// TLV,即Tag(Type)—Length—Value,是一种简单实用的数据传输方案。
2+
//在TLV的定义中,可以知道它包括三个域,分别为:标签域(Tag),长度域(Length),内容域(Value)。这里的长度域的值实际上就是内容域的长度。
3+
//
4+
//解码前 (20 bytes) 解码后 (20 bytes)
5+
//+------------+------------+-----------------+ +------------+------------+-----------------+
6+
//| Tag | Length | Value |----->| Tag | Length | Value |
7+
//| 0x00000001 | 0x0000000C | "HELLO, WORLD" | | 0x00000001 | 0x0000000C | "HELLO, WORLD" |
8+
//+------------+------------+-----------------+ +------------+------------+-----------------+
9+
// Tag: uint32类型,占4字节,Tag作为MsgId,暂定为1
10+
// Length:uint32类型,占4字节,Length标记Value长度12(hex:0x0000000C)
11+
// Value: 共12个字符,占12字节
12+
//
13+
// 说明:
14+
// lengthFieldOffset = 4 (Length的字节位索引下标是4) 长度字段的偏差
15+
// lengthFieldLength = 4 (Length是4个byte) 长度字段占的字节数
16+
// lengthAdjustment = 0 (Length只表示Value长度,程序只会读取Length个字节就结束,后面没有来,故为0,若Value后面还有crc占2字节的话,那么此处就是2。若Length标记的是Tag+Length+Value总长度,那么此处是-8)
17+
// initialBytesToStrip = 0 (这个0表示返回完整的协议内容Tag+Length+Value,如果只想返回Value内容,去掉Tag的4字节和Length的4字节,此处就是8) 从解码帧中第一次去除的字节数
18+
// maxFrameLength = 2^32 + 4 + 4 (Length为uint类型,故2^32次方表示Value最大长度,此外Tag和Length各占4字节)
19+
20+
package examples
21+
22+
import (
23+
"bytes"
24+
"encoding/binary"
25+
"encoding/hex"
26+
"github.com/aceld/zinx/ziface"
27+
"github.com/aceld/zinx/zlog"
28+
"math"
29+
"unsafe"
30+
)
31+
32+
const TLV_HEADER_SIZE = 8 //表示TLV空包长度
33+
34+
type LtvData struct {
35+
Tag uint32
36+
Length uint32
37+
Value string
38+
}
39+
40+
type LTVDecoder struct {
41+
}
42+
43+
func (this *LTVDecoder) GetLengthField() ziface.LengthField {
44+
// +---------------+---------------+---------------+
45+
// | Length | Tag | Value |
46+
// | uint32(4byte) | uint32(4byte) | n byte |
47+
// +---------------+---------------+---------------+
48+
// Length:uint32类型,占4字节,Length标记Value长度
49+
// Tag: uint32类型,占4字节
50+
// Value: 占n字节
51+
//
52+
//说明:
53+
// lengthFieldOffset = 0 (Length的字节位索引下标是0) 长度字段的偏差
54+
// lengthFieldLength = 4 (Length是4个byte) 长度字段占的字节数
55+
// lengthAdjustment = 4 (Length只表示Value长度,程序只会读取Length个字节就结束,后面没有来,故为0,若Value后面还有crc占2字节的话,那么此处就是2。若Length标记的是Tag+Length+Value总长度,那么此处是-8)
56+
// initialBytesToStrip = 0 (这个0表示返回完整的协议内容Tag+Length+Value,如果只想返回Value内容,去掉Tag的4字节和Length的4字节,此处就是8) 从解码帧中第一次去除的字节数
57+
// maxFrameLength = 2^32 + 4 + 4 (Length为uint32类型,故2^32次方表示Value最大长度,此外Tag和Length各占4字节)
58+
//默认使用TLV封包方式
59+
return ziface.LengthField{
60+
MaxFrameLength: math.MaxUint32 + 4 + 4,
61+
LengthFieldOffset: 0,
62+
LengthFieldLength: 4,
63+
LengthAdjustment: 4,
64+
InitialBytesToStrip: 0,
65+
Order: binary.LittleEndian, //好吧,我看了代码,使用的是小端😂
66+
}
67+
}
68+
69+
func (this *LTVDecoder) Intercept(chain ziface.Chain) ziface.Response {
70+
request := chain.Request()
71+
if request != nil {
72+
switch request.(type) {
73+
case ziface.IRequest:
74+
iRequest := request.(ziface.IRequest)
75+
iMessage := iRequest.GetMessage()
76+
if iMessage != nil {
77+
data := iMessage.GetData()
78+
zlog.Ins().DebugF("TLV-RawData size:%d data:%s\n", len(data), hex.EncodeToString(data))
79+
datasize := len(data)
80+
_data := LtvData{}
81+
if datasize >= TLV_HEADER_SIZE {
82+
_data.Length = binary.LittleEndian.Uint32(data[0:4])
83+
_data.Tag = binary.LittleEndian.Uint32(data[4:8])
84+
value := make([]byte, _data.Length)
85+
binary.Read(bytes.NewBuffer(data[8:8+_data.Length]), binary.LittleEndian, value)
86+
_data.Value = string(value)
87+
iMessage.SetMsgID(_data.Tag)
88+
iRequest.SetResponse(_data)
89+
zlog.Ins().DebugF("TLV-DecodeData size:%d data:%+v\n", unsafe.Sizeof(data), _data)
90+
}
91+
}
92+
}
93+
}
94+
return chain.Proceed(chain.Request())
95+
}

examples/zinx_client/main.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package main
88

99
import (
1010
"fmt"
11+
"github.com/aceld/zinx/examples"
1112
"github.com/aceld/zinx/examples/zinx_client/c_router"
1213
"github.com/aceld/zinx/ziface"
1314
"github.com/aceld/zinx/zlog"
@@ -20,7 +21,7 @@ import (
2021
"time"
2122
)
2223

23-
//客户端自定义业务
24+
// 客户端自定义业务
2425
func business(conn ziface.IConnection) {
2526

2627
for {
@@ -35,7 +36,7 @@ func business(conn ziface.IConnection) {
3536
}
3637
}
3738

38-
//创建连接的时候执行
39+
// 创建连接的时候执行
3940
func DoClientConnectedBegin(conn ziface.IConnection) {
4041
zlog.Debug("DoConnecionBegin is Called ... ")
4142

@@ -46,7 +47,7 @@ func DoClientConnectedBegin(conn ziface.IConnection) {
4647
go business(conn)
4748
}
4849

49-
//连接断开的时候执行
50+
// 连接断开的时候执行
5051
func DoClientConnectedLost(conn ziface.IConnection) {
5152
//在连接销毁之前,查询conn的Name,Home属性
5253
if name, err := conn.GetProperty("Name"); err == nil {
@@ -72,6 +73,10 @@ func main() {
7273
client.AddRouter(2, &c_router.PingRouter{})
7374
client.AddRouter(3, &c_router.HelloRouter{})
7475

76+
tlvDecoder := examples.LTVDecoder{}
77+
client.SetLengthField(tlvDecoder.GetLengthField())
78+
client.AddInterceptor(&tlvDecoder) //TVL协议解码器
79+
7580
//启动客户端client
7681
client.Start()
7782

@@ -83,7 +88,7 @@ func main() {
8388
}
8489

8590
/*
86-
模拟客户端, 不使用client模块方式
91+
模拟客户端, 不使用client模块方式
8792
*/
8893
func main_old() {
8994
conn, err := net.Dial("tcp", "127.0.0.1:8999")

examples/zinx_decoder/decode/htlvcrcdecoder.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/aceld/zinx/examples/zinx_decoder/bili/utils"
2626
"github.com/aceld/zinx/ziface"
2727
"github.com/aceld/zinx/zlog"
28+
"math"
2829
"unsafe"
2930
)
3031

@@ -42,6 +43,30 @@ type HtlvCrcData struct {
4243
type HtlvCrcDecoder struct {
4344
}
4445

46+
func (this *HtlvCrcDecoder) GetLengthField() ziface.LengthField {
47+
//+------+-------+---------+--------+--------+
48+
//| 头码 | 功能码 | 数据长度 | 数据内容 | CRC校验 |
49+
//| 1字节 | 1字节 | 1字节 | N字节 | 2字节 |
50+
//+------+-------+---------+--------+--------+
51+
//头码 功能码 数据长度 Body CRC
52+
//A2 10 0E 0102030405060708091011121314 050B
53+
//说明:
54+
// 1.数据长度len是14(0E),这里的len仅仅指Body长度;
55+
//
56+
// lengthFieldOffset = 2 (len的索引下标是2,下标从0开始) 长度字段的偏差
57+
// lengthFieldLength = 1 (len是1个byte) 长度字段占的字节数
58+
// lengthAdjustment = 2 (len只表示Body长度,程序只会读取len个字节就结束,但是CRC还有2byte没读呢,所以为2)
59+
// initialBytesToStrip = 0 (这个0表示完整的协议内容,如果不想要A2,那么这里就是1) 从解码帧中第一次去除的字节数
60+
// maxFrameLength = 255 + 4(起始码、功能码、CRC) (len是1个byte,所以最大长度是无符号1个byte的最大值)
61+
return ziface.LengthField{
62+
MaxFrameLength: math.MaxInt8 + 4,
63+
LengthFieldOffset: 2,
64+
LengthFieldLength: 1,
65+
LengthAdjustment: 2,
66+
InitialBytesToStrip: 0,
67+
}
68+
}
69+
4570
func (this *HtlvCrcDecoder) Intercept(chain ziface.Chain) ziface.Response {
4671
request := chain.Request()
4772
if request != nil {

examples/zinx_decoder/decode/tlvdecoder.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"encoding/hex"
2525
"github.com/aceld/zinx/ziface"
2626
"github.com/aceld/zinx/zlog"
27+
"math"
2728
"unsafe"
2829
)
2930

@@ -38,6 +39,31 @@ type TlvData struct {
3839
type TLVDecoder struct {
3940
}
4041

42+
func (this *TLVDecoder) GetLengthField() ziface.LengthField {
43+
// +---------------+---------------+---------------+
44+
// | Tag | Length | Value |
45+
// | uint32(4byte) | uint32(4byte) | n byte |
46+
// +---------------+---------------+---------------+
47+
// Tag: uint32类型,占4字节
48+
// Length:uint32类型,占4字节,Length标记Value长度
49+
// Value: 占n字节
50+
//
51+
//说明:
52+
// lengthFieldOffset = 4 (Length的字节位索引下标是4) 长度字段的偏差
53+
// lengthFieldLength = 4 (Length是4个byte) 长度字段占的字节数
54+
// lengthAdjustment = 0 (Length只表示Value长度,程序只会读取Length个字节就结束,后面没有来,故为0,若Value后面还有crc占2字节的话,那么此处就是2。若Length标记的是Tag+Length+Value总长度,那么此处是-8)
55+
// initialBytesToStrip = 0 (这个0表示返回完整的协议内容Tag+Length+Value,如果只想返回Value内容,去掉Tag的4字节和Length的4字节,此处就是8) 从解码帧中第一次去除的字节数
56+
// maxFrameLength = 2^32 + 4 + 4 (Length为uint32类型,故2^32次方表示Value最大长度,此外Tag和Length各占4字节)
57+
//默认使用TLV封包方式
58+
return ziface.LengthField{
59+
MaxFrameLength: math.MaxUint32 + 4 + 4,
60+
LengthFieldOffset: 4,
61+
LengthFieldLength: 4,
62+
LengthAdjustment: 0,
63+
InitialBytesToStrip: 0,
64+
}
65+
}
66+
4167
func (this *TLVDecoder) Intercept(chain ziface.Chain) ziface.Response {
4268
request := chain.Request()
4369
if request != nil {

examples/zinx_decoder/server.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,15 @@ func main() {
2525
s.SetOnConnStop(DoConnectionLost)
2626

2727
//处理TLV协议数据
28-
s.AddInterceptor(&decode.TLVDecoder{}) //TVL协议解码器
28+
tlvDecoder := decode.TLVDecoder{}
29+
s.SetLengthField(tlvDecoder.GetLengthField())
30+
s.AddInterceptor(&tlvDecoder) //TVL协议解码器
2931
s.AddRouter(0x00000001, &router.TLVBusinessRouter{}) //TLV协议对应业务功能
3032

3133
//处理HTLVCRC协议数据
32-
//s.AddInterceptor(&decode.HtlvCrcDecoder{}) //TVL协议解码器
34+
//htlvDecoder := decode.HtlvCrcDecoder{}
35+
//s.SetLengthField(htlvDecoder.GetLengthField())
36+
//s.AddInterceptor(&htlvDecoder) //TVL协议解码器
3337
//s.AddRouter(0x10, &router.HtlvCrcBusinessRouter{}) //TLV协议对应业务功能,因为client.go中模拟数据funcode字段为0x10
3438

3539
//开启服务

examples/zinx_heartbeat/client.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,20 @@ package main
22

33
import (
44
"fmt"
5+
"github.com/aceld/zinx/examples"
56
"github.com/aceld/zinx/ziface"
67
"github.com/aceld/zinx/znet"
78
"os"
89
"os/signal"
910
"time"
1011
)
1112

12-
//ping test 自定义路由
13+
// ping test 自定义路由
1314
type PingRouter struct {
1415
znet.BaseRouter
1516
}
1617

17-
//Ping Handle
18+
// Ping Handle
1819
func (this *PingRouter) Handle(request ziface.IRequest) {
1920
fmt.Println("Call PingRouter Handle")
2021
//先读取客户端的数据,再回写ping...ping...ping
@@ -27,7 +28,7 @@ func (this *PingRouter) Handle(request ziface.IRequest) {
2728
*/
2829
}
2930

30-
//客户端自定义业务
31+
// 客户端自定义业务
3132
func business(conn ziface.IConnection) {
3233

3334
for {
@@ -41,7 +42,7 @@ func business(conn ziface.IConnection) {
4142
}
4243
}
4344

44-
//创建连接的时候执行
45+
// 创建连接的时候执行
4546
func DoClientConnectedBegin(conn ziface.IConnection) {
4647
fmt.Println("DoConnecionBegin is Called ... ")
4748

@@ -52,7 +53,7 @@ func DoClientConnectedBegin(conn ziface.IConnection) {
5253
go business(conn)
5354
}
5455

55-
//连接断开的时候执行
56+
// 连接断开的时候执行
5657
func DoClientConnectedLost(conn ziface.IConnection) {
5758
//在连接销毁之前,查询conn的Name,Home属性
5859
if name, err := conn.GetProperty("Name"); err == nil {
@@ -77,6 +78,10 @@ func main() {
7778
//注册收到服务器消息业务路由
7879
client.AddRouter(0, &PingRouter{})
7980

81+
tlvDecoder := examples.LTVDecoder{}
82+
client.SetLengthField(tlvDecoder.GetLengthField())
83+
client.AddInterceptor(&tlvDecoder) //TVL协议解码器
84+
8085
//启动心跳检测
8186
client.StartHeartBeat(5 * time.Second)
8287

examples/zinx_heartbeat/server.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

33
import (
44
"fmt"
5+
"github.com/aceld/zinx/examples"
56
"github.com/aceld/zinx/ziface"
67
"github.com/aceld/zinx/znet"
78
"time"
@@ -11,7 +12,7 @@ type TestRouter struct {
1112
znet.BaseRouter
1213
}
1314

14-
//Handle -
15+
// Handle -
1516
func (t *TestRouter) Handle(req ziface.IRequest) {
1617
fmt.Println("--> Call Handle, reveived msg: ", string(req.GetData()), " msgID: ", req.GetMsgID(), " connID: ", req.GetConnection().GetConnID())
1718

@@ -25,6 +26,10 @@ func main() {
2526

2627
s.AddRouter(1, &TestRouter{})
2728

29+
tlvDecoder := examples.LTVDecoder{}
30+
s.SetLengthField(tlvDecoder.GetLengthField())
31+
s.AddInterceptor(&tlvDecoder) //LTV协议解码器
32+
2833
//启动心跳检测
2934
s.StartHeartBeat(5 * time.Second)
3035

examples/zinx_logger/client.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

33
import (
44
"fmt"
5+
"github.com/aceld/zinx/examples"
56
"github.com/aceld/zinx/examples/zinx_client/c_router"
67
"github.com/aceld/zinx/ziface"
78
"github.com/aceld/zinx/zlog"
@@ -11,7 +12,7 @@ import (
1112
"time"
1213
)
1314

14-
//客户端自定义业务
15+
// 客户端自定义业务
1516
func business(conn ziface.IConnection) {
1617

1718
for {
@@ -26,7 +27,7 @@ func business(conn ziface.IConnection) {
2627
}
2728
}
2829

29-
//创建连接的时候执行
30+
// 创建连接的时候执行
3031
func DoClientConnectedBegin(conn ziface.IConnection) {
3132
zlog.Debug("DoConnecionBegin is Called ... ")
3233

@@ -37,7 +38,7 @@ func DoClientConnectedBegin(conn ziface.IConnection) {
3738
go business(conn)
3839
}
3940

40-
//连接断开的时候执行
41+
// 连接断开的时候执行
4142
func DoClientConnectedLost(conn ziface.IConnection) {
4243
//在连接销毁之前,查询conn的Name,Home属性
4344
if name, err := conn.GetProperty("Name"); err == nil {
@@ -61,6 +62,9 @@ func main() {
6162

6263
//注册收到服务器消息业务路由
6364
client.AddRouter(0, &c_router.PingRouter{})
65+
tlvDecoder := examples.LTVDecoder{}
66+
client.SetLengthField(tlvDecoder.GetLengthField())
67+
client.AddInterceptor(&tlvDecoder) //LTV协议解码器
6468

6569
//启动客户端client
6670
client.Start()

0 commit comments

Comments
 (0)