XDR: External Data Representation

简介

XDR全称为External Data Representation,是一个描述和编码数据的标准。1987年由Sun公司(Sun Microsystems, Inc)发明。

XDR同时是一门语言,主要用来描述协议的数据格式,如RPCNFS等协议就是使用它来描述自身的数据格式。

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为已声明的数据类型定义一个新标识符。

需要注意的是,在不同场景下,为已声明的数据类型定义一个新标识符会有不同的语法:

  • structunionenum数据类型定义新标识符

    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];
}
复制代码

转载于:https://juejin.im/post/5c835ce66fb9a04a037a06ce

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值