zoukankan      html  css  js  c++  java
  • 项目管理理论与实践系列文章索引

    项目管理理论与实践(1)——企业项目管理介绍

    项目管理理论与实践(2)——软件需求分析

    项目管理理论与实践(3)——如何进行有效的项目管理

    项目管理理论与实践(4)——UML应用(上)

    项目管理理论与实践(5)——UML应用(下)

    项目管理理论与实践(6)——利用Excel制作项目文档的设计技巧

    项目管理理论与实践(7)——软件开发报价的计算方法

    待续

    作者:Leepy
     
    邮箱:sunleepy(AT)gmail.com
     
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。

    金融系统中PBOC/EMV的TLV的算法实现(含C++/C#)

          TLV即Tag-Length-Value,常在IC卡与POS终端设备中通过这样的一个应用通信协议进行数据交换。在金融系统以及认证中,PBOC以及 EMV的认证规范文档上面也有对TLV做了一些说明,由于认证规范都是英文文档,所以有些人可能不易于理解。首先我先介绍下什么是TLV,TLV的用途是 什么,以及如何实现它的打包解包算法。

          金融系统中的TLV是BER-TLV编码的一个特例编码规范,而BER-TLV是ISO定义中的规范。在TLV的定义中,可以知道它包括三个域,分别为:标签域(Tag),长度域(Length),内容域(Value)。这里的长度域的值实际上就是内容域的长度

          其实,在BER编码的方式有两种情况,一种是确定长度的方式,一种是不确定长度的方式,而金融TLV选择了确定长度的方式,这样在设备之间的数据传输量上就可以减少。

    Tag域说明:

          先来看下TLV的Tag是如何编码的,先看下图:

    image

    这张图说明了Tag域第一个字节的编码格式。其中b8-b1代表1个字节中的8个位。

    其中b8,b7代表数据的类别。根据2个位的组合,有四种类别:通用类别,应用类别,上下文语境类别,专用类别。这个主要用于在于终端设备交互的时候,确定数据处理的类型。

    b6代表的是数据元结构,也就是说它是属于简单数据元结构,还是属于结构(复合)数据元结构。当b6为1的时候,就需要后续的字节进行扩展。也就是说复合的TLV中,value域里也包含一个或多个TLV,这个稍后接着介绍。

    当b5-b1代表串行号,当5个位都为1时,需要将tag域扩展到下一个字节中,也就是Tag占2个字节;而当5个位都不全为1时,该Tag域就只占1个字节。

          现在,看下b5-b1:11111的情况:

    image

          从图中我们看到BER-TLV编码中,当b8为1时,Tag还需要有后续字节,直到b8为0为止。从EMV文档中的说明,Tag最多只占用2个字节,所以这样就相对比较简单一些了。当b8为0时,该Tag域结束,总共就占用2个字节。

    Length域说明:

          在文档中没有图片叙述,我自绘一个:

    image

    当b8为0时,该字节的b7-b1作为value域的长度;当b8为1时,b7-b1作为后续字节的长度,也就是说,例如有这样一个 值:10000011,代表后续还有3个字节作为value域的长度(本字节不算,本字节变为作为一个Length的索引)。3个字节代表value的长 度,意味着什么呢,意味着内容的长度当需要很大的时候,字节的位数就会跟着越高,3个字节就代表最大可以有256*256*256的长度。

    Value域说明:

          也是分成两种情况考虑,就是前面说到的Tag分成两个数据元结构,一种是简单数据元结构,一种是复合数据元架构:

          先来看看简单数据元结构:

          image

    Tag就是Tag,没有子标签Tag,基本结构就是T-L-V。

          再看下符合数据元结构:

    image

    后面的Value说明:Primitive or constructed BER-TLV data object number,包含一个简单数据元结构或者也可以是一个符合数据元结构。这样可以看出,算法中必须要实现Tag的嵌套功能,递归算法不可少。

    算法实现:

          根据以上的说明现在来实现它的打包解包的算法(打包的目的是将一个从终端上发的请求数据——字节数组,构造成一系列的TLV结构实体;解包的目的刚好相反,就是将TLV结构实体解析成字节数组,然后通过IC卡发送到终端上)。

          首先定义一个TLV结构实体:

    1 // TLV结构体
    2 struct TLVEntity {
    3     unsigned char* Tag;         //标记
    4     unsigned char* Length;      //数据长度
    5     unsigned char* Value;       //数据
    6     unsigned int TagSize;       //标记占用字节数
    7     unsigned int LengthSize;    //数据长度占用字节数
    8     TLVEntity* Sub_TLVEntity;   //子嵌套TLV实体
    9 };
    其 中TagSize代表Tag字段的字节长度,LengthSize代表Length的字节长度,这里的Length记住要使用char*,由于前面说 过,Length可能包含多个字节,通过多个字节确定Value域的长度,Sub_TLVEntity作为子嵌套的TLV结构体。

          定义一个TLVPackage的打包类:

    TLVPackage.h:

    01 // TLV打包类
    02 class TLVPackage
    03 {
    04 public:
    05     TLVPackage();
    06     virtual ~TLVPackage();
    07     //构造TLV实体
    08     static void Construct(unsigned char* buffer, unsigned int bufferLength, TLVEntity* tlvEntity, unsigned int& entityLength, unsigned int status=0);
    09     //解析TLV字节数组
    10     static void Parse(TLVEntity* tlvEntity, unsigned int entityLength, unsigned char* buffer, unsigned int& bufferLength);
    11 };

    具体方法实现:

    001 // 构造TLV
    002 void TLVPackage:: Construct(
    003     unsigned char* buffer,
    004     unsigned int bufferLength,
    005     TLVEntity* tlvEntity,
    006     unsigned int& entityLength,
    007     unsigned int status
    008     )
    009 {
    010     int currentTLVIndex = 0;
    011     int currentIndex = 0;
    012     int currentStatus = 'T'; //状态字符
    013     unsigned long valueSize = 0;
    014  
    015     while(currentIndex < bufferLength)
    016     {
    017         switch(currentStatus)
    018         {
    019         case 'T':
    020             valueSize = 0;
    021             //判断是否单一结构
    022             if((status == 1 && buffer[currentIndex] & 0x20) != 0x20)
    023             {
    024                 tlvEntity[currentTLVIndex].Sub_TLVEntity = NULL; //单一结构时将子Tag置空
    025                 //判断是否多字节Tag
    026                 if((buffer[currentIndex] & 0x1f) == 0x1f)
    027                 {
    028                     int endTagIndex = currentIndex;
    029                     while((buffer[++endTagIndex] & 0x80) == 0x80); //判断第二个字节的最高位是否为1
    030                     int tagSize = endTagIndex - currentIndex + 1; //计算Tag包含多少字节
    031  
    032                     tlvEntity[currentTLVIndex].Tag = new unsigned char[tagSize];
    033                     memcpy(tlvEntity[currentTLVIndex].Tag, buffer + currentIndex, tagSize);
    034                     tlvEntity[currentTLVIndex].Tag[tagSize] = 0;
    035  
    036                     tlvEntity[currentTLVIndex].TagSize = tagSize;
    037  
    038                     currentIndex += tagSize;
    039                 }
    040                 else
    041                 {
    042                     tlvEntity[currentTLVIndex].Tag = new unsigned char[1];
    043                     memcpy(tlvEntity[currentTLVIndex].Tag, buffer + currentIndex, 1);
    044                     tlvEntity[currentTLVIndex].Tag[1] = 0;
    045  
    046                     tlvEntity[currentTLVIndex].TagSize = 1;
    047  
    048                     currentIndex += 1;
    049                 }
    050             }
    051             else
    052             {
    053                 //判断是否多字节Tag
    054                 if((buffer[currentIndex] & 0x1f) == 0x1f)
    055                 {
    056                     int endTagIndex = currentIndex;
    057                     while((buffer[++endTagIndex] & 0x80) == 0x80); //判断第二个字节的最高位是否为1
    058                     int tagSize = endTagIndex - currentIndex + 1; //计算Tag包含多少字节
    059  
    060                     tlvEntity[currentTLVIndex].Tag = new unsigned char[tagSize];
    061                     memcpy(tlvEntity[currentTLVIndex].Tag, buffer + currentIndex, tagSize);
    062                     tlvEntity[currentTLVIndex].Tag[tagSize] = 0;
    063  
    064                     tlvEntity[currentTLVIndex].TagSize = tagSize;
    065  
    066                     currentIndex += tagSize;
    067                 }
    068                 else
    069                 {
    070                     tlvEntity[currentTLVIndex].Tag = new unsigned char[1];
    071                     memcpy(tlvEntity[currentTLVIndex].Tag, buffer + currentIndex, 1);
    072                     tlvEntity[currentTLVIndex].Tag[1] = 0;
    073  
    074                     tlvEntity[currentTLVIndex].TagSize = 1;
    075  
    076                     currentIndex += 1;             
    077                 }
    078  
    079                 //分析SubTag
    080                 int subLength = 0; 
    081                  
    082                 unsigned char* temp;
    083                 if((buffer[currentIndex] & 0x80) == 0x80)
    084                 {
    085                     for (int index = 0; index < 2; index++)
    086                     {
    087                         subLength += buffer[currentIndex + 1 + index] << (index * 8); //计算Length域的长度
    088                     }
    089  
    090                     temp = new unsigned char[subLength];
    091  
    092                     memcpy(temp, buffer + currentIndex + 3, subLength);
    093                 }
    094                 else
    095                 {
    096                     subLength = buffer[currentIndex];
    097  
    098                     temp = new unsigned char[subLength];
    099  
    100                     memcpy(temp, buffer + currentIndex + 1, subLength);
    101                 }
    102                 temp[subLength] = 0;
    103                  
    104                 //memcpy(temp, buffer + currentIndex + 1, subLength);
    105                 unsigned int oLength;
    106                 tlvEntity[currentTLVIndex].Sub_TLVEntity = new TLVEntity[1];
    107                 Construct(temp, subLength, tlvEntity[currentTLVIndex].Sub_TLVEntity, oLength);
    108             }
    109  
    110             currentStatus = 'L';
    111             break;
    112         case 'L':      
    113             //判断长度字节的最高位是否为1,如果为1,则该字节为长度扩展字节,由下一个字节开始决定长度
    114             if((buffer[currentIndex] & 0x80) != 0x80)
    115             {
    116                 tlvEntity[currentTLVIndex].Length = new unsigned char[1];
    117                 memcpy(tlvEntity[currentTLVIndex].Length, buffer + currentIndex, 1);
    118                 tlvEntity[currentTLVIndex].Length[1] = 0;
    119                 tlvEntity[currentTLVIndex].LengthSize = 1;
    120  
    121                 valueSize = tlvEntity[currentTLVIndex].Length[0];
    122  
    123                 currentIndex += 1;
    124             }
    125             else
    126             {
    127                 //为1的情况
    128  
    129                 unsigned int lengthSize = buffer[currentIndex] & 0x7f;
    130                  
    131                 currentIndex += 1; //从下一个字节开始算Length域
    132  
    133                 for (int index = 0; index < lengthSize; index++)
    134                 {
    135                     valueSize += buffer[currentIndex + index] << (index * 8); //计算Length域的长度
    136                 }
    137  
    138                 tlvEntity[currentTLVIndex].Length = new unsigned char[lengthSize];
    139                 memcpy(tlvEntity[currentTLVIndex].Length, buffer + currentIndex, lengthSize);
    140                 tlvEntity[currentTLVIndex].Length[lengthSize] = 0;
    141  
    142                 tlvEntity[currentTLVIndex].LengthSize = lengthSize;
    143  
    144                 currentIndex += lengthSize;
    145             }
    146  
    147             currentStatus = 'V';
    148             break;
    149         case 'V':
    150             tlvEntity[currentTLVIndex].Value = new unsigned char[valueSize];
    151             memcpy(tlvEntity[currentTLVIndex].Value, buffer + currentIndex, valueSize);
    152             tlvEntity[currentTLVIndex].Value[valueSize] = 0;
    153  
    154             currentIndex += valueSize;
    155              
    156             //进入下一个TLV构造循环
    157             currentTLVIndex += 1;
    158  
    159             currentStatus = 'T';
    160             break;
    161         default:
    162             return;
    163         }
    164     }
    165  
    166     entityLength = currentTLVIndex;
    167 }
    168  
    169 // 解析TLV
    170 void TLVPackage::Parse(
    171     TLVEntity* tlvEntity,
    172     unsigned int entityLength,
    173     unsigned char* buffer,
    174     unsigned int& bufferLength
    175     )
    176 {
    177     int currentIndex = 0;
    178     int currentTLVIndex = 0;
    179     unsigned long valueSize = 0;
    180  
    181     while(currentTLVIndex < entityLength)
    182     {
    183         valueSize = 0;
    184         TLVEntity entity = tlvEntity[currentTLVIndex];
    185          
    186         memcpy(buffer + currentIndex, entity.Tag, entity.TagSize);  //解析Tag
    187         currentIndex += entity.TagSize;
    188  
    189         for (int index = 0; index < entity.LengthSize; index++)
    190         {
    191             valueSize += entity.Length[index] << (index * 8); //计算Length域的长度
    192         }
    193         if(valueSize > 127)
    194         {
    195             buffer[currentIndex] = 0x80 | entity.LengthSize;
    196             currentIndex += 1;
    197         }
    198          
    199         memcpy(buffer + currentIndex, entity.Length, entity.LengthSize);    //解析Length
    200         currentIndex += entity.LengthSize;
    201         //判断是否包含子嵌套TLV
    202         if(entity.Sub_TLVEntity == NULL)
    203         {
    204             memcpy(buffer + currentIndex, entity.Value, valueSize); //解析Value
    205             currentIndex += valueSize;
    206         }
    207         else
    208         {
    209             unsigned int oLength;
    210             Parse(entity.Sub_TLVEntity, 1, buffer + currentIndex, oLength); //解析子嵌套TLV
    211             currentIndex += oLength;
    212         }
    213  
    214         currentTLVIndex++;
    215     }
    216     buffer[currentIndex] = 0;
    217     bufferLength = currentIndex;
    218 }

    然后写测试程序:

    01 // 上发测试数据
    02 unsigned char requestBuf[] = {
    03         0x9F, 0x1C, 0x12, 0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32, 0x30, 0x34, 0x30, 0x34,
    04         0x32, 0x37, 0x31, 0x38, 0x9F, 0x62, 0x01, 0x01, 0x57, 0x12, 0x62, 0x22, 0x89, 0x00, 0x00, 0x02, 0x91,
    05         0x01, 0xD0, 0x90, 0x32, 0x01, 0x02, 0x47, 0x17, 0x13, 0x00, 0x0F, 0x5F, 0x20, 0x0A, 0x48, 0x55, 0x47,
    06         0x55, 0x4F, 0x20, 0x4D, 0x49, 0x4E, 0x47, 0x9F, 0x1F, 0x3C, 0x25, 0x39, 0x39, 0x36, 0x32, 0x32, 0x32,
    07         0x38, 0x39, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x39, 0x31, 0x30, 0x31, 0x5E, 0x47, 0x55, 0x4F, 0x20,
    08         0x4D, 0x49, 0x4E, 0x47, 0x2F, 0x48, 0x55, 0x5E, 0x30, 0x39, 0x30, 0x33, 0x32, 0x30, 0x31, 0x30, 0x32,
    09         0x34, 0x37, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x38, 0x39, 0x30,
    10         0x30, 0x3F
    11 };
    12  
    13     TLVEntity tlvEntity[TLV_MAX_LENGTH];
    14     unsigned int tlv_count;
    15     //构造TLV
    16     TLVPackage::Construct(requestBuf, sizeof(requestBuf), tlvEntity, tlv_count);
    17  
    18     unsigned char parseBuf[1024];
    19     unsigned int buf_count;
    20     //解析TLV
    21     TLVPackage::Parse(tlvEntity, tlv_count, parseBuf, buf_count);
    22  
    23     if(strncmp((char*)parseBuf, (char*)requestBuf, sizeof(requestBuf)) == 0)
    24     {
    25         AfxMessageBox("TRUE");
    26     }
    27     else
    28     {
    29         AfxMessageBox("FALSE");
    30     }

    最后测试结果中,可以得到最后将弹出“TRUE”的对话框。证明构造TLV得到的TLVEntity,再对这个实体进行解析,可以的到解析后的字节数组,最后通过strncmp的方法比较判断,是否原始字节数组和解析后的字节数组是否一致。

    另外,为了方便C#程序员的使用,我对该C++程序重新改写了一下,得出的结果也是一样的。

    TLVEntity.cs

    01 /// <summary>
    02     /// TLV实体
    03     /// </summary>
    04     public class TLVEntity
    05     {
    06         /// <summary>
    07         /// 标记
    08         /// </summary>
    09         public byte[] Tag { get; set; }
    10  
    11         /// <summary>
    12         /// 数据长度
    13         /// </summary>
    14         public byte[] Length { get; set; }
    15  
    16         /// <summary>
    17         /// 数据
    18         /// </summary>
    19         public byte[] Value { get; set; }
    20  
    21         /// <summary>
    22         /// 标记占用字节数
    23         /// </summary>
    24         public int TagSize { get; set; }
    25  
    26         /// <summary>
    27         /// 数据长度占用字节数
    28         /// </summary>
    29         public int LengthSize { get; set; }
    30  
    31         /// <summary>
    32         /// 子嵌套TLV实体
    33         /// </summary>
    34         public TLVEntity Sub_TLVEntity { get; set; }
    35     }

    以及TLVPackage.cs

    001 /// <summary>
    002     /// TLV打包类
    003     /// </summary>
    004     public class TLVPackage
    005     {
    006         /// <summary>
    007         /// 构造TLV
    008         /// </summary>
    009         /// <param name="buffer">
    010         public static List<tlventity> Construct(byte[] buffer)
    011         {
    012             List<tlventity> list = new List<tlventity>();
    013             int currentTLVIndex = 0;
    014             int currentIndex = 0;
    015             int currentStatus = 'T'; //状态字符
    016             int valueSize = 0;
    017  
    018             TLVEntity tlvEntity = null;
    019  
    020             while (currentIndex < buffer.Length)
    021             {
    022                 switch (currentStatus)
    023                 {
    024                     case 'T':
    025                         tlvEntity = new TLVEntity();
    026                         valueSize = 0;
    027                         //判断是否单一结构
    028                         if ((buffer[currentIndex] & 0x20) != 0x20)
    029                         {
    030                             tlvEntity.Sub_TLVEntity = null; //单一结构时将子Tag置空【】
    031                             //判断是否多字节Tag
    032                             if ((buffer[currentIndex] & 0x1f) == 0x1f)
    033                             {
    034                                 int endTagIndex = currentIndex;
    035                                 while ((buffer[++endTagIndex] & 0x80) == 0x80) ; //判断第二个字节的最高位是否为1
    036                                 int tagSize = endTagIndex - currentIndex + 1; //计算Tag包含多少字节
    037  
    038                                 tlvEntity.Tag = new byte[tagSize];
    039                                 Array.Copy(buffer, currentIndex, tlvEntity.Tag, 0, tagSize);
    040  
    041                                 tlvEntity.TagSize = tagSize;
    042  
    043                                 currentIndex += tagSize;
    044                             }
    045                             else
    046                             {
    047                                 tlvEntity.Tag = new byte[1];
    048                                 Array.Copy(buffer, currentIndex, tlvEntity.Tag, 0, 1);
    049  
    050                                 tlvEntity.TagSize = 1;
    051  
    052                                 currentIndex += 1;
    053                             }
    054                         }
    055                         else
    056                         {
    057                             //判断是否多字节Tag
    058                             if ((buffer[currentIndex] & 0x1f) == 0x1f)
    059                             {
    060                                 int endTagIndex = currentIndex;
    061                                 while ((buffer[++endTagIndex] & 0x80) == 0x80) ; //判断第二个字节的最高位是否为1
    062                                 int tagSize = endTagIndex - currentIndex + 1; //计算Tag包含多少字节
    063  
    064                                 tlvEntity.Tag = new byte[tagSize];
    065                                 Array.Copy(buffer, currentIndex, tlvEntity.Tag, 0, tagSize);
    066  
    067                                 tlvEntity.TagSize = tagSize;
    068  
    069                                 currentIndex += tagSize;
    070                             }
    071                             else
    072                             {
    073                                 tlvEntity.Tag = new byte[1];
    074                                 Array.Copy(buffer, currentIndex, tlvEntity.Tag, 0, 1);
    075  
    076                                 tlvEntity.TagSize = 1;
    077  
    078                                 currentIndex += 1;
    079                             }
    080  
    081                             //分析SubTag
    082                             int subLength = 0;
    083  
    084                             byte[] temp;
    085                             if ((buffer[currentIndex] & 0x80) == 0x80)
    086                             {
    087                                 for (int index = 0; index < 2; index++)
    088                                 {
    089                                     subLength += buffer[currentIndex + 1 + index] << (index * 8); //计算Length域的长度
    090                                 }
    091  
    092                                 temp = new byte[subLength];
    093  
    094                                 Array.Copy(buffer, currentIndex + 3, temp, 0, subLength);
    095                             }
    096                             else
    097                             {
    098                                 subLength = buffer[currentIndex];
    099  
    100                                 temp = new byte[subLength];
    101  
    102                                 Array.Copy(buffer, currentIndex + 1, temp, 0, subLength);
    103                             }
    104  
    105                             int oLength;
    106                             tlvEntity.Sub_TLVEntity = new TLVEntity();
    107                             List<tlventity> tempList = Construct(temp);
    108                             tlvEntity.Sub_TLVEntity = tempList[0];
    109                         }
    110  
    111                         currentStatus = 'L';
    112                         break;
    113                     case 'L':
    114                         //判断长度字节的最高位是否为1,如果为1,则该字节为长度扩展字节,由下一个字节开始决定长度
    115                         if ((buffer[currentIndex] & 0x80) != 0x80)
    116                         {
    117                             tlvEntity.Length = new byte[1];
    118                             Array.Copy(buffer, currentIndex, tlvEntity.Length, 0, 1);
    119  
    120                             tlvEntity.LengthSize = 1;
    121  
    122                             valueSize = tlvEntity.Length[0];
    123                             currentIndex += 1;
    124                         }
    125                         else
    126                         {
    127                             //为1的情况
    128  
    129                             int lengthSize = buffer[currentIndex] & 0x7f;
    130  
    131                             currentIndex += 1; //从下一个字节开始算Length域
    132  
    133                             for (int index = 0; index < lengthSize; index++)
    134                             {
    135                                 valueSize += buffer[currentIndex + index] << (index * 8); //计算Length域的长度
    136                             }
    137  
    138                             tlvEntity.Length = new byte[lengthSize];
    139                             Array.Copy(buffer, currentIndex, tlvEntity.Length, 0, lengthSize);
    140  
    141                             tlvEntity.LengthSize = lengthSize;
    142  
    143                             currentIndex += lengthSize;
    144                         }
    145  
    146                         currentStatus = 'V';
    147                         break;
    148                     case 'V':
    149                         tlvEntity.Value = new byte[valueSize];
    150                         Array.Copy(buffer, currentIndex, tlvEntity.Value, 0, valueSize);
    151  
    152                         currentIndex += valueSize;
    153  
    154                         //进入下一个TLV构造循环
    155                         list.Add(tlvEntity);
    156  
    157                         currentStatus = 'T';
    158                         break;
    159                     default:
    160                         return new List<tlventity>();
    161                 }
    162             }
    163  
    164             return list;
    165         }
    166  
    167         /// <summary>
    168         /// 解析TLV
    169         /// </summary>
    170         /// <param name="list">
    171         /// <returns></returns>
    172         public static byte[] Parse(List<tlventity> list)
    173         {
    174             byte[] buffer = new byte[4096];
    175             int currentIndex = 0;
    176             int currentTLVIndex = 0;
    177             int valueSize = 0;
    178  
    179             while (currentTLVIndex < list.Count())
    180             {
    181                 valueSize = 0;
    182                 TLVEntity entity = list[currentTLVIndex];
    183  
    184                 Array.Copy(entity.Tag, 0, buffer, currentIndex, entity.TagSize);    //解析Tag
    185  
    186                 currentIndex += entity.TagSize;
    187  
    188                 for (int index = 0; index < entity.LengthSize; index++)
    189                 {
    190                     valueSize += entity.Length[index] << (index * 8); //计算Length域的长度
    191                 }
    192                 if (valueSize > 127)
    193                 {
    194                     buffer[currentIndex] = Convert.ToByte(0x80 | entity.LengthSize);
    195                     currentIndex += 1;
    196                 }
    197  
    198                 Array.Copy(entity.Length, 0, buffer, currentIndex, entity.LengthSize);  //解析Length
    199  
    200                 currentIndex += entity.LengthSize;
    201                 //判断是否包含子嵌套TLV
    202                 if (entity.Sub_TLVEntity == null)
    203                 {
    204                     Array.Copy(entity.Value, 0, buffer, currentIndex, valueSize);   //解析Value
    205                     currentIndex += valueSize;
    206                 }
    207                 else
    208                 {
    209                     byte[] tempBuffer = Parse(new List<tlventity> { entity.Sub_TLVEntity });
    210                     Array.Copy(tempBuffer, 0, buffer, currentIndex, tempBuffer.Length); //解析子嵌套TLV
    211                     currentIndex += tempBuffer.Length;
    212                 }
    213  
    214                 currentTLVIndex++;
    215             }
    216  
    217             byte[] resultBuffer = new byte[currentIndex];
    218             Array.Copy(buffer, 0, resultBuffer, 0, currentIndex);
    219  
    220             return resultBuffer;
    221         }
    222     }</tlventity></tlventity></tlventity></tlventity></tlventity></tlventity></tlventity>

    接着,写测试程序:

    01 static byte[] requestBuffer =
    02         {
    03             0x9F, 0x1C, 0x82, 0x2C, 0x01,
    04             0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,
    05             0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,
    06             0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,
    07             0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,
    08             0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,
    09             0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,
    10             0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,
    11             0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,
    12             0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,
    13             0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32,
    14             0x71, 0x07, 0x9f, 0x19, 0x04, 0x11, 0x22, 0x33, 0x44
    15         };
    16  
    17         static void Main(string[] args)
    18         {
    19             Console.WriteLine("待组装的数据包:");
    20             requestBuffer.ToList().ForEach(o => { Console.Write("{0},", "0x" + o.ToString("X")); });
    21  
    22             Console.WriteLine("\r\n\r\n开始构造TLV");
    23             //构造TLV
    24             List<tlventity> list = TLVPackage.Construct(requestBuffer);
    25             Console.WriteLine("\r\n构造结束!");
    26  
    27             Console.WriteLine("\r\n开始解析TLV");
    28             //解析TLV
    29             byte[] responseBuffer = TLVPackage.Parse(list);
    30             Console.WriteLine("\r\n解析结束!");
    31  
    32             Console.WriteLine("\r\n解析结果:");
    33  
    34             if (ByteEquals(requestBuffer, responseBuffer))
    35             {
    36                 Console.WriteLine("Equal!");
    37             }
    38             else
    39             {
    40                 Console.WriteLine("Not Equal!");
    41             }
    42  
    43             Console.ReadKey();
    44         }</tlventity>

    运行结果:

    image

    总结

    TLV在数据通信方面,其实运用得很广泛,在应用层数据通信中,如HTTP协议,HTML,XML语言本身定义了一些标签 (Body,Head,Script)对数据串行化,接收方再根据标签解析原始数据,通过浏览器展现出来。因此本质上也是属于TLV协议的设计模式。甚至 在传输层的TCP,UDP协议,你完全可以通过TLV实现自定义的应用协议。

    附上C#源代码:TLVPackageDemo.rar

    作者:Leepy
     
    邮箱:sunleepy(AT)gmail.com
     
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。
  • 相关阅读:
    [ Python入门教程 ] Python文件基本操作
    [转载] 完整诠释软件质量模型
    [ Python入门教程 ] Python 数据结构基本操作
    [ Python入门教程 ] Python字符串数据类型及基本操作
    Notepad++好用的功能和插件
    Python在cmd上打印彩色文字
    你若读书,风雅自来
    [ 转载 ] ssh连接远程主机执行脚本的环境变量问题
    Python基本模块介绍:sys、platform
    深入解析跨站请求伪造漏洞:原理剖析
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2082327.html
Copyright © 2011-2022 走看看