一.Tag
1.Tag
传输数据时,接收方要明确知道每个收到的数据的类型,我们就要对各类型进行系统性的编号。在ASN.1中使用Tag来唯一标识数据的类型。
(1).分配给每个类型的tag实际上是一个值对:<taggingclass, number>。有四种taggingclass:UNIVERSAL,APPLICATION,context-specific和PRIVATE,分别用00、01、10、11表示。在一个上下文中,如果TaggingClass不同,则相同number的两个Tag也是不同的。
<1>.UNIVERSAL的Tag是ASN.1标准定义的,在描述中不能修改。
<2>.context-specificTag是对SEQUENCE、SET和CHOICE及其成员使用的,可以在描述中自己定义,只要不产生歧义,相同数值可以在不同结构中反复使用。如:
A-possible-type::= SET
{
integer[0] CHOICE
{
a[0] INTEGER,
b[1] INTEGER
},
boolean[1] CHOICE
{
a[0] BOOLEAN,
b[1] BOOLEAN
}
}
SET在ASN.1中定义的Tag值是17,上例的用户定义的类型A-possible-type有两个成员,分别用[0],[1]标识。这两个成员又各自包含两个成员,同样在自已的范围内用[0],[1]。
<3>.APPLICATION和PRIVATE已经不推荐使用。
2.IMPLICIT tagging和EXPLICITtagging
<1>. IMPLICIT
看一个例子:
overseas [1]IMPLICIT SEQUENCE
{
nameUTF8String,
typeOutletType,
locationAddress
},
该类型编码后,Tag[1]会覆盖掉SEQUENCE的默认类Tag[16],具体格式:
oversears是SEQUENCE类型,默认Tag应该是16,这里使用了关键字'IMPLICIT',将其覆盖为1,
CHIOCE类型不能用IMPLICIT模式,例:
warehouse[2] IMPLICIT CHOICE
{
northern[0] NULL,
southern[1] NULL
}
CHIOCE类型在编码时只有一个TLV,即northern或southern中的一个,使用IMPLICIT,[0]或[1]会覆盖掉[2]
在下面的情况中,warehouse取southern时,就会导致details两个成员的Tag都是[1]:
detailsSET
{
overseas[1] SEQUENCE
{
nameUTF8String,
typeOutletType,
locationAddress
},
warehouse[2] IMPLICIT CHOICE
{
northern[0] NULL,
southern[1] NULL
}
}
因此,CHOICE类型只能用显式Tag
<2>. EXPLICIT
如果一个类型的Tag是显式(EXPLICIT)的(或者在模块定义中声明了EXPLICITTAGS),则要以constructed方式编码三元组系列。
前面的CHOICE可用显式Tag
warehouse[2] EXPLICIT CHOICE
{
northern[0] NULL,
southern[1] NULL
}
编码为:
3.全局Tag模式
模块定义时,可以声明模块全局Tag模式。可以是EXPLICITTAGS、IMPLICITTAGS和AUTOMATICTAGS。
EXPLICITTAGS/IMPLICITTAGS:模块内所有SEQUENCE、SET都是EXPLICIT或IMPLICIT模式,但不影响IMPORTS的内容。
AUTOMATICTAGS:模块内所有SEQUENCE、SET类型ASN.1编译器会自动从0开始,步长为1进行自动编码。而其中的成员则用IMPLICIT模式。
CHOICE类型在以上情况都会自动被指定为EXPLICIT模式。
二.ASN.1结构类型(组合类型)
1.SEQUENCE
SEQUENCE是一组简单类型的有序集合,它可以嵌套使用,还可以使用OPTIONAL、DEFAULT和COMPONENTSOf等对成员进行修饰。
常见的声明如:
Description::= SEQUENCE
{
surname IA5String,
first-nameIA5String,
ageINTEGER
}
该类型的一个值为:
johnnyDescription ::=
{
surname"Smith",
first-name"John",
age40
}
注意最后一个成员后没有','
2.SET
与SEQUENCE一样,SET也是是一组简单类型集合,不同处是他的成员是无序的,没有先后关系。
3.SEQUENCEOf与STEOF
SEQUENCEOF相当于某些语言中的动态数组或者列表:所有成员都是一个类型,数目不定。如:
SteepleChase::= SEQUENCE OF INTEGER
他的取值格式是:
winningCombinationSteepleChase ::= {5, 2, 12}
no-one-arrivedSteepleChase ::= { }
STEOF和SEQUENCEOF相比,SETOf的成员是顺序的,其它类似。
4.CHOICE类型
CHOICE类型表示一种选择,类似UNION。和SEQUENCE、SET类型不同,CHOICE没有缺省的UNIVERSALTag值,因为它是一些类型的集合,其中被选择项目的Tag会被作为CHOICE相关Tag。
三.类型扩展
在定义中插入扩展标记“…”来定义一个类型是可扩展的。在ASN.1中可扩展的类型有ENUMERATED、
SEQUENCE、SET和CHOICE。如:
State::= ENUMERATED {on, off, out-of-order, ...}
Description::= SEQUENCE
{
surnameIA5String,
first-nameIA5String,
ageINTEGER,
...
}
扩展标记可以有两个,他们将类型定义分割为两个扩展部分,在扩展时,新增的项目可能有多个,并且其中可能还带有OPTIONAL和DEFAULT。这种情况下,解码器在解码中就会遇到困难。为了区分不同版本,在扩展部分,可以使用版本符号“[[]]”,如:
Afters::= CHOICE
{
cheeseIA5String,
dessertIA5String,
...!IA5String:"dimensionerror",
[[coffeeNULL ]], -- version 2
[[cognacIA5String]] -- version 3
}
如果扩展部分只有一个成员,则版本符号可以省略。如:
Afters::= CHOICE
{
cheeseIA5String,
dessertIA5String,
...!IA5String:"dimensionerror",
coffeeNULL, -- version 2
}
同一个版本扩展也可以添加多个成员,例:
Afters::= CHOICE
{
cheeseIA5String,
dessertIA5String,
...!IA5String:"dimensionerror",
[[coffeeNULL,
coke NULL]]-- version 2
}
当解码器发现没有预期的扩展或出现不预期的扩展时,为了能够正常工作,我们一般会事先规定忽略不期望的扩展,并为期望的扩展赋默认值。
解码器还会以事先约定的信号通知应用层。这个约定的信号就是异常Exception,在抽象语法中以“!”开头,后接一个值(可以是数、字符串等),放在扩展标记之后。上面例子中,解码器会通知应用层"dimensionerror"错误。
四.约束
1.单值约束
单值约束是最简单的约束,即将一个类型限制为一个值,如:
Two::= INTEGER (2)
Day::= ENUMERATED
{
monday(0),tuesday(1), wednesday(2), thursday(3), friday(4), saturday(5),sunday(6)
}
Day::= IA5String(“monday”|“tuesday”|“wednesday”|“thursday”|“friday”|“saturday”|“sunday”|)
2.类型包含约束
当声明一个类型和另一个类型拥有,只需要将被参考类型列出,如
WeekEnd::= Day (saturday|sunday)
FrenchWeekEnd::= Day (WeekEnd)
3.值域约束
From3to15::= Number (3..15) 取整数3-15任意一个
Upcase::= IA5String('A'..'Z') 取ASCII码A-Z任意一个
4.大小约束
Exactly31BitsString::= BIT STRING (SIZE (31))长度固定为31
Exactly31BitsString::= BIT STRING (SIZE (1..31))长度范围是1-31
5.正则表达约束
通过关键字PATTERN来约束字符串:
DateAndTime::= VisibleString(PATTERN "\d#2/\d#2/\d#4-\d#2:\d#2")
--DD/MM/YYYY-HH:MM
#n表示重复前一个表达式n次,/d不知道什么含义。
6.SEQUENCEOF或者SETOf成员的约束
AddressBlock::= SEQUENCE OF VisibleString (SIZE (1..32))
表示 VisibleString字串的长度是1到32个字符。
以下是对SEQUENCEOF类型本身的约束,表示该有序列可以有1到32个VisibleString字符串。
AddressBlock::= SEQUENCE (SIZE (1..32)) OF VisibleString
7.SEQUENCE、SET和CHOICE成员的约束
对于SEQUENCE和SET多个成员进行约束,我们使用WITHCOMPONENTS来添加约束,注意关键字结尾有S
对类型:
Quadruple::= SEQUENCE
{
alphaENUMERATED {state1, state2, state3},
betaIA5String OPTIONAL,
gammaSEQUENCE OF INTEGER,
deltaBOOLEAN DEFAULT TRUE
}
添加约束后为:
Quadruple1::= Quadruple (WITH COMPONENTS
{
...,
alpha(state1),
gamma(SIZE (5))
})
注意括号;符号“…”指示只对显式声明的成员进行约束,其它成员不变。
8.对OCTETSTRING内容的约束
可以使用CONTAINING和ENCODEDBY指定OCTETSTRING的内容和编码,如:
MoreCompact ::=OCTET STRING (CONTAINING MyType ENCODED BY {joint-iso-itu-t asn1packed-encoding(3) basic(0) unaligned(1)})
MyType::= SEQUENCE { -- ....... -- }
这里明确指定了OCTETSTRING的内容是MyType并且使用PER进行编码。
9.约束的组合
可以将前面所述的各种约束适当组合,得到更为准确的描述,如:
PhoneNumber ::=NumericString (FROM ("0".."9"))(SIZE (10))描述电话号码
10.自定义约束
可以通过关键字CONSTRAINEDBy来引入自定义约束,它通常都会在编解码过程中引入特定的处理。
五.上下文交换类型
1.EXTERNAL类型
不推荐使用。可以用EMBEDDEDPDV类型替代。
2.EMBEDDEDPDV类型
EMBEDDEDPDV类型等效于:
EMBEDDEDPDV ::= [UNIVERSAL 11] IMPLICIT SEQUENCE
{
identificationCHOICE
{
syntaxes SEQUENCE
{
abstractOBJECT IDENTIFIER,
transferOBJECT IDENTIFIER
},
syntaxOBJECT IDENTIFIER,
presentation-context-idINTEGER,
context-negotiationSEQUENCE
{
presentation-context-idINTEGER,
transfer-syntaxOBJECT IDENTIFIER
},
transfer-syntaxOBJECT IDENTIFIER,
fixedNULL
},
data-valueOCTET STRING
}
EMBEDDEDPDV是一种专门用于通讯的基本类型,其中:
syntaxes(注意有s)表征编码规则中抽象语法和传输语法的对象标识;
syntax表征抽象语法和编码规则;
presentation-context-id是协商后的表示上下文(只用于OSI环境中,即一对抽象语法和传输语法);context-negotiation用于表示上下文协商,可能在连接建议开始或者连接过程中上下文修改;
transfer-syntax。此时,抽象语法应该是应用设计者固定采用的方式,并且发送、接收双方都已明确;
fixed表明发送、接收双方都已知道抽象语法和传输语法。
3.CHARACTERSTRING类型
CHARACTERSTRING是EMBEDDEDPDV的一个具体应用,在一些特殊场合下的字符串类型,可能不想如前述标准类型那样采用标准的编码方式,而是希望其字符抽象语法和字符传输语法能在通讯系统标识层间协商或者在环境合适时直接使用字符串。
六.信息对象类、信息对象和信息对象集合
这部分没看明白,资料中模糊的地方太多,先放一边
七.宏Macro
自1994版本标准后,宏Macro已经被信息对象类和信息对象取代了。