转:TLV 格式及编解码示例
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 格式及编解码示例的更多相关文章
- RocketMq通信协议格式及编解码 (源码分析)
一.RocketMq broker服务器与客户端的网络通信是基于netty4.x实现的,重点分析 RocketMq设计的通信协议及对应的编解码 开发. 名字解释 ...
- DLib库Base64编解码示例
代码 #include <iostream> #include <fstream> #include <sstream> #include <string&g ...
- Thrift源码分析(二)-- 协议和编解码
协议和编解码是一个网络应用程序的核心问题之一,客户端和服务器通过约定的协议来传输消息(数据),通过特定的格式来编解码字节流,并转化成业务消息,提供给上层框架调用. Thrift的协议比较简单,它把协议 ...
- Notepad++插件Base64编解码
我们平常进行Base64编码需要自己写代码转换, 或者使用其他人编写的小工具程序, 也可以使用在线base64编码工具, 现在我们还可以使用Notepad++自带的插件, 进行Base64编码和解码, ...
- 各种音视频编解码学习详解 h264 ,mpeg4 ,aac 等所有音视频格式
编解码学习笔记(一):基本概念 媒体业务是网络的主要业务之间.尤其移动互联网业务的兴起,在运营商和应用开发商中,媒体业务份量极重,其中媒体的编解码服务涉及需求分析.应用开发.释放 license收费等 ...
- H.264格式,iOS硬编解码 以及 iOS 11对HEVC硬编解码的支持
H.264格式,iOS硬编解码 以及 iOS 11对HEVC硬编解码的支持 1,H.264格式 网络表示层NAL,如图H.264流由一帧一帧的NALU组成: SPS:序列参数集,作用于一系列连续的编码 ...
- 视音频编解码学习工程:TS封装格式分析器
=====================================================视音频编解码学习工程系列文章列表: 视音频编解码学习工程:H.264分析器 视音频编解码学习工 ...
- 视音频编解码学习工程:AAC格式分析器
=====================================================视音频编解码学习工程系列文章列表: 视音频编解码学习工程:H.264分析器 视音频编解码学习工 ...
- 视音频编解码学习工程:FLV封装格式分析器
===================================================== 视音频编解码学习工程系列文章列表: 视音频编解码学习工程:H.264分析器 视音频编解码学习 ...
随机推荐
- zabbix设置多个收件人
1.建群组 2.添加群组权限 3.添加用户,归属到上面新建的组 4.动作里发送消息给新建的组 5.这样设置后,管理员账号不用设置收件媒介
- 1.入手树莓派之linux环境搭建
最近刚刚买了一款 树莓派3代B型 raspberrypi 板载蓝牙和WIFI 英国版本,没玩过,觉得很好奇,生怕记性不好哈,把自己玩的过程记录一下,以备不时之需: 需要材料: 1) 树莓派: 2)sd ...
- 用固定长度的数组实现stack queue
package my_basic.class_3; /** * 用数组结构实现大小固定的队列和栈 */ public class Code_01_Array_stack_queue { public ...
- No-3.Linux 终端命令格式
Linux 终端命令格式 01. 终端命令格式 command [-options] [parameter] 说明: command:命令名,相应功能的英文单词或单词的缩写 [-options]:选项 ...
- 12scrapy_redis
一.简介 1.redis redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zse ...
- Docker安装Oracle12C,导入dmp文件出现ORA-12170错误
oracle版本为 sath89/oracle-12c oracle基本信息 hostname: localhost port: 1521 sid: xe username: system passw ...
- 怎么给xshell服务配置密钥远程登陆
xshell密钥登陆 1.找一台测试服务器xiuxiu-test生成密钥对2. cd ./.ssh/ && 把公钥放在~/.ssh/authorized_keys文件中 cat id ...
- KVM中的网络简介(qemu-kvm)
emu-kvm主要向客户机提供了如下4种不同模式的网络: 1)基于网桥(bridge)的虚拟网卡 2)基于NAT(Network Addresss Translation)的虚拟网络 3)QEMU内置 ...
- 我的Python分析成长之路1
Python是什么? ...
- Codeforces 5D Follow Traffic Rules
[题意概述] 某个物体要从A途经B到达C,在通过B的时候速度不能超过vd. 它的加速度为a,最大速度为vm:AB之间距离为d,AC之间距离为L: 问物体最少花多少时间到达C. [题解] 分情况讨论. ...