金融系统中PBOC/EMV的TLV的算法实现(含C++/C#)
来源:互联网 发布:mac win10 iso 下载 编辑:程序博客网 时间:2024/04/28 08:20
http://www.cnblogs.com/liping13599168/archive/2011/06/15/2081366.html
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结构实体:
// TLV结构体
struct
TLVEntity {
unsigned
char
* Tag;
//标记
unsigned
char
* Length;
//数据长度
unsigned
char
* Value;
//数据
unsigned
int
TagSize;
//标记占用字节数
unsigned
int
LengthSize;
//数据长度占用字节数
TLVEntity* Sub_TLVEntity;
//子嵌套TLV实体
};
定义一个TLVPackage的打包类:
TLVPackage.h:
// TLV打包类
class
TLVPackage
{
public
:
TLVPackage();
virtual
~TLVPackage();
//构造TLV实体
static
void
Construct(unsigned
char
* buffer, unsigned
int
bufferLength, TLVEntity* tlvEntity, unsigned
int
& entityLength, unsigned
int
status=0);
//解析TLV字节数组
static
void
Parse(TLVEntity* tlvEntity, unsigned
int
entityLength, unsigned
char
* buffer, unsigned
int
& bufferLength);
};
具体方法实现:
// 构造TLV
void
TLVPackage:: Construct(
unsigned
char
* buffer,
unsigned
int
bufferLength,
TLVEntity* tlvEntity,
unsigned
int
& entityLength,
unsigned
int
status
)
{
int
currentTLVIndex = 0;
int
currentIndex = 0;
int
currentStatus =
'T'
;
//状态字符
unsigned
long
valueSize = 0;
while
(currentIndex < bufferLength)
{
switch
(currentStatus)
{
case
'T'
:
valueSize = 0;
//判断是否单一结构
if
((status == 1 && buffer[currentIndex] & 0x20) != 0x20)
{
tlvEntity[currentTLVIndex].Sub_TLVEntity = NULL;
//单一结构时将子Tag置空
//判断是否多字节Tag
if
((buffer[currentIndex] & 0x1f) == 0x1f)
{
int
endTagIndex = currentIndex;
while
((buffer[++endTagIndex] & 0x80) == 0x80);
//判断第二个字节的最高位是否为1
int
tagSize = endTagIndex - currentIndex + 1;
//计算Tag包含多少字节
tlvEntity[currentTLVIndex].Tag =
new
unsigned
char
[tagSize];
memcpy
(tlvEntity[currentTLVIndex].Tag, buffer + currentIndex, tagSize);
tlvEntity[currentTLVIndex].Tag[tagSize] = 0;
tlvEntity[currentTLVIndex].TagSize = tagSize;
currentIndex += tagSize;
}
else
{
tlvEntity[currentTLVIndex].Tag =
new
unsigned
char
[1];
memcpy
(tlvEntity[currentTLVIndex].Tag, buffer + currentIndex, 1);
tlvEntity[currentTLVIndex].Tag[1] = 0;
tlvEntity[currentTLVIndex].TagSize = 1;
currentIndex += 1;
}
}
else
{
//判断是否多字节Tag
if
((buffer[currentIndex] & 0x1f) == 0x1f)
{
int
endTagIndex = currentIndex;
while
((buffer[++endTagIndex] & 0x80) == 0x80);
//判断第二个字节的最高位是否为1
int
tagSize = endTagIndex - currentIndex + 1;
//计算Tag包含多少字节
tlvEntity[currentTLVIndex].Tag =
new
unsigned
char
[tagSize];
memcpy
(tlvEntity[currentTLVIndex].Tag, buffer + currentIndex, tagSize);
tlvEntity[currentTLVIndex].Tag[tagSize] = 0;
tlvEntity[currentTLVIndex].TagSize = tagSize;
currentIndex += tagSize;
}
else
{
tlvEntity[currentTLVIndex].Tag =
new
unsigned
char
[1];
memcpy
(tlvEntity[currentTLVIndex].Tag, buffer + currentIndex, 1);
tlvEntity[currentTLVIndex].Tag[1] = 0;
tlvEntity[currentTLVIndex].TagSize = 1;
currentIndex += 1;
}
//分析SubTag
int
subLength = 0;
unsigned
char
* temp;
if
((buffer[currentIndex] & 0x80) == 0x80)
{
for
(
int
index = 0; index < 2; index++)
{
subLength += buffer[currentIndex + 1 + index] << (index * 8);
//计算Length域的长度
}
temp =
new
unsigned
char
[subLength];
memcpy
(temp, buffer + currentIndex + 3, subLength);
}
else
{
subLength = buffer[currentIndex];
temp =
new
unsigned
char
[subLength];
memcpy
(temp, buffer + currentIndex + 1, subLength);
}
temp[subLength] = 0;
//memcpy(temp, buffer + currentIndex + 1, subLength);
unsigned
int
oLength;
tlvEntity[currentTLVIndex].Sub_TLVEntity =
new
TLVEntity[1];
Construct(temp, subLength, tlvEntity[currentTLVIndex].Sub_TLVEntity, oLength);
}
currentStatus =
'L'
;
break
;
case
'L'
:
//判断长度字节的最高位是否为1,如果为1,则该字节为长度扩展字节,由下一个字节开始决定长度
if
((buffer[currentIndex] & 0x80) != 0x80)
{
tlvEntity[currentTLVIndex].Length =
new
unsigned
char
[1];
memcpy
(tlvEntity[currentTLVIndex].Length, buffer + currentIndex, 1);
tlvEntity[currentTLVIndex].Length[1] = 0;
tlvEntity[currentTLVIndex].LengthSize = 1;
valueSize = tlvEntity[currentTLVIndex].Length[0];
currentIndex += 1;
}
else
{
//为1的情况
unsigned
int
lengthSize = buffer[currentIndex] & 0x7f;
currentIndex += 1;
//从下一个字节开始算Length域
for
(
int
index = 0; index < lengthSize; index++)
{
valueSize += buffer[currentIndex + index] << (index * 8);
//计算Length域的长度
}
tlvEntity[currentTLVIndex].Length =
new
unsigned
char
[lengthSize];
memcpy
(tlvEntity[currentTLVIndex].Length, buffer + currentIndex, lengthSize);
tlvEntity[currentTLVIndex].Length[lengthSize] = 0;
tlvEntity[currentTLVIndex].LengthSize = lengthSize;
currentIndex += lengthSize;
}
currentStatus =
'V'
;
break
;
case
'V'
:
tlvEntity[currentTLVIndex].Value =
new
unsigned
char
[valueSize];
memcpy
(tlvEntity[currentTLVIndex].Value, buffer + currentIndex, valueSize);
tlvEntity[currentTLVIndex].Value[valueSize] = 0;
currentIndex += valueSize;
//进入下一个TLV构造循环
currentTLVIndex += 1;
currentStatus =
'T'
;
break
;
default
:
return
;
}
}
entityLength = currentTLVIndex;
}
// 解析TLV
void
TLVPackage::Parse(
TLVEntity* tlvEntity,
unsigned
int
entityLength,
unsigned
char
* buffer,
unsigned
int
& bufferLength
)
{
int
currentIndex = 0;
int
currentTLVIndex = 0;
unsigned
long
valueSize = 0;
while
(currentTLVIndex < entityLength)
{
valueSize = 0;
TLVEntity entity = tlvEntity[currentTLVIndex];
memcpy
(buffer + currentIndex, entity.Tag, entity.TagSize);
//解析Tag
currentIndex += entity.TagSize;
for
(
int
index = 0; index < entity.LengthSize; index++)
{
valueSize += entity.Length[index] << (index * 8);
//计算Length域的长度
}
if
(valueSize > 127)
{
buffer[currentIndex] = 0x80 | entity.LengthSize;
currentIndex += 1;
}
memcpy
(buffer + currentIndex, entity.Length, entity.LengthSize);
//解析Length
currentIndex += entity.LengthSize;
//判断是否包含子嵌套TLV
if
(entity.Sub_TLVEntity == NULL)
{
memcpy
(buffer + currentIndex, entity.Value, valueSize);
//解析Value
currentIndex += valueSize;
}
else
{
unsigned
int
oLength;
Parse(entity.Sub_TLVEntity, 1, buffer + currentIndex, oLength);
//解析子嵌套TLV
currentIndex += oLength;
}
currentTLVIndex++;
}
buffer[currentIndex] = 0;
bufferLength = currentIndex;
}
然后写测试程序:
// 上发测试数据
unsigned
char
requestBuf[] = {
0x9F, 0x1C, 0x12, 0x33, 0x33, 0x30, 0x32, 0x32, 0x37, 0x31, 0x39, 0x36, 0x32, 0x30, 0x34, 0x30, 0x34,
0x32, 0x37, 0x31, 0x38, 0x9F, 0x62, 0x01, 0x01, 0x57, 0x12, 0x62, 0x22, 0x89, 0x00, 0x00, 0x02, 0x91,
0x01, 0xD0, 0x90, 0x32, 0x01, 0x02, 0x47, 0x17, 0x13, 0x00, 0x0F, 0x5F, 0x20, 0x0A, 0x48, 0x55, 0x47,
0x55, 0x4F, 0x20, 0x4D, 0x49, 0x4E, 0x47, 0x9F, 0x1F, 0x3C, 0x25, 0x39, 0x39, 0x36, 0x32, 0x32, 0x32,
0x38, 0x39, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x39, 0x31, 0x30, 0x31, 0x5E, 0x47, 0x55, 0x4F, 0x20,
0x4D, 0x49, 0x4E, 0x47, 0x2F, 0x48, 0x55, 0x5E, 0x30, 0x39, 0x30, 0x33, 0x32, 0x30, 0x31, 0x30, 0x32,
0x34, 0x37, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x38, 0x39, 0x30,
0x30, 0x3F
};
TLVEntity tlvEntity[TLV_MAX_LENGTH];
unsigned
int
tlv_count;
//构造TLV
TLVPackage::Construct(requestBuf,
sizeof
(requestBuf), tlvEntity, tlv_count);
unsigned
char
parseBuf[1024];
unsigned
int
buf_count;
//解析TLV
TLVPackage::Parse(tlvEntity, tlv_count, parseBuf, buf_count);
if
(
strncmp
((
char
*)parseBuf, (
char
*)requestBuf,
sizeof
(requestBuf)) == 0)
{
AfxMessageBox(
"TRUE"
);
}
else
{
AfxMessageBox(
"FALSE"
);
}
最后测试结果中,可以得到最后将弹出“TRUE”的对话框。证明构造TLV得到的TLVEntity,再对这个实体进行解析,可以的到解析后的字节数组,最后通过strncmp的方法比较判断,是否原始字节数组和解析后的字节数组是否一致。
另外,为了方便C#程序员的使用,我对该C++程序重新改写了一下,得出的结果也是一样的。
TLVEntity.cs
/// <summary>
/// TLV实体
/// </summary>
public
class
TLVEntity
{
/// <summary>
/// 标记
/// </summary>
public
byte
[] Tag {
get
;
set
; }
/// <summary>
/// 数据长度
/// </summary>
public
byte
[] Length {
get
;
set
; }
/// <summary>
/// 数据
/// </summary>
public
byte
[] Value {
get
;
set
; }
/// <summary>
/// 标记占用字节数
/// </summary>
public
int
TagSize {
get
;
set
; }
/// <summary>
/// 数据长度占用字节数
/// </summary>
public
int
LengthSize {
get
;
set
; }
/// <summary>
/// 子嵌套TLV实体
/// </summary>
public
TLVEntity Sub_TLVEntity {
get
;
set
; }
}
以及TLVPackage.cs
/// <summary>
/// TLV打包类
/// </summary>
public
class
TLVPackage
{
/// <summary>
/// 构造TLV
/// </summary>
/// <param name="buffer">
public
static
List<tlventity> Construct(
byte
[] buffer)
{
List<tlventity> list =
new
List<tlventity>();
int
currentTLVIndex = 0;
int
currentIndex = 0;
int
currentStatus =
'T'
;
//状态字符
int
valueSize = 0;
TLVEntity tlvEntity =
null
;
while
(currentIndex < buffer.Length)
{
switch
(currentStatus)
{
case
'T'
:
tlvEntity =
new
TLVEntity();
valueSize = 0;
//判断是否单一结构
if
((buffer[currentIndex] & 0x20) != 0x20)
{
tlvEntity.Sub_TLVEntity =
null
;
//单一结构时将子Tag置空【】
//判断是否多字节Tag
if
((buffer[currentIndex] & 0x1f) == 0x1f)
{
int
endTagIndex = currentIndex;
while
((buffer[++endTagIndex] & 0x80) == 0x80) ;
//判断第二个字节的最高位是否为1
int
tagSize = endTagIndex - currentIndex + 1;
//计算Tag包含多少字节
tlvEntity.Tag =
new
byte
[tagSize];
Array.Copy(buffer, currentIndex, tlvEntity.Tag, 0, tagSize);
tlvEntity.TagSize = tagSize;
currentIndex += tagSize;
}
else
{
tlvEntity.Tag =
new
byte
[1];
Array.Copy(buffer, currentIndex, tlvEntity.Tag, 0, 1);
tlvEntity.TagSize = 1;
currentIndex += 1;
}
}
else
{
//判断是否多字节Tag
if
((buffer[currentIndex] & 0x1f) == 0x1f)
{
int
endTagIndex = currentIndex;
while
((buffer[++endTagIndex] & 0x80) == 0x80) ;
//判断第二个字节的最高位是否为1
int
tagSize = endTagIndex - currentIndex + 1;
//计算Tag包含多少字节
tlvEntity.Tag =
new
byte
[tagSize];
Array.Copy(buffer, currentIndex, tlvEntity.Tag, 0, tagSize);
tlvEntity.TagSize = tagSize;
currentIndex += tagSize;
}
else
{
tlvEntity.Tag =
new
byte
[1];
Array.Copy(buffer, currentIndex, tlvEntity.Tag, 0, 1);
tlvEntity.TagSize = 1;
currentIndex += 1;
}
//分析SubTag
int
subLength = 0;
byte
[] temp;
if
((buffer[currentIndex] & 0x80) == 0x80)
{
for
(
int
index = 0; index < 2; index++)
{
subLength += buffer[currentIndex + 1 + index] << (index * 8);
//计算Length域的长度
}
temp =
new
byte
[subLength];
Array.Copy(buffer, currentIndex + 3, temp, 0, subLength);
}
else
{
subLength = buffer[currentIndex];
temp =
new
byte
[subLength];
Array.Copy(buffer, currentIndex + 1, temp, 0, subLength);
}
int
oLength;
tlvEntity.Sub_TLVEntity =
new
TLVEntity();
List<tlventity> tempList = Construct(temp);
tlvEntity.Sub_TLVEntity = tempList[0];
}
currentStatus =
'L'
;
break
;
case
'L'
:
//判断长度字节的最高位是否为1,如果为1,则该字节为长度扩展字节,由下一个字节开始决定长度
if
((buffer[currentIndex] & 0x80) != 0x80)
{
tlvEntity.Length =
new
byte
[1];
Array.Copy(buffer, currentIndex, tlvEntity.Length, 0, 1);
tlvEntity.LengthSize = 1;
valueSize = tlvEntity.Length[0];
currentIndex += 1;
}
else
{
//为1的情况
int
lengthSize = buffer[currentIndex] & 0x7f;
currentIndex += 1;
//从下一个字节开始算Length域
for
(
int
index = 0; index < lengthSize; index++)
{
valueSize += buffer[currentIndex + index] << (index * 8);
//计算Length域的长度
}
tlvEntity.Length =
new
byte
[lengthSize];
Array.Copy(buffer, currentIndex, tlvEntity.Length, 0, lengthSize);
tlvEntity.LengthSize = lengthSize;
currentIndex += lengthSize;
}
currentStatus =
'V'
;
break
;
case
'V'
:
tlvEntity.Value =
new
byte
[valueSize];
Array.Copy(buffer, currentIndex, tlvEntity.Value, 0, valueSize);
currentIndex += valueSize;
//进入下一个TLV构造循环
list.Add(tlvEntity);
currentStatus =
'T'
;
break
;
default
:
return
new
List<tlventity>();
}
}
return
list;
}
/// <summary>
/// 解析TLV
/// </summary>
/// <param name="list">
/// <returns></returns>
public
static
byte
[] Parse(List<tlventity> list)
{
byte
[] buffer =
new
byte
[4096];
int
currentIndex = 0;
int
currentTLVIndex = 0;
int
valueSize = 0;
while
(currentTLVIndex < list.Count())
{
valueSize = 0;
TLVEntity entity = list[currentTLVIndex];
Array.Copy(entity.Tag, 0, buffer, currentIndex, entity.TagSize);
//解析Tag
currentIndex += entity.TagSize;
for
(
int
index = 0; index < entity.LengthSize; index++)
{
valueSize += entity.Length[index] << (index * 8);
//计算Length域的长度
}
if
(valueSize > 127)
{
buffer[currentIndex] = Convert.ToByte(0x80 | entity.LengthSize);
currentIndex += 1;
}
Array.Copy(entity.Length, 0, buffer, currentIndex, entity.LengthSize);
//解析Length
currentIndex += entity.LengthSize;
//判断是否包含子嵌套TLV
if
(entity.Sub_TLVEntity ==
null
)
{
Array.Copy(entity.Value, 0, buffer, currentIndex, valueSize);
//解析Value
currentIndex += valueSize;
}
else
{
byte
[] tempBuffer = Parse(
new
List<tlventity> { entity.Sub_TLVEntity });
Array.Copy(tempBuffer, 0, buffer, currentIndex, tempBuffer.Length);
//解析子嵌套TLV
currentIndex += tempBuffer.Length;
}
currentTLVIndex++;
}
byte
[] resultBuffer =
new
byte
[currentIndex];
Array.Copy(buffer, 0, resultBuffer, 0, currentIndex);
return
resultBuffer;
}
}</tlventity></tlventity></tlventity></tlventity></tlventity></tlventity></tlventity>
接着,写测试程序:
static
byte
[] requestBuffer =
{
0x9F, 0x1C, 0x82, 0x2C, 0x01,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
0x71, 0x07, 0x9f, 0x19, 0x04, 0x11, 0x22, 0x33, 0x44
};
static
void
Main(
string
[] args)
{
Console.WriteLine(
"待组装的数据包:"
);
requestBuffer.ToList().ForEach(o => { Console.Write(
"{0},"
,
"0x"
+ o.ToString(
"X"
)); });
Console.WriteLine(
"\r\n\r\n开始构造TLV"
);
//构造TLV
List<tlventity> list = TLVPackage.Construct(requestBuffer);
Console.WriteLine(
"\r\n构造结束!"
);
Console.WriteLine(
"\r\n开始解析TLV"
);
//解析TLV
byte
[] responseBuffer = TLVPackage.Parse(list);
Console.WriteLine(
"\r\n解析结束!"
);
Console.WriteLine(
"\r\n解析结果:"
);
if
(ByteEquals(requestBuffer, responseBuffer))
{
Console.WriteLine(
"Equal!"
);
}
else
{
Console.WriteLine(
"Not Equal!"
);
}
Console.ReadKey();
}</tlventity>
运行结果:
总结
TLV在数据通信方面,其实运用得很广泛,在应用层数据通信中,如HTTP协议,HTML,XML语言本身定义了一些标签(Body,Head,Script)对数据串行化,接收方再根据标签解析原始数据,通过浏览器展现出来。因此本质上也是属于TLV协议的设计模式。甚至在传输层的TCP,UDP协议,你完全可以通过TLV实现自定义的应用协议。
- 金融系统中PBOC/EMV的TLV的算法实现(含C++/C#)
- 金融系统中PBOC/EMV的TLV的算法实现(含C++/C#)
- 金融系统中PBOC/EMV的TLV的算法实现(含C++/C#)
- 融系统中PBOC/EMV的TLV的算法实现(含C++/C#)
- 融系统中PBOC/EMV的TLV的算法实现(含C++/C#)
- PBOC/EMV中TLV的构造和解析
- PBOC/EMV中TLV的构造和解析
- PBOC/EMV中TLV的构造和解析
- PBOC/EMV之TLV编码与解码
- PBOC/EMV之TLV编码与解码
- PBOC/EMV之TLV编码与解码
- PBOC/EMV之TLV编码与解码
- PBOC/EMV之TLV编码与解码
- PBOC2.0/EMV之TLV格式解析(C++)
- PBOC/EMV之DES算法
- PBOC/EMV之DES算法
- PBOC/EMV之DES算法
- PBOC/EMV之DES算法
- 植物大战僵尸
- hdu2222 Keywords Search (AC自动机)
- UVA - 11489 Integer Game
- vb.net 关于log的简单代码
- 数据结构C++算法实现2 - 归并排序1
- 金融系统中PBOC/EMV的TLV的算法实现(含C++/C#)
- 【算法】深度优先搜索(DFS)I
- 让你的开发变得更加快起来
- 2013年长沙网络赛G题
- Spring如何处理线程并发
- 登山
- 新建项目(failed to import..)解决方法
- ios页面间传递参数四种方式
- 组合数递推模版