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. python3.7 socket通信

    def OpenClient(self,e): global line line = socket.socket(socket.AF_INET,socket.SOCK_STREAM) line.bin ...

  2. C++中vector用法

    在c++中,vector是一个十分有用的容器,下面对这个容器做一下总结. 1 基本操作 (1)头文件#include<vector>. (2)创建vector对象,vector<in ...

  3. vue-gemini-scrollbar(vue组件-自定义滚动条)

    vue-gemini-scrollbar(vue组件-自定义滚动条) https://segmentfault.com/a/1190000013338560

  4. jxcel - 好用的Excel与Java对象转换工具

    更多精彩博文,欢迎访问我的个人博客 Jxcel简介 Jxcel是一个支持Java对象与Excel(目前仅xlsx.xls)互相转换的工具包. 项目地址:https://github.com/jptan ...

  5. AndroidStudio连不上天天模拟器

    问题:天天模拟器经常无法被Android Studio读取出来: 解决方法:手动连接它的端口: 方法一:找到Android\SDK\platform-tools目录,在当前目录下打开命令行窗口(shi ...

  6. sqlserver差异备份3117

    1.出现错误"3117" 2.完整备份/选项/不对数据库执行任何操作 3.数据库显示"正在还原" 4.差异备份/选项/回滚 5.数据库完整备份与差异备份成功

  7. POJ-1011(sticks,深搜)

    Description George took sticks of the same length and cut them randomly until all parts became at mo ...

  8. 深入理解JavaScript的设计模式

    使用适当的设计模式可以帮助你编写更好.更易于理解的代码.这样的代码也更容易维护.但是,重要的是不要过度使用它们.在使用设计模式之前,你应该仔细考虑你的问题是否符合设计模式. 当你开始一个新的项目时,你 ...

  9. Nginx配置ThinkPHP和Laravel虚拟主机

    ThinkPHP server { listen 443 ssl; server_name abc.com; root /var/www/abc; ssl on; ssl_certificate /e ...

  10. post processing in CFD

    post post Table of Contents 1. Post-processing 1.1. Reverse flow 1.1.1. reasons 1.1.2. solutions 1.2 ...