简介
XDR
全称为External Data Representation
,是一个描述和编码数据的标准。1987年由Sun公司(Sun Microsystems, Inc)发明。
XDR
同时是一门语言,主要用来描述协议的数据格式,如RPC、NFS等协议就是使用它来描述自身的数据格式。
XDR
语言只能用于描述协议的数据格式,不具有编程功能。该语言具有以下特点:
- 类似于C语言
- 描述复杂的数据格式时,相比图形描述,其更简洁
XDR
语法
分号;
在XDR
语言中,分号是语句结束符。也就是说,每个语句必须以分号结束。它表明一个逻辑实体的结束。例如:
int a;
int b;
复制代码
保留字
下表列出了XDR
语言中的保留字。这些保留字不能作为常量名、变量名或其他标识符名称。
关键字 | 说明 |
---|---|
int | 声明整型变量 |
hyper | 声明长整型变量 |
unsigned | 声明无符号类型变量 |
float | 声明浮点型变量 |
double | 声明双精度浮点型变量 |
enum | 声明枚举类型 |
bool | 声明布尔类型 |
opaque | 声明字节流数组类型 |
string | 声明字符串类型 |
struct | 声明结构体类型 |
union | 声明共用体类型 |
switch | 声明共用体类型和用于开关语句 |
case | 开关语句分支 |
typedef | 用以给数据类型取别名 |
void | 声明空值,声明无返回值或无参数的操作 |
注释
XDR
语言有2种注释方法:
-
使用
//
注释// 单行注释 复制代码
-
使用
/* */
注释/* 单行注释 */ /* 多行注释 多行注释 ... */ 复制代码
定义变量
定义变量的语法如下:
type-name variable_name = value;
复制代码
XDR
数据类型
XDR
语言提供了多种数据类型来帮助描述协议的数据格式,下面将会一一展开介绍。
整数类型
XDR
语言提供的整数类型有:
类型 | 存储大小 |
---|---|
int(整型) | 4字节 |
unsigned int(无符号整型) | 4字节 |
hyper(长整型) | 8字节 |
unsigned hyper(无符号长整型) | 8字节 |
各个整数类型定义变量的语法如下:
int a;
unsigned int b;
hyper c;
unsigned hyper d;
复制代码
实例演示:
int a = 10; unsigned hyper d = 10000; 复制代码
浮点数类型
XDR
语言提供的浮点数类型有:
类型 | 存储大小 | 精度 |
---|---|---|
float(单精度浮点型) | 4字节 | 6 位小数 |
double(双进度浮点型) | 8字节 | 15 位小数 |
XDR
语言的浮点数类型使用的是IEEE 754标准。
各个浮点数类型定义变量的语法如下:
float a;
double b;
复制代码
实例演示:
float a = 1.2; double b = 3.402823E+38; 复制代码
枚举类型
XDR
使用enum
定义枚举类型,语法如下:
enum identifier { name-identifier = constant, ... } ;
复制代码
注意:枚举成员的值的类型为int
类型;每个枚举成员的值都是唯一的。
实例演示:通过枚举描述红绿蓝3种颜色
enum color_type { RED = 1, GREEN = 2, BLUE = 3 } ; color_type color = RED; 复制代码
布尔类型
XDR
使用bool
定义布尔类型变量,语法如下:
bool identifier;
复制代码
布尔类型只有2个值:FALSE
或者 TRUE
。
实例演示:
bool a = TRUE; 复制代码
Opaque Data
类型
Opaque Data
类型主要用来描述字节流数组,它有2种类型:定长和变长Opaque Data
类型。
XDR
使用opaque
声明Opaque Data
类型。
定长Opaque Data
类型
定长Opaque Data
类型定义变量的语法如下:
opaque identifier[n];
复制代码
其中,n
是一个整数常量,用于声明数组的长度。
如果
n
不是4的倍数,程序应对数组进行补齐操作,即在第n
个字节后添加r
(r 取值范围为:[0,3])个值为0的字节,使得(n+r) mod 4 = 0
。定长
Opaque Data
类型的数据格式如下图所示:
0 1 ... +--------+--------+...+--------+--------+...+--------+ | byte 0 | byte 1 |...|byte n-1| 0 |...| 0 | +--------+--------+...+--------+--------+...+--------+ |<-----------n bytes---------->|<------r bytes------>| |<-----------n+r (where (n+r) mod 4 = 0)------------>| FIXED-LENGTH OPAQUE 复制代码
实例演示:
opaque byteBox[128]; 复制代码
变长Opaque Data
类型
变长Opaque Data
类型定义变量的语法如下:
opaque identifier<m>;
// or
opaque identifier<>;
复制代码
其中,m
是一个整数常量,用于声明数组的最大长度。
若通过第二种方式(不明确声明数组的最大长度)声明定义变量,则数组默认最大长度为:(2^32) - 1
。
如果
m
不是4的倍数,程序应对数组进行补齐操作,即在第m
个字节后添加r
(r 取值范围为:[0,3])个值为0的字节,使得(m+r) mod 4 = 0
。变长
Opaque Data
类型的数据格式如下图所示:
0 1 2 3 4 5 ... +-----+-----+-----+-----+-----+-----+...+-----+-----+...+-----+ | length n |byte0|byte1|...| n-1 | 0 |...| 0 | +-----+-----+-----+-----+-----+-----+...+-----+-----+...+-----+ |<-------4 bytes------->|<------n bytes------>|<---r bytes--->| |<----n+r (where (n+r) mod 4 = 0)---->| VARIABLE-LENGTH OPAQUE 复制代码
其中,数组前4个字节声明了数组的真实长度(有效数据长度)。
实例演示:
opaque byteBox<>; 复制代码
字符串类型
字符串类型主要用来描述ASCII字符数组,它是变长数据类型。
XDR
使用string
定义字符串类型变量,语法如下:
string object<m>;
//or
string object<>;
复制代码
其中,m
是一个整数常量,用于声明数组的最大长度。
若通过第二种方式(不明确声明数组的最大长度)定义字符串类型变量,则数组默认最大长度为:(2^32) - 1
。
如果
m
不是4的倍数,程序应对数组进行补齐操作,即在第m
个字节后添加r
(r 取值范围为:[0,3])个值为0的字节,使得(m+r) mod 4 = 0
。字符串类型的数据格式如下图所示:
0 1 2 3 4 5 ... +-----+-----+-----+-----+-----+-----+...+-----+-----+...+-----+ | length n |byte0|byte1|...| n-1 | 0 |...| 0 | +-----+-----+-----+-----+-----+-----+...+-----+-----+...+-----+ |<-------4 bytes------->|<------n bytes------>|<---r bytes--->| |<----n+r (where (n+r) mod 4 = 0)---->| STRING 复制代码
其中,数组前4个字节声明了数组的真实长度(有效数据长度)。
实例演示:
string asciiBox<>; 复制代码
数组类型
数组类型主要用来描述已知的数据类型的元素数组,它有2种类型:定长和变长数组类型。
在数组中,每个元素的长度都是4的倍数。
数组每个元素的数据类型相同,但是它们的长度却不一定相同,比如字符串数组。
定长数组类型
定长数组类型定义变量的语法如下:
type-name identifier[n];
复制代码
其中,n
是一个整数常量,用于声明数组的长度。
定长数组类型的数据格式如下图所示:
+---+---+---+---+---+---+---+---+...+---+---+---+---+ | element 0 | element 1 |...| element n-1 | +---+---+---+---+---+---+---+---+...+---+---+---+---+ |<--------------------n elements------------------->| FIXED-LENGTH ARRAY 复制代码
实例演示:
string strList[10]; 复制代码
变长数组类型
变长数组类型定义变量的语法如下:
type-name identifier<m>;
// or
type-name identifier<>;
复制代码
其中,m
是一个整数常量,用于声明数组的最大长度。
若通过第二种方式(不明确声明数组的最大长度)定义变量,则数组默认最大长度为:(2^32) - 1
。
变长数组类型的数据格式如下图所示:
0 1 2 3 +--+--+--+--+--+--+--+--+--+--+--+--+...+--+--+--+--+ | n | element 0 | element 1 |...|element n-1| +--+--+--+--+--+--+--+--+--+--+--+--+...+--+--+--+--+ |<-4 bytes->|<--------------n elements------------->| COUNTED ARRAY 复制代码
其中,数组前4个字节声明了数组的真实长度(有效数据长度)。
实例演示:
string strList<>; 复制代码
结构体类型
结构体类型主要用于描述自定义的数据对象类型。
XDR
使用struct
定义结构体类型,语法如下:
struct identifier {
component-declaration-A;
component-declaration-B;
...
};
复制代码
注意:结构体中的成员可以是不同的数据类型,但是成员的长度都应该是4的倍数。
实例演示:
struct msg { unsigned int id; string body<>; }; `` 复制代码
共用体类型
共用体类型主要用于描述“根据不同条件返回不同数据类型”的数据类型。
XDR
使用union switch
定义共用体类型,语法如下:
union switch (discriminant-declaration) {
case discriminant-value-A:
arm-declaration-A;
case discriminant-value-B:
arm-declaration-B;
...
default: default-declaration;
} identifier;
复制代码
注意:每个case
关键字后面都需要跟着一个合法的判断值。default
语句是可选的。
实例演示:根据颜色返回字节流数组或者结构体或者空的数据类型。
union switch (color_type color) { case RED: opaque results[0]; case BLUE: struct { unsigned int hex; } info; default: void; } 复制代码
Void
XDR
使用void
代表空。用于描述无值的情况,或者用于描述不接受数据作为输入或不接受数据作为输出的操作。
Constant
XDR
使用const
为字面量定义一个符号名称,语法如下:
const name-identifier = n;
复制代码
实例演示:在下面的例子中,
pi
这个符号常量等同于整数常量3.14159。
const pi = 3.14159; 复制代码
Typedef
XDR
使用typedef
为已声明的数据类型定义一个新标识符。
需要注意的是,在不同场景下,为已声明的数据类型定义一个新标识符会有不同的语法:
-
为
struct
、union
、enum
数据类型定义新标识符typedef <<struct, union, or enum definition>> identifier; 复制代码
实例演示:例如定义
bool
类型。typedef enum { /* using typedef */ FALSE = 0, TRUE = 1 } bool; // or enum bool { /* preferred alternative */ FALSE = 0, TRUE = 1 }; 复制代码
-
为数组类型定义新标识符
typedef type_name identifier[n]; 复制代码
实例演示:定义一个int数组。
typedef int byteBox[1024]; 复制代码
这时候,下面定义
kb
变量2种方式都是可以的。byteBox kb; // or int kb[1024]; 复制代码
-
为其他数据数据类型定义新标识符
typedef type_name identifier; 复制代码
实例演示:定义一个
byte
类型。typedef int byte; 复制代码
Optional-data
类型
Optional-data
类型用于描述值可能为空(void
)的数据类型。它相当于C
语言中的指针。
Optional-data
类型定义变量的语法如下:
type-name *identifier;
复制代码
使用XDR
描述协议
下面将会通过一个小案例演示XDR
是如何描述协议的数据格式的。
下图为以太网协议中“帧”的数据格式:
我们现在使用XDR
描述进行描述:
struct frame {
opaque d_mac[6];
opaque s_mac[6];
opaque type[2];
opaque data<1500>;
opaque fcs[4];
}
复制代码