TLV是一种可变格式,意思就是:

Type类型, Lenght长度,Value值;

Type和Length的长度固定,一般那是2、4个字节(这里统一采用4个字节);

Value的长度有Length指定;

编码方法:

1.       将类型type用htonl转换为网络字节顺序,指针偏移+4

2.       将长度length用htonl转换为网络字节顺序,指针偏移+4

3.       若值value数据类型为int、char、short,则将其转换为网络字节顺序,指针偏移+4;若值为字符串类型,写进后,指针偏移+length

……继续处理后面的tlv;

解码方法:

1.       读取type 用ntohl转换为主机字节序得到类型,指针偏移+4

2.       读取lengh用ntohl转换为主机字节序得到长度;指针偏移+4

3.       根据得到的长度读取value,若value数据类型为int、char、short,用ntohl转换为主机字节序,指针偏移+4;若value数据类型为字符串类型,指针偏移+length

……继续处理后面的tlv;

类型(Type)字段是关于标签和编码格式的信息;

长度 (Length)字段定义数值的长度;

内容(Value)字段表示实际的数值。

因此,一个编码值又称TLV(Type,Length,Value)三元组。编码可以是基本型或结构型,如果它表示一个简单类型的、完整的显式值,那么编码就是基本型 (primitive);如果它表示的值具有嵌套结构,那么编码就是结构型 (constructed)。

  • #include <stdio.h>
  • #include <WinSock2.h>
  • #include <string>
  • #pragma comment(lib, "WS2_32")
  • enum emTLVNodeType
  • {
  • emTlvNNone = 0,
  • emTlvNRoot,         //根节点
  • emTlvName,          //名字
  • emTlvAge,           //年龄
  • emTlvColor          //颜色 1 白色 2 黑色
  • };
  • typedefstruct _CAT_INFO
  • {
  • char szName[12];
  • int iAge;
  • int iColor;
  • }CAT_INFO,*LPCAT_INFO;
  • class CTlvPacket
  • {
  • public:
  • CTlvPacket(char *pBuf,unsigned int len):m_pData(pBuf),m_uiLength(len),m_pEndData(m_pData+len),m_pWritePtr(m_pData),m_pReadPtr(m_pData) { }
  • ~CTlvPacket() { }
  • bool WriteInt(int data,bool bMovePtr = true)
  • {
  • int tmp = htonl(data);
  • return Write(&tmp,sizeof(int));
  • }
  • bool Write(constvoid *pDst,unsigned int uiCount)
  • {
  • ::memcpy(m_pWritePtr,pDst,uiCount);
  • m_pWritePtr += uiCount;
  • return m_pWritePtr < m_pEndData ? true : false;
  • }
  • bool ReadInt(int *data,bool bMovePtr = true)
  • {
  • Read(data,sizeof(int));
  • *data = ntohl(*data);
  • returntrue;
  • }
  • bool Read(void *pDst,unsigned int uiCount)
  • {
  • ::memcpy(pDst,m_pReadPtr,uiCount);
  • m_pReadPtr += uiCount;
  • return m_pReadPtr < m_pEndData ? true : false;
  • }
  • private:
  • char *m_pData;
  • unsigned int m_uiLength;
  • char *m_pEndData;
  • char *m_pWritePtr;
  • char *m_pReadPtr;
  • };
  • /*
  • 格式:
  • root L1 V
  • T L V T L V T L V
  • L1 的长度即为“T L V T L V T L V”的长度
  • */
  • int TLV_EncodeCat(LPCAT_INFO pCatInfo, char *pBuf, int &iLen)
  • {
  • if (!pCatInfo || !pBuf)
  • {
  • return -1;
  • }
  • CTlvPacket enc(pBuf,iLen);
  • enc.WriteInt(emTlvNRoot);
  • enc.WriteInt(20+12+12); //length
  • enc.WriteInt(emTlvName);
  • enc.WriteInt(12);
  • enc.Write(pCatInfo->szName,12);
  • enc.WriteInt(emTlvAge);
  • enc.WriteInt(4);
  • enc.WriteInt(pCatInfo->iAge);
  • enc.WriteInt(emTlvColor);
  • enc.WriteInt(4);
  • enc.WriteInt(pCatInfo->iColor);
  • iLen = 8+20+12+12;
  • return 0;
  • }
  • int TLV_DecodeCat(char *pBuf, int iLen, LPCAT_INFO pCatInfo)
  • {
  • if (!pCatInfo || !pBuf)
  • {
  • return -1;
  • }
  • CTlvPacket encDec(pBuf,iLen);
  • int iType;
  • int iSum,iLength;
  • encDec.ReadInt(&iType);
  • if (emTlvNRoot != iType)
  • {
  • return -2;
  • }
  • encDec.ReadInt(&iSum);
  • while (iSum > 0)
  • {
  • encDec.ReadInt(&iType);
  • encDec.ReadInt(&iLength);
  • switch(iType)
  • {
  • case emTlvName:
  • encDec.Read(pCatInfo->szName,12);
  • iSum -= 20;
  • break;
  • case emTlvAge:
  • encDec.ReadInt(&pCatInfo->iAge);
  • iSum -= 12;
  • break;
  • case emTlvColor:
  • encDec.ReadInt(&pCatInfo->iColor);
  • iSum -= 12;
  • break;
  • default:
  • printf("TLV_DecodeCat unkonwn error. \n");
  • break;
  • }
  • }
  • return 0;
  • }
  • int main(int argc, char* argv[])
  • {
  • int iRet, iLen;
  • char buf[256] = {0};
  • CAT_INFO cat;
  • memset(&cat,0,sizeof(cat));
  • strcpy(cat.szName,"Tom");
  • cat.iAge = 5;
  • cat.iColor = 2;
  • iRet = TLV_EncodeCat(&cat,buf,iLen);
  • if ( 0 == iRet )
  • {
  • printf("TLV_EncodeCat ok, iLen = %d. \n",iLen);
  • }
  • else
  • {
  • printf("TLV_EncodeCat error \n");
  • }
  • memset(&cat,0,sizeof(cat));
  • iRet = TLV_DecodeCat(buf,iLen,&cat);
  • if ( 0 == iRet )
  • {
  • printf("TLV_DecodeCat ok, cat name = %s, age = %d, color = %d. \n",cat.szName,cat.iAge,cat.iColor);
  • }
  • else
  • {
  • printf("TLV_DecodeCat error, code = %d. \n", iRet);
  • }
  • int iWait = getchar();
  • return 0;
  • }

