Skip to content

Commit

Permalink
Add LTVDecoder.go
Browse files Browse the repository at this point in the history
  • Loading branch information
MacBookAirM2 committed Mar 14, 2023
1 parent f9a3939 commit 21d512a
Show file tree
Hide file tree
Showing 16 changed files with 228 additions and 32 deletions.
95 changes: 95 additions & 0 deletions examples/LTVDecoder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// TLV,即Tag(Type)—Length—Value,是一种简单实用的数据传输方案。
//在TLV的定义中,可以知道它包括三个域,分别为:标签域(Tag),长度域(Length),内容域(Value)。这里的长度域的值实际上就是内容域的长度。
//
//解码前 (20 bytes) 解码后 (20 bytes)
//+------------+------------+-----------------+ +------------+------------+-----------------+
//| Tag | Length | Value |----->| Tag | Length | Value |
//| 0x00000001 | 0x0000000C | "HELLO, WORLD" | | 0x00000001 | 0x0000000C | "HELLO, WORLD" |
//+------------+------------+-----------------+ +------------+------------+-----------------+
// Tag: uint32类型,占4字节,Tag作为MsgId,暂定为1
// Length:uint32类型,占4字节,Length标记Value长度12(hex:0x0000000C)
// Value: 共12个字符,占12字节
//
// 说明:
// lengthFieldOffset = 4 (Length的字节位索引下标是4) 长度字段的偏差
// lengthFieldLength = 4 (Length是4个byte) 长度字段占的字节数
// lengthAdjustment = 0 (Length只表示Value长度,程序只会读取Length个字节就结束,后面没有来,故为0,若Value后面还有crc占2字节的话,那么此处就是2。若Length标记的是Tag+Length+Value总长度,那么此处是-8)
// initialBytesToStrip = 0 (这个0表示返回完整的协议内容Tag+Length+Value,如果只想返回Value内容,去掉Tag的4字节和Length的4字节,此处就是8) 从解码帧中第一次去除的字节数
// maxFrameLength = 2^32 + 4 + 4 (Length为uint类型,故2^32次方表示Value最大长度,此外Tag和Length各占4字节)

package examples

import (
"bytes"
"encoding/binary"
"encoding/hex"
"github.com/aceld/zinx/ziface"
"github.com/aceld/zinx/zlog"
"math"
"unsafe"
)

const TLV_HEADER_SIZE = 8 //表示TLV空包长度

type LtvData struct {
Tag uint32
Length uint32
Value string
}

type LTVDecoder struct {
}

func (this *LTVDecoder) GetLengthField() ziface.LengthField {
// +---------------+---------------+---------------+
// | Length | Tag | Value |
// | uint32(4byte) | uint32(4byte) | n byte |
// +---------------+---------------+---------------+
// Length:uint32类型,占4字节,Length标记Value长度
// Tag: uint32类型,占4字节
// Value: 占n字节
//
//说明:
// lengthFieldOffset = 0 (Length的字节位索引下标是0) 长度字段的偏差
// lengthFieldLength = 4 (Length是4个byte) 长度字段占的字节数
// lengthAdjustment = 4 (Length只表示Value长度,程序只会读取Length个字节就结束,后面没有来,故为0,若Value后面还有crc占2字节的话,那么此处就是2。若Length标记的是Tag+Length+Value总长度,那么此处是-8)
// initialBytesToStrip = 0 (这个0表示返回完整的协议内容Tag+Length+Value,如果只想返回Value内容,去掉Tag的4字节和Length的4字节,此处就是8) 从解码帧中第一次去除的字节数
// maxFrameLength = 2^32 + 4 + 4 (Length为uint32类型,故2^32次方表示Value最大长度,此外Tag和Length各占4字节)
//默认使用TLV封包方式
return ziface.LengthField{
MaxFrameLength: math.MaxUint32 + 4 + 4,
LengthFieldOffset: 0,
LengthFieldLength: 4,
LengthAdjustment: 4,
InitialBytesToStrip: 0,
Order: binary.LittleEndian, //好吧,我看了代码,使用的是小端😂
}
}

