心在使用它之前是否被定义过。如:
employeeNumber EmployeeNumber ::= 12345 EmployeeNumber ::= [APPLICATION 2] INTEGER
2)所有的标识符、参考、关键字都要以一个字母开头,后接字母(大、小写都可以)、数字或者连字符“-”(但不能以连字符“-”结尾,也不能连续出现两个连字符),不能出现下划线“_”。 合法的:
INTEGER v1515 No-final-dash MY-CLASS 不合法的:
Final-dashdouble-- dash under score 1515 3M
3)关键字一般都是全部大写的,除了一些字符串类型,如PrintableString,UTF8String,等,因为这些都是由原类型OCTET STRING衍生出来的。
4)在标识符中,只有类型和模块名字是以大写字母开头的,其它标识符都是以小写字母开头的。
5)字符串有三种形式:
? <1>用引号引用的字符串: “This is a string”
? <2>单引号引用的二进制串后加大写字母B: ?01101?B
? <3>单引号引用的十六进制串后加大写字母H: ?0123456789ABCDEF?H
6)带小数点的小数形式不能在ASN.1中直接使用,在ASN.1中实数实际定义为三个整数:尾数、基数和指数。
7)注释以两个连字符“--”开始,结束于行的结尾或者该行中另一个双连字符。 8)如同大多数计算机语言,ASN.1不对空格、制表符、换行符和注释做翻译。但是在定义符号(或者分配符号Assignment)“::=”中不能有分隔符,否则不能正确处理。
2.3 类型与类型定义
2.3.1 ASN.1中的类型
ASN.1中的一个重要概念就是类型。类型是一个非空的值的集合,可以被编码后传输。相比与高级语言中复杂的数据结构,ASN.1中的类型主要是为了数据的传输(比如为SEQUENCE和SET定义了OPTIONAL条目)。而BIT STRING和EMBEDDED PDV则是为了通讯专门设计的。
ASN.1中的基本类型如Table 2-1中所示,更为复杂的类型可以由基本类型通过如Table 2-2中的组合类型构造得到。
Table 2-1 内建数据类型 类型 NULL 含义 只包含一个值NULL,用于传送一个报告或者作为CHOICE类型中某些值 INTEGER REAL ENUMERATED BIT STRING OCTET STRING OBJECT IDENTIFIER, RELATIVE-OID EXTERNAL, EMBEDDED PDV …String(除了BIT STRING、各种字符串,有NumericString、OCTET STRING外) PrintableString、VisibleStirng、ISO64String、IA5String、TeletexStirng、T61String、VideotexString、GraphicString、GeneralString、UniversalString、BMPString和UTF8String CHARACTER STRING UTCTime, GeneralizedTime
允许为字符串协商一个明确的字符表 日期 全部整数(包括正数和负数) 实数,表示浮点数 标识符的枚举(实例状态机的状态) 比特串 字节串 一个实体的标识符,它在一个全世界范围树状结构中注册 表示层上下文交换类型 Table 2-2 组合类型 类型 CHOICE SEQUENCE SET SEQUENCE OF SET OF 含义 在类型中选择(相当于C中的联合) 由不同类型的值组成一个有序的结构(相当于C中的结构体) 由不同类型的值组成一个无序的结构 由相同类型的值组成一个有序的结构(相当于C中的数组) 由相同类型的值组成一个无序的结构 2.3.2 类型定义
<新类型的名字> ::= <类型描述> 其中:
<新类型的名字>是一个以大写字母开头的标识符; <类型描述>是基于内建类型或在其它地方定义的类型。
如:
Married ::= BOOLEAN Age ::= INTEGER Picture ::= BIT STRING Form ::= SEQUENCE {
name PrintableString, }
Payment-method ::= CHOICE {
check
Check-number,
SEQUENCE
age Age, married Married,
marriage-certificate Picture OPTIONAL
credit-card {
number Card-number,
}
expiry-date Date
}
注意:在SEQUENCE和SET等(好像应该是所有组合类型的)定义中,最后一个成员结尾没有逗号“,”。
为了接收方能正确解码,发送方为每个值的类型附加一个数,称为tag,在描述中以“[]”标识。缺省情况下,编码器会使用universal的tag。很多时候,缺省情况下不能消除所有的模糊性,有必要明确指出各成员的tag。
如:
Afters ::= CHOICE { }
cheese dessert
[0] PrintableString, [1] PrintableString
Coordinates ::= SET { x }
y z
[1] INTEGER, //这证明好像也可以用类来直接声明变量 [2] INTEGER,
[3] INTEGER OPTIONAL
注意:ASN.1允许递归式的类型分配(Assignment),但我们应当保证其中包含至少一个非递归的值,因为编码规则无法处理无限的值。当然,绝大多数结构类型的成员都终结于简单类型。
为了准确描述一个类型,我们需要对值的集合进行一定的限制。这用到子类型约束,在类型之后用圆括号进行标识。
如:
Lottery-number ::= INTERGER(1..49)
Lottery-draw ::= SEQUENCE SIZE(6) OF Lottery-number Upper-case-words ::= IA5String (FROM(“A”..”Z”))
Phone-number ::= NumericString (FROM(“0”..”9”))(SIZE(10))
Coordinates-in-plan ::= Coordinates (WITH COMPONENTS {…, z ABSENT})
有约束的类型当然还是类型,可以用在任何一个可以使用类型的地方。
最后,因为版本升级,在新的描述中,出现新的成员被加入到SEQUENCE、SET或者CHOICE或者在上述类型基础上添加约束而衍生的子类型时,两个连接的机器(特别是在开放网络中)不一定使用的是相同版本描述而生成的编解码器。为了防止一方因收到过多或者过少数据而出现错误,ASN.1中用符号“…”来标记可能以后是其它类型的地方。这样即使是旧的编解码器也不会因为描述扩充而导致编解码错误。
如:
以后新的版本中,描述可能为:
Type ::= SEQUENCE { }
component1 INTERGER, component2 BOOLEAN, …,
[[component3 REAL]], …
-- version 2
Type ::= SEQUENCE { }
component1 INTERGER,
component2 BOOLEAN, -- version 1 …
注意:新加入的类型成员要嵌套在“[[]]”中。
2.4 值定义
<新的值的名字> <该值的类型> ::= <值描述>

