TLV协议的装包与解包(C语言)

本文介绍了TLV(Tag-Length-Value)协议的基本概念,包括其报文格式和在数据传输中防止错误的方法。通过在字节流末尾添加CRC校验来确保数据的完整性。接着详细讲解了TLV的封包和解包过程,封包涉及如何将数据转换为TLV格式,而解包则阐述了如何从接收到的字节流中正确解析出TLV元素,包括校验CRC以验证数据准确性。
摘要由CSDN通过智能技术生成

1.TLV简介

TLV :即Tag(Type)-Length-Value,它包含三个域,第一个Tag为要封装的数据的类型域,第二个Length为封装的总的数据长度,第三个Value为要装入数据的值。其实就是一个简单的自定义通信协议,将要传送的数据进行编码组织将其发送出去的过程。
在这里插入图片描述
这是基本的tlv报文格式,在实际应用中我们可能会碰见在传输过程中数据发生跳变,这时候我们需要在一个字节流末尾加一个CRC校验,传输前算一下字节流的大小,传输到另外一个端口后再算一下,对比前后两个CRC的值,如果相同,表示没有发生字节跳变,反之,则舍弃。
加工后tlv报文:
在这里插入图片描述
PACK_HEADE是自己定义的(0xFD),大小通常为一个字节;Tag也是自己定义,通常为一个字节;Length的大小要看你的数据所占用的字节大小,它的大小为包头大小+Tag大小+Length大小+校验和大小+数据字节大小,自身一般占用一个字节;crc校验和一般占两个字节。发送过程中如果不加头,发送的数据0x05 0x02 0x3c,在接收端就会以Tag(Type)-Length-Value顺序进行解析,正常情况下可以获取到正确的值,但是当发生数据跳变或者混入其他数据时,接收端按照之前的顺序解析就会出错,当我们加上头的时候,接收端解析的时候会先找到包头,然后按顺序解析,但是这样还是有出错的可那,但是加上crc校验和之后,crc根据接收到的数据计算出一个校验和,用来和装包装进去的校验和进行比较,如果相同说明这一帧数据正确,接收端才会开始解析数据,如果不正确就不解析。

2.TLV的封包

下面是我对获取到的温度进行装包的代码:

 int  packtlv_temp(char *buf, int size)
 {
   
     unsigned short crc16=0;
     int     pack_len = 0;
     int     data_len = 0;
     int     ofset = 0;
     float   temp;
     char    datatime[32];
     int     i,j;
  
      if(!buf || size < TLV_MINI_SIZE)
      {
   
  
          printf("Invalid input adgument\n");
          return 0;
  
      }
           /*   Packet head */ 
      buf[ofset]=HEAD;
      ofset +=1;
  
       /*   Tag */ 
      buf[ofset]=TAG_TEMP;
      ofset 
TLV (Type-Length-Value) 是一种数据封装格式,在很多通信协议数据结构中广泛使用,特别是网络、配置文件和数据存储等领域。C语言中处理TLV数据通常涉及以下几个步骤: 1. 定义结构:在C语言里,你可以创建一个结构体,包含三个字段:type(类型标识)、length(长度)和value(值)。例如: ```c typedef struct { uint8_t type; uint16_t length; void* value; // 指向实际数据的位置 } TlvEntry; ``` 2. 编码:对于不同类型的数据,你可以编写函数来将它们编码成TLV格式。比如添加整数、字符串或自定义结构体到`TlvEntry`中。 ```c void encode_int(TlvEntry* entry, int value) { entry->type = ...; // 根据需要设置类型 entry->length = htons(sizeof(int)); // 高16位表示长度,使用htons转换网络字节序 entry->value = &((uint16_t*)entry->value)[0]; // 存储int的地址 *((uint16_t*)entry->value) = htonl(value); // 转换并存储值 } void encode_string(TlvEntry* entry, const char* str) { entry->type = ...; entry->length = htons(strlen(str) + 1); // 包含NULL终止符 entry->value = ...; // 存储字符串的地址 memcpy(entry->value, str, strlen(str)); } ``` 3. 解码:从接收到的TLV数据中,可以遍历每个条目并提取信息。 ```c void decode_tlv(const TlvEntry* entries, size_t count) { for (size_t i = 0; i < count; i++) { switch (entries[i].type) { case TYPE_INTEGER: printf("Integer: %d\n", ntohl(*((uint16_t*)entries[i].value))); break; case TYPE_STRING: printf("String: %s\n", (char*)entries[i].value); break; // 其他类型处理... } } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值