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. IntelliJ IDEA openfire 使用IntelliJ IDEA 部署OPENFIRE 服务端

    用MyEclipse部署OF的步骤,网上有很多,可以自行google,这里要记录的是用据说最好用的JAVA编辑器IntelliJ IDEA来部署OF服务端.试了好多下,终于成功了,记录下. 直接上图吧 ...

  2. Mysql数据库表的迁移和表的复制

    同一台服务器上的,数据库之间的表的迁移: create table db.tablename as select * from db2.tablename; 此sql使用于mysql,从一台服务器上的 ...

  3. JavaEE-06 Servlet基础

    学习要点 Servlet生命周期 Servlet API的常用接口和类 Servlet的部署和配置 Servlet处理用户请求 Servlet JSP回顾 JSP技术开发web应用在服务器端生成网页的 ...

  4. 2015 提高组 信息传递--tarjan找最小环

    P2661 信息传递 题目描述 有 n 个同学(编号为 1 到 n )正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为 i 的同学的信息传递对象是编号为 Ti​ 的同学. ...

  5. (转)浅谈trie树

    浅谈Trie树(字典树)         Trie树(字典树) 一.引入 字典是干啥的?查找字的. 字典树自然也是起查找作用的.查找的是啥?单词. 看以下几个题: 1.给出n个单词和m个询问,每次询问 ...

  6. mysql5.7配置

    my3306.cnf [client] port = 3306   #端口socket = /data/mysql3306/mysql3306.sock   #mysql以socket方式运行的soc ...

  7. js事件默认行为

    事件默认行为: 当一个事件发生的时候浏览器自己默认做的事情 怎么阻止? 当前这个行为是什么事件触发的,然后在这个事件的处理函数中使用 return false; 但是return false 阻止的是 ...

  8. CSS3---box-shadow设置

    1.box-shadow是向盒子添加阴影.支持添加一个或者多个. 2.box-shadow: X轴偏移量 Y轴偏移量 [阴影模糊半径] [阴影扩展半径] [阴影颜色] [投影方式]; 3.注意:ins ...

  9. 使用solrJ创建索引

    sorlJ官方介绍谷歌翻译 SolrJ是一个API,可以让Java应用程序轻松与Solr对话. SolrJ隐藏了很多连接到Solr的细节,并允许您的应用程序通过简单的高级方法与Solr进行交互.  p ...

  10. 实验:iscsi共享存储

    实验名称: iscsi共享存储 实验环境: 我们需要准备一个磁盘,对于这个磁盘我们需要使用,将这个磁盘空间共享给iscsi客户端: 实验需求: 我们这里使用两台服务器来实现iscsi共享存储: 1.指 ...