TLV 格式及编解码示例
来源:互联网 发布:淘宝 断码鞋 编辑:程序博客网 时间:2024/04/28 21:44
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)。
下面是我写的一个Demo程序:
#include <stdio.h>#include <WinSock2.h>#include <string>#pragma comment(lib, "WS2_32")enum emTLVNodeType{emTlvNNone = 0,emTlvNRoot,//根节点emTlvName,//名字emTlvAge,//年龄emTlvColor//颜色 1 白色 2 黑色};typedef struct _CAT_INFO{char szName[12];intiAge;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(const void *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);return true;}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 VT L V T L V T L VL1 的长度即为“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); //根节点emTlvNRoot中的L,20=4+4+12,12=4+4+4,12=4+4+4enc.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; //总长度再加上emTLVNRoot的T和L,8=4+4return 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;}
本Demo程序在VC2005环境下编译通过,下面是运行结果截图
- TLV 格式及编解码示例
- 【通信】TLV 格式及编解码示例
- TLV 格式及编解码示例
- TLV格式及编解码示例
- TLV 格式及编解码示例
- TLV 格式及编解码示例
- TLV编解码【编程】
- PBOC-TLV编码格式解码
- TLV 格式及编码
- TLV格式及编码
- TLV 格式及编码
- TLV 格式及编码
- 【TLV格式及编码】
- TLV 格式及编码
- TLV格式及编码
- APE格式及编解码说明
- URL编解码示例
- 华为编程大赛——TLV编解码
- [非技术]---开篇---
- php面向对象
- DW删除记录(3)
- View 拖动&插入 研究
- DW删除记录(4)
- TLV 格式及编解码示例
- [Java]JAVA获取实体与List 数组的转换
- Linux-简介
- GDI+图像处理学习笔记——改变图像的透明度
- 浅析为何要内存对齐(by liukun321咕唧咕唧)
- Java正则表达式详解
- VC内存泄露检查工具Visual Leak Detector介绍
- 一道容易出错的招聘笔试题
- 看了之后,有点感触 。。。