项目管理理论与实践系列文章索引
项目管理理论与实践(1)——企业项目管理介绍
项目管理理论与实践(2)——软件需求分析
项目管理理论与实践(3)——如何进行有效的项目管理
项目管理理论与实践(4)——UML应用(上)
项目管理理论与实践(5)——UML应用(下)
项目管理理论与实践(6)——利用Excel制作项目文档的设计技巧
项目管理理论与实践(7)——软件开发报价的计算方法
待续
作者: Leepy
邮箱:sunleepy(AT)gmail.com
出处: http://liping13599168.cnblogs.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是如何编码的,先看下图:
这张图说明了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的情况:
从图中我们看到BER-TLV编码中,当b8为1时,Tag还需要有后续字节,直到b8为0为止。从EMV文档中的说明,Tag最多只占用2个字节,所以这样就相对比较简单一些了。当b8为0时,该Tag域结束,总共就占用2个字节。
Length域说明:
在文档中没有图片叙述,我自绘一个:
当b8为0时,该字节的b7-b1作为value域的长度;当b8为1时,b7-b1作为后续字节的长度,也就是说,例如有这样一个 值:10000011,代表后续还有3个字节作为value域的长度(本字节不算,本字节变为作为一个Length的索引)。3个字节代表value的长 度,意味着什么呢,意味着内容的长度当需要很大的时候,字节的位数就会跟着越高,3个字节就代表最大可以有256*256*256的长度。
Value域说明:
也是分成两种情况考虑,就是前面说到的Tag分成两个数据元结构,一种是简单数据元结构,一种是复合数据元架构:
先来看看简单数据元结构:
Tag就是Tag,没有子标签Tag,基本结构就是T-L-V。
再看下符合数据元结构:
后面的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>
运行结果:
总结
TLV在数据通信方面,其实运用得很广泛,在应用层数据通信中,如HTTP协议,HTML,XML语言本身定义了一些标签 (Body,Head,Script)对数据串行化,接收方再根据标签解析原始数据,通过浏览器展现出来。因此本质上也是属于TLV协议的设计模式。甚至 在传输层的TCP,UDP协议,你完全可以通过TLV实现自定义的应用协议。
附上C#源代码: TLVPackageDemo.rar
作者: Leepy
邮箱:sunleepy(AT)gmail.com
出处: http://liping13599168.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。
作者: Leo_wl
出处: http://www.cnblogs.com/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息