• 转: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. "); 
    •             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. ",iLen); 
    •     } 
    •     else 
    •     { 
    •         printf("TLV_EncodeCat error "); 
    •     } 
    •  
    •     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. ",cat.szName,cat.iAge,cat.iColor); 
    •     } 
    •     else 
    •     { 
    •         printf("TLV_DecodeCat error, code = %d. ", iRet); 
    •     } 
    •  
    •     int iWait = getchar(); 
    •     return 0; 

     

    有志者事竟成
  • 相关阅读:
    Android H5混合开发(5):封装Cordova View, 让Fragment、弹框、Activity自由使用Cordova
    机器学习 AI 谷歌ML Kit 与苹果Core ML
    Android 设备唯一标识(多种实现方案)
    Android自定义控件:图形报表的实现(折线图、曲线图、动态曲线图)(View与SurfaceView分别实现图表控件)
    Android 禁止截屏、录屏 — 解决PopupWindow无法禁止录屏问题
    Android原生PDF功能实现:PDF阅读、PDF页面跳转、PDF手势伸缩、PDF目录树、PDF预览缩略图
    某助手验证码通信交互包分析
    IOS弓箭传说的插件开发
    微店APP协议简要分析
    Owhat sign参数分析
  • 原文地址:https://www.cnblogs.com/dancheblog/p/3759338.html
Copyright © 2020-2023  润新知