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. Tomcat7的安装与配置

    Tomcat的安装及配置我曾经使用过tomcat,并实现了一个简单的servlet程序.没想到再次安装tomcat的时候用浪费了我大半天的时间.我想有必要做个总结,否则下次不知又要花费我多少时间. 1 ...

  2. fork后子进程从哪里开始执行

    子进程和父进程都从调用fork函数的下一条语句开始执行

  3. Python3简明教程(十四)—— Collections模块

    collections 是 Python 内建的一个集合模块,提供了许多有用的集合类. 在这个实验我们会学习 Collections 模块.这个模块实现了一些很好的数据结构,它们能帮助你解决各种实际问 ...

  4. 关于在Qt里让程序休眠一段时间的方法总结

    出处:http://hanzhaoxin.cnblogs.com/ Qt 为何没有提供 Sleep 论坛上不时见到有人问: Qt 为什么没有提供跨平台的 sleep 函数? 使用平台相关的 Sleep ...

  5. Linux常用命令大全3

    linux命令1,关机shutdown -h now2,init 0 关闭系统3,shutdown -h hours:minutes &按预定时间关闭系统4,shutdown -c取消按预定时 ...

  6. android滚动图片

    关于广告轮播,大家肯定不会陌生,它在现手机市场各大APP出现的频率极高,它的优点在于"不占屏",可以仅用小小的固定空位来展示几个甚至几十个广告条,而且动态效果很好,具有很好的用户& ...

  7. RN传参的问题

    RN父组件通过props属性给子组件传参,假设参数 target={target} 子组件在render函数里 let { target } = this.props; 如果子组件有个 FlatLis ...

  8. Java多线程的内存模型和Thread状态切换

    线程的内存模型 32位操作系统的寻址空间为2的32次方,也就是4GB的寻址空间:系统在这4GB的空间里划分出1GB的空间给系统专用,称作内核空间,具有最高权限:剩下3GB的空间为用户空间(一般JVM的 ...

  9. 在Windows上安装和配置Jenkins

    一.windows上安装Jenkins 1.官网下载Jenkins安装包Jenkins.msi ,进入安装模式,选择默认配置,安装完成之后,就会默认打开浏览器 http://localhost:808 ...

  10. Nowcoder 106 C.Professional Manager(统计并查集的个数)

    题意: 给出四种操作: 1. 合并u,v两棵树 2. 从u所在的集合中删除u 3. 询问u所在集合有多少颗树 4. 询问 u,v是否在同一个集合 分析: 对于删除操作, 只要新开一个点代替原来的点即可 ...