首页 > 其他分享 >【TLV】一种TLV编码实现

【TLV】一种TLV编码实现

时间:2024-01-23 12:22:37浏览次数:27  
标签:编码 tlv container TLV 实现 TEST root string

项目地址:skullboyer/TLV (github.com)

介绍

TLV节点说明,tag字段高位表示有无嵌套

+-------------------------------------------------------------------------------------------+
|  Single     |  Multi                                                                      |
+-------------------------------------------------------------------------------------------+
|  TLV        |  TL TLV TLV                     |  TL TL TLV TLV                            |
|-----------------------------------------------|-------------------------------------------|
|  0xxx_xxxx  |  1xxx_xxxx 0xxx_xxxx 0xxx_xxxx  |  1xxx_xxxx 1xxx_xxxx 0xxx_xxxx 0xxx_xxxx  |
+-------------------------------------------------------------------------------------------+

使用链表来管理tlv节点

=>create                     =>add                     =>add                     =>add
+-------------------+        +----------------+        +----------------+        +----------------+
|  +-------------+  |        |  +----------+  |        |  +----------+  |        |  +----------+  |
|  |    head     |  |  <-->  |  |   list   |  |  <-->  |  |   list   |  |  <-->  |  |   list   |  |
|  |-------------|  |        |  |   data   |  |        |  |   data   |  |        |  |   data   |  |
|  |     /\      |  |        |  +----------+  |        |  +----------+  |        |  +----------+  |
|  |  tlv_group  |  |        |       /\       |        |       /\       |        |       /\       |
|  +-------------+  |        |    tlv_group1  |        |   tlv_group2   |        |   tlv_groupx   |
|        /\         |        +----------------+        +----------------+        +----------------+
|     container     |
+-------------------+

序列化,即二进制字节流

+-------------------------------------------------+
|   TLVTLVTLVTLTLVTLVTLTLTLVTLVTLTLVTLVTLTLV      |
+-------------------------------------------------+
|   1010101010000101111010010100111000100001'b    |
+-------------------------------------------------+

快速开始

你可以使用本项目提供的脚本 do.sh 来快速的使用本项目

可以使用帮助命令方便查看 ./do.sh help

-*- help -*-
usage: ./do.sh [make] [exec] [mla] [clean] [help]

Example usage of the TLV mechanism
$ ./do.sh make

Check the TLV code for memory leaks
$ ./do.sh mla ON/OFF
$ ./do.sh make

Execute the program to view the results
$ ./do.sh exec (manual/smart)

Remove unnecessary code
$ ./do.sh clean

可以使用编译、执行命令来快速熟悉本项目的用法

$ ./do.sh make
$ ./do.sh exec manual/smart