转:TLV 格式及编解码示例的更多相关文章

  1. RocketMq通信协议格式及编解码 (源码分析)

    一.RocketMq broker服务器与客户端的网络通信是基于netty4.x实现的,重点分析  RocketMq设计的通信协议及对应的编解码 开发.         名字解释           ...

  2. DLib库Base64编解码示例

    代码 #include <iostream> #include <fstream> #include <sstream> #include <string&g ...

  3. Thrift源码分析(二)-- 协议和编解码

    协议和编解码是一个网络应用程序的核心问题之一,客户端和服务器通过约定的协议来传输消息(数据),通过特定的格式来编解码字节流,并转化成业务消息,提供给上层框架调用. Thrift的协议比较简单,它把协议 ...

  4. Notepad++插件Base64编解码

    我们平常进行Base64编码需要自己写代码转换, 或者使用其他人编写的小工具程序, 也可以使用在线base64编码工具, 现在我们还可以使用Notepad++自带的插件, 进行Base64编码和解码, ...

  5. 各种音视频编解码学习详解 h264 ,mpeg4 ,aac 等所有音视频格式

    编解码学习笔记(一):基本概念 媒体业务是网络的主要业务之间.尤其移动互联网业务的兴起,在运营商和应用开发商中,媒体业务份量极重,其中媒体的编解码服务涉及需求分析.应用开发.释放 license收费等 ...

  6. H.264格式,iOS硬编解码 以及 iOS 11对HEVC硬编解码的支持

    H.264格式,iOS硬编解码 以及 iOS 11对HEVC硬编解码的支持 1,H.264格式 网络表示层NAL,如图H.264流由一帧一帧的NALU组成: SPS:序列参数集,作用于一系列连续的编码 ...

  7. 视音频编解码学习工程:TS封装格式分析器

    =====================================================视音频编解码学习工程系列文章列表: 视音频编解码学习工程:H.264分析器 视音频编解码学习工 ...

  8. 视音频编解码学习工程:AAC格式分析器

    =====================================================视音频编解码学习工程系列文章列表: 视音频编解码学习工程:H.264分析器 视音频编解码学习工 ...

  9. 视音频编解码学习工程:FLV封装格式分析器

    ===================================================== 视音频编解码学习工程系列文章列表: 视音频编解码学习工程:H.264分析器 视音频编解码学习 ...

随机推荐

  1. loadrunner:文本检查点web_reg_find和web_find两个函数的区别

    web_reg_find是先注册(register)后查找的:使用时将它放在请求语句的前面. 而web_find是查找前面的请求结果:使用时将它放在请求语句的后面. 另二者的参数也完成不一样的,web ...

  2. HTTP 200 OK和HTTP 304 Not modified的由来

    这两个字段都和HTTP协议的缓存控制相关. 浏览器缓存机制是通过HTTP协议Header里的Cache-Control(或Expires)和Last-Modified(或 Etag)等字段来实现. 这 ...

  3. 如何破解密码的哈希值,破解双MD5密码值

    这是关于我如何破解密码的哈希值1亿2200万* John the Ripper和oclHashcat-plus故事. 这是几个月前,当我看到一条推特:从korelogic约含共1亿4600万个密码的密 ...

  4. xcode uml 工具

    https://github.com/PaulTaykalo/objc-dependency-visualizer ./generate-objc-dependencies-to-json.rb -d ...

  5. Window服务程序(windows service application)如何调试

    服务程序不能通过常规的按F5或F11的方式来进行调试和运行,也无法立即运行一个服务或逐步调试它的代码. 因此,你必须安装并启动你的服务,然后附属(attach)一个Debugger到这个服务的进程上.

  6. Spring boot 项目打成war包并在idea中运行

    1. 修改pom文件原来是jar改成<packaging>war</packaging> 2. 在pom文件中添加移除内置tomcat并且添加添加servlet-api的依赖. ...

  7. docker运行时设置redis密码并替换redis默认的dump.rdb

    docker run -itd --name test -p 6379:6379 -v /tmp/dump.rdb:/data/dump.rdb redis:4.0.8 --requirepass ' ...

  8. django--基础操作

    Django基础操作 django常用命令 创建django项目 django-admin startproject mysite 创建项目完成以后,文件目录结构为: 修改settings文件内容 A ...

  9. Python开发环境之pyenv环境搭建

    首先到Github上下载Pyenv相应的一键安装脚本, 安装完毕,设置环境变量,设置环境变量,可以添加到个人家目录的.bashrc或.bash_profile及系统的全局的/etc/profile, ...

  10. 杭电 2141 Can you find it? (二分法)

    Description Give you three sequences of numbers A, B, C, then we give you a number X. Now you need t ...