func (this *LTVDecoder) Intercept(chain ziface.Chain) ziface.Response {
request := chain.Request()
if request != nil {
switch request.(type) {
case ziface.IRequest:
iRequest := request.(ziface.IRequest)
iMessage := iRequest.GetMessage()
if iMessage != nil {
data := iMessage.GetData()
zlog.Ins().DebugF("TLV-RawData size:%d data:%s\n", len(data), hex.EncodeToString(data))
datasize := len(data)
_data := LtvData{}
if datasize >= TLV_HEADER_SIZE {
_data.Length = binary.LittleEndian.Uint32(data[0:4])
_data.Tag = binary.LittleEndian.Uint32(data[4:8])
value := make([]byte, _data.Length)
binary.Read(bytes.NewBuffer(data[8:8+_data.Length]), binary.LittleEndian, value)
_data.Value = string(value)
iMessage.SetMsgID(_data.Tag)
iRequest.SetResponse(_data)
zlog.Ins().DebugF("TLV-DecodeData size:%d data:%+v\n", unsafe.Sizeof(data), _data)
}
}
}
}
return chain.Proceed(chain.Request())
}
13 changes: 9 additions & 4 deletions examples/zinx_client/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package main

import (
"fmt"
"github.com/aceld/zinx/examples"
"github.com/aceld/zinx/examples/zinx_client/c_router"
"github.com/aceld/zinx/ziface"
"github.com/aceld/zinx/zlog"
Expand All @@ -20,7 +21,7 @@ import (
"time"
)

//客户端自定义业务
// 客户端自定义业务
func business(conn ziface.IConnection) {

for {
Expand All @@ -35,7 +36,7 @@ func business(conn ziface.IConnection) {
}
}

//创建连接的时候执行
// 创建连接的时候执行
func DoClientConnectedBegin(conn ziface.IConnection) {
zlog.Debug("DoConnecionBegin is Called ... ")

Expand All @@ -46,7 +47,7 @@ func DoClientConnectedBegin(conn ziface.IConnection) {
go business(conn)
}

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

tlvDecoder := examples.LTVDecoder{}
client.SetLengthField(tlvDecoder.GetLengthField())
client.AddInterceptor(&tlvDecoder) //TVL协议解码器

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

Expand All @@ -83,7 +88,7 @@ func main() {
}

/*
模拟客户端, 不使用client模块方式
模拟客户端, 不使用client模块方式
*/
func main_old() {
conn, err := net.Dial("tcp", "127.0.0.1:8999")
Expand Down
25 changes: 25 additions & 0 deletions examples/zinx_decoder/decode/htlvcrcdecoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/aceld/zinx/examples/zinx_decoder/bili/utils"
"github.com/aceld/zinx/ziface"
"github.com/aceld/zinx/zlog"
"math"
"unsafe"
)

Expand All @@ -42,6 +43,30 @@ type HtlvCrcData struct {
type HtlvCrcDecoder struct {
}

func (this *HtlvCrcDecoder) GetLengthField() ziface.LengthField {
//+------+-------+---------+--------+--------+
//| 头码 | 功能码 | 数据长度 | 数据内容 | CRC校验 |
//| 1字节 | 1字节 | 1字节 | N字节 | 2字节 |
//+------+-------+---------+--------+--------+
//头码 功能码 数据长度 Body CRC
//A2 10 0E 0102030405060708091011121314 050B
//说明:
// 1.数据长度len是14(0E),这里的len仅仅指Body长度;
//
// lengthFieldOffset = 2 (len的索引下标是2,下标从0开始) 长度字段的偏差
// lengthFieldLength = 1 (len是1个byte) 长度字段占的字节数
// lengthAdjustment = 2 (len只表示Body长度,程序只会读取len个字节就结束,但是CRC还有2byte没读呢,所以为2)
// initialBytesToStrip = 0 (这个0表示完整的协议内容,如果不想要A2,那么这里就是1) 从解码帧中第一次去除的字节数
// maxFrameLength = 255 + 4(起始码、功能码、CRC) (len是1个byte,所以最大长度是无符号1个byte的最大值)
return ziface.LengthField{
MaxFrameLength: math.MaxInt8 + 4,
LengthFieldOffset: 2,
LengthFieldLength: 1,
LengthAdjustment: 2,
InitialBytesToStrip: 0,
}
}

func (this *HtlvCrcDecoder) Intercept(chain ziface.Chain) ziface.Response {
request := chain.Request()
if request != nil {
Expand Down
26 changes: 26 additions & 0 deletions examples/zinx_decoder/decode/tlvdecoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"encoding/hex"
"github.com/aceld/zinx/ziface"
"github.com/aceld/zinx/zlog"
"math"
"unsafe"
)

Expand All @@ -38,6 +39,31 @@ type TlvData struct {
type TLVDecoder struct {
}

func (this *TLVDecoder) GetLengthField() ziface.LengthField {
// +---------------+---------------+---------------+
// | Tag | Length | Value |
// | uint32(4byte) | uint32(4byte) | n byte |
// +---------------+---------------+---------------+
// Tag: uint32类型,占4字节
// Length:uint32类型,占4字节,Length标记Value长度
// Value: 占n字节
//
//说明:
// lengthFieldOffset = 4 (Length的字节位索引下标是4) 长度字段的偏差
// lengthFieldLength = 4 (Length是4个byte) 长度字段占的字节数
// lengthAdjustment = 0 (Length只表示Value长度,程序只会读取Length个字节就结束,后面没有来,故为0,若Value后面还有crc占2字节的话,那么此处就是2。若Length标记的是Tag+Length+Value总长度,那么此处是-8)
// initialBytesToStrip = 0 (这个0表示返回完整的协议内容Tag+Length+Value,如果只想返回Value内容,去掉Tag的4字节和Length的4字节,此处就是8) 从解码帧中第一次去除的字节数
// maxFrameLength = 2^32 + 4 + 4 (Length为uint32类型,故2^32次方表示Value最大长度,此外Tag和Length各占4字节)
//默认使用TLV封包方式
return ziface.LengthField{
MaxFrameLength: math.MaxUint32 + 4 + 4,
LengthFieldOffset: 4,
LengthFieldLength: 4,
LengthAdjustment: 0,
InitialBytesToStrip: 0,
}
}

func (this *TLVDecoder) Intercept(chain ziface.Chain) ziface.Response {
request := chain.Request()
if request != nil {
Expand Down
8 changes: 6 additions & 2 deletions examples/zinx_decoder/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,15 @@ func main() {
s.SetOnConnStop(DoConnectionLost)

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

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

//开启服务
Expand Down
15 changes: 10 additions & 5 deletions examples/zinx_heartbeat/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@ package main

import (
"fmt"
"github.com/aceld/zinx/examples"
"github.com/aceld/zinx/ziface"
"github.com/aceld/zinx/znet"
"os"
"os/signal"
"time"
)

//ping test 自定义路由
// ping test 自定义路由
type PingRouter struct {
znet.BaseRouter
}

//Ping Handle
// Ping Handle
func (this *PingRouter) Handle(request ziface.IRequest) {
fmt.Println("Call PingRouter Handle")
//先读取客户端的数据,再回写ping...ping...ping
Expand All @@ -27,7 +28,7 @@ func (this *PingRouter) Handle(request ziface.IRequest) {
*/
}

//客户端自定义业务
// 客户端自定义业务
func business(conn ziface.IConnection) {

for {
Expand All @@ -41,7 +42,7 @@ func business(conn ziface.IConnection) {
}
}

//创建连接的时候执行
// 创建连接的时候执行
func DoClientConnectedBegin(conn ziface.IConnection) {
fmt.Println("DoConnecionBegin is Called ... ")

Expand All @@ -52,7 +53,7 @@ func DoClientConnectedBegin(conn ziface.IConnection) {
go business(conn)
}

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

tlvDecoder := examples.LTVDecoder{}
client.SetLengthField(tlvDecoder.GetLengthField())
client.AddInterceptor(&tlvDecoder) //TVL协议解码器

//启动心跳检测
client.StartHeartBeat(5 * time.Second)

Expand Down
7 changes: 6 additions & 1 deletion examples/zinx_heartbeat/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"fmt"
"github.com/aceld/zinx/examples"
"github.com/aceld/zinx/ziface"
"github.com/aceld/zinx/znet"
"time"
Expand All @@ -11,7 +12,7 @@ type TestRouter struct {
znet.BaseRouter
}

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

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

s.AddRouter(1, &TestRouter{})

tlvDecoder := examples.LTVDecoder{}
s.SetLengthField(tlvDecoder.GetLengthField())
s.AddInterceptor(&tlvDecoder) //LTV协议解码器

//启动心跳检测
s.StartHeartBeat(5 * time.Second)

Expand Down
10 changes: 7 additions & 3 deletions examples/zinx_logger/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"fmt"
"github.com/aceld/zinx/examples"
"github.com/aceld/zinx/examples/zinx_client/c_router"
"github.com/aceld/zinx/ziface"
"github.com/aceld/zinx/zlog"
Expand All @@ -11,7 +12,7 @@ import (
"time"
)

//客户端自定义业务
// 客户端自定义业务
func business(conn ziface.IConnection) {

for {
Expand All @@ -26,7 +27,7 @@ func business(conn ziface.IConnection) {
}
}

//创建连接的时候执行
// 创建连接的时候执行
func DoClientConnectedBegin(conn ziface.IConnection) {
zlog.Debug("DoConnecionBegin is Called ... ")

Expand All @@ -37,7 +38,7 @@ func DoClientConnectedBegin(conn ziface.IConnection) {
go business(conn)
}

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

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

//启动客户端client
client.Start()
Expand Down
Loading

0 comments on commit 21d512a

Please sign in to comment.