可以使用MLA命令来检查本项目内存泄漏情况(详见:https://github.com/skullboyer/MLA)

$ ./do.sh mla ON/OFF
$ ./do.sh make
$ ./do.sh exec manual/smart

用法

在使用上分为手动与智能,区别在时间与空间的平衡,以及使用者的便利性,通过处理下述tlv节点来演示两种方式的使用规则

+-------------------------+
|  TLV  || TLV ||   TLV   |
|-------------------------|
|  TLV      @      skull  |
+-------------------------+
+-------------------------------------------------+
|  TL | TLV                               || TLV  |
|-------------------------------------------------|
|       Half a loaf is better than no bread.  天  |
+-------------------------------------------------+
+------------------------------------------------------------ ----------+
|  TL || TL | TLV         | TLV    || TL | TLV                  || TLV  |
|-----------------------------------------------------------------------|
|             All work and  no play        makes Jack a dull boy.  灵   |
+-----------------------------------------------------------------------+
+------------+
|  TL | TLV  |
|------------|
|       盖   |
+------------+

手动(执行顺序即为序列化结果序):

// test.c
int8_t tlv_producer_manual(uint8_t **data)
{
    MAIN_ASSERT(*data == NULL);

    tlv_container_t *container_root = tlv_container_create();
    tlv_t *tlv = NULL;

    // -*- single: TLV TLV TLV -*-
    char *string = "TLV";
    tlv_package(&tlv, tlv_tag_get_low(TEST_TAG01), strlen(string), string);
    tlv_container_push(container_root, tlv);
    tlv_destroy(&tlv);

    string = "@";
    tlv_package(&tlv, tlv_tag_get_low(TEST_TAG02), strlen(string), string);
    tlv_container_push(container_root, tlv);
    tlv_destroy(&tlv);

    string = "skull";
    tlv_package(&tlv, tlv_tag_get_low(TEST_TAG03), strlen(string), string);
    tlv_container_push(container_root, tlv);
    tlv_destroy(&tlv);

    // -*- multi: TL TLV TLV -*-
    tlv_container_t *container = tlv_container_create();
    string = "Half a loaf is better than no bread.";
    tlv_package(&tlv, tlv_tag_get_low(TEST_TAGa1), strlen(string), string);
    tlv_container_push(container, tlv);
    tlv_destroy(&tlv);

    uint32_t value = 0xA9A4E5;
    tlv_package(&tlv, tlv_tag_get_low(TEST_TAGa2), sizeof(value), &value);
    tlv_container_push(container, tlv);
    tlv_destroy(&tlv);

    if (tlv_container_serialize(container) != 0) {
        LOGD("tlv container serialize fail");
    }
    tlv_nested_package(&tlv, tlv_tag_get_high(TEST_TAGa0), container);
    tlv_container_push(container_root, tlv);
    tlv_destroy(&tlv);
    tlv_container_destroy(&container);

    // -*- multi: TL TL TLV TLV TL TLV -*-
    container = tlv_container_create();
    string = "All work and";
    tlv_package(&tlv, tlv_tag_get_low(TEST_TAGca1), strlen(string), string);
    tlv_container_push(container, tlv);
    tlv_destroy(&tlv);

    string = "no play";
    tlv_package(&tlv, tlv_tag_get_low(TEST_TAGca2), strlen(string), string);
    tlv_container_push(container, tlv);
    tlv_destroy(&tlv);

    tlv_container_t *container1 = tlv_container_create();
    if (tlv_container_serialize(container) != 0) {
        LOGD("tlv container serialize fail");
    }
    tlv_nested_package(&tlv, tlv_tag_get_high(TEST_TAGa0), container);
    tlv_container_push(container1, tlv);
    tlv_destroy(&tlv);
    tlv_container_destroy(&container);

    container = tlv_container_create();
    string = "makes Jack a dull boy.";
    tlv_package(&tlv, tlv_tag_get_low(TEST_TAGcb1), strlen(string), string);
    tlv_container_push(container, tlv);
    tlv_destroy(&tlv);

    if (tlv_container_serialize(container) != 0) {
        LOGD("tlv container serialize fail");
    }
    tlv_nested_package(&tlv, tlv_tag_get_high(TEST_TAGb0), container);
    tlv_container_push(container1, tlv);
    tlv_destroy(&tlv);
    tlv_container_destroy(&container);

    value = 0xB581E7;
    tlv_package(&tlv, tlv_tag_get_low(TEST_TAGc1), sizeof(value), &value);
    tlv_container_push(container1, tlv);
    tlv_destroy(&tlv);

    if (tlv_container_serialize(container1) != 0) {
        LOGD("tlv container serialize fail");
    }
    tlv_nested_package(&tlv, tlv_tag_get_high(TEST_TAGc00), container1);
    tlv_container_push(container_root, tlv);
    tlv_destroy(&tlv);
    tlv_container_destroy(&container1);

    // -*- multi: TL TLV -*-
    container = tlv_container_create();
    value = 0x969BE7;
    tlv_package(&tlv, tlv_tag_get_low(TEST_TAGd1), sizeof(value), &value);
    tlv_container_push(container, tlv);
    tlv_destroy(&tlv);

    if (tlv_container_serialize(container) != 0) {
        LOGD("tlv container serialize fail");
    }
    tlv_nested_package(&tlv, tlv_tag_get_high(TEST_TAGd0), container);
    tlv_container_push(container_root, tlv);
    tlv_destroy(&tlv);
    tlv_container_destroy(&container);

    // -*- serialize -*-
    if (tlv_container_serialize(container_root) != 0) {
        LOGD("tlv container_root serialize fail");
    }

智能(序列化结果序取决于Tag定义,与执行顺序无关):

// test.c
int8_t tlv_producer_smart(uint8_t **data)
{
    MAIN_ASSERT(*data == NULL);

    tlv_container_t *container_root = NULL;

    char *string = "TLV";
    tlv_container_handle(&container_root, TEST_TAG01, strlen(string), string);

    string = "@";
    tlv_container_handle(&container_root, TEST_TAG02, strlen(string), string);

    string = "skull";
    tlv_container_handle(&container_root, TEST_TAG03, strlen(string), string);

    string = "Half a loaf is better than no bread.";
    tlv_container_handle(&container_root, TEST_TAGa1, strlen(string), string);

    string = "All work and";
    tlv_container_handle(&container_root, TEST_TAGca1, strlen(string), string);

    string = "no play";
    tlv_container_handle(&container_root, TEST_TAGca2, strlen(string), string);

    uint32_t value = 0xA9A4E5;
    tlv_container_handle(&container_root, TEST_TAGa2, sizeof(value), &value);

    string = "makes Jack a dull boy.";
    tlv_container_handle(&container_root, TEST_TAGcb1, strlen(string), string);

    value = 0xB581E7;
    tlv_container_handle(&container_root, TEST_TAGd1, sizeof(value), &value);

    value = 0x969BE7;
    tlv_container_handle(&container_root, TEST_TAGc1, sizeof(value), &value);

    // -*- serialize -*-
    if (tlv_container_serialize(container_root) != 0) {
        LOGD("tlv container_root serialize fail");
    }

设计

新增tlv节点在tlv-container中存在相同tag的处理逻辑

             root                                             root
            .----------------------.--------.                .-----------------------.--------.
            | T1| T2| ... | Tn| Tm|         |      =>        | T1| T2| ... | Tn'| Tm|         |
            | L | L | ... | L | L |->       |                | L | L | ... | L  | L |->       |
            | V | V | ... | V | V |         |                | V | V | ... | V  | V |         |
            '----------------------'--------'                '-----------------------'--------'
                            |                                                ^
          .---->-----------' `--.                                            | remount
         /     check             \ pick off                                  |
        ^                         v                                          |
      .---.                     .---.                                      .----.
      | T |                     | Tn|                                      | Tn'|
      | L |                     | L |                                      | L  |
      | V |                     | V |                                      | V  |
      '---'                     '---'                                      '----'
       new                        |                                          ^
                               .-' disassembly                               | assembly
                              v                                              |
                         .--------.----.     new   .---.  group   .------------.----.
                         | T1| T2| ... |      +    | T |   =>     | T1| T2| Tx| ... |
                         | L | L | ... |           | L |          | L | L | L | ... |
                         | V | V | ... |           | V |          | V | V | V | ... |
                         '--------'----'           '---'          '------------'----'

示例

示例test.c中演示了一种典型使用场景

  +------------+       +-----------------------+   transfer   +-------------------------+     +------------+
  | TLV encode | ==>   | data package and send | ===========> | data receive and verify | ==> | TLV decode |
  +------------+       +-----------------------+              +-------------------------+     +------------+

共同进步

欢迎大家使用并issue反馈

标签:编码,tlv,container,TLV,实现,TEST,root,string
From: https://www.cnblogs.com/skullboyer/p/17982042

相关文章

  • Layui select实现赋值和主动触发选择时间,及radio实现可取消
    Layuiselect赋值,并主动触发选择事件//Layuiselect赋值,并主动触发选择事件//Input:selectId:ID选择器,selectFilter:lay-filter名称,value:需要的赋值,text:显示文本值functionsetSelect(selectId,selectFilter,value,text){//赋值$(selectId).find("option[va......
  • .NET 6 实现一个任务队列,且在不同线程中调用队列,队列始终都是串行执行
    在.NET6中,要实现一个任务队列,确保队列中的任务始终串行执行,即使它们是由不同线程调用的,你可以使用Channel<T>结合Task.Run或者更简单地使用BlockingCollection<T>与Task.Factory.StartNew或async/await模式。不过,为了保持代码的简洁性和现代性,我会推荐使用Channel<T>结合async/aw......
  • 无公网IP也可以实现宝塔FTP文件服务远程连接(提高运维效率!!)
    宝塔FTP是宝塔面板中的一项功能,用于设置和管理FTP服务。通过宝塔FTP,用户可以创建FTP账号,配置FTP用户权限,并进行文件上传、下载和删除等操作.cpolar是一种安全的内网穿透云服务,可以将内网下的本地服务器通过安全隧道暴露至公网,使得公网用户可以正常访问内网服务。下面介绍宝塔FTP......
  • 如何在OriginBot上实现人脸识别
    转载自古月居编辑:东岸因为@一点人工一点智能01  人脸识别大家在生活中经常会看到在我们进入商城时,门口会有相机在拍摄我们,并且会统计有多少人数进入商店,它是如何进行人数量统计的呢?这就是是计算机视觉领域的一项关键技术——人脸识别,它使计算机系统能够自动检测、识别和验证图像......
  • C#对象二进制序列化优化:位域技术实现极限压缩
    目录1.引言2.优化过程2.1.进程对象定义与初步分析2.2.排除Json序列化2.3.使用BinaryWriter进行二进制序列化2.4.数据类型调整2.5.再次数据类型调整与位域优化3.优化效果与总结1.引言在操作系统中,进程信息对于系统监控和性能分析至关重要。假设我们需要开发一个监控程序......
  • 使用promise实现延迟与回调。以及为什么使用promise实现延迟
    简单延迟几秒functiondelay(seconds){returnnewPromise(resolve=>setTimeout(resolve,seconds*1000));}//使用这个函数来延迟1秒delay(1).then(()=>{console.log('1秒已经过去了!');});简化版functiondelay(seconds){returnnewP......
  • Spring Cloud 系列:Seata 中TCC模式具体实现
    概述https://seata.io/zh-cn/docs/dev/mode/tcc-modehttps://seata.io/zh-cn/docs/user/mode/tccTCC模式与AT模式非常相似,每阶段都是独立事务,不同的是TCC通过人工编码来实现数据恢复。需要实现三个方法:Try:资源的检测和预留;Confirm:完成资源操作业务;要求Try成功Confirm一......
  • Java21 + SpringBoot3集成easy-captcha实现验证码显示和登录校验
    目录前言相关技术简介easy-captcha实现步骤引入maven依赖定义实体类定义登录服务类定义登录控制器前端登录页面实现测试和验证总结附录使用Session缓存验证码前端登录页面实现代码前言近日心血来潮想做一个开源项目,目标是做一款可以适配多端、功能完备的模板工程,包含后台管理系......
  • 怎样才能实现私域流量的增长?
    为了优化私域流量增长,以下策略可能有效:1.价值吸引,而非仅仅是免费:采用免费策略吸引用户是常见做法,但关键在于通过高价值或服务提升用户体验,确保用户在“获取”免费产品过程中感受到真正的价值。精心策划价值传递,建立用户期望,确保用户体验后能够自发传播正面口碑,为产品或服务提供良......
  • VUE框架CLI组件化配置Router路由局部守卫path和componet和router完整项目实现------VU
    <template><div><!--组件分为普通组件和路由组件--><divclass="s2"><h2>县区</h2><ul><!--query形式接收--><!--<li>{{$route.......