利用开源ASN1C库实现asn.1的编解码

最近在研究MMS的时候接触到了抽象语义记法ASN.1(Abstract Syntax Notation One),于是对它做了一番了解,下面将这几天的学习到的做下记录,以供以后偷懒。

  ASN.1是一种 ISO/ITU-T 标准,描述了一种对数据进行表示、编码、传输和解码的数据格式。它提供了一整套正规的格式用于描述对象的结构,而不管语言上如何执行及这些数据的具体指代,也不用去管到底是什么样的应用程序,也就是说这种记法独立于编程语言,具有平台无关性。关于它的更多的介绍百度文库有很多资源,这里提供一个 ISO/ITU-T 标准关于本部分标准的链接,全英文看起来是吃力了点,但慢慢品读下来往往会有想不到的收获。(http://www.itu.int/ITU-T/recommendations/index.aspx),在search栏输入x.680~x.683或x.690可以查看到ASN.1的具体标准及编解码的方法,或者从http://www.itu.int/ITU-T/studygroups/com17/languages/获得相关文档。

  有了ASN.1和相关编码的概念之后,接下来就是如何用编程语言实现ASN.1的编解码了,下面结合开源编译器ASN1C对这部分做详细介绍。

  一、下载asn.1 编译器ASN1C

  在http://lionet.info/asn1c/download.html处下载,此处我选择了“Windows installer: asn1c-0.9.21.exe”,下载后双击安装即可。

  本文假设安装于“D:\Program Files\asn1c”。

  二、创建asn.1抽象模型并利用ASN1C编译器生成C语言类型文件

  1、asn.1文本描述如下

  点击(此处)折叠或打开

  RetangleTest DEFINITIONS ::=BEGIN

  Rectangle ::= SEQUENCE{

  height INTEGER, -- Height of the rectangle

  width INTEGER -- Width of the rectangle

  }

  END

  保存文件为“D:\Program Files\asn1c\try.asn1"。

  2、利用ASN1C工具生成try.asn1的C语言类型文件

  假设ASN1C安装在“D:\Program Files\asn1c”路径下,可以按如下步骤生成C语言类型文件:

  ①打开控制台:"开始-运行-cmd";

  ②进入到软件目录下:cd “D:\Program Files\asn1c”;

  ③执行生成指令:输入asn1c -S skeletons -fskeletons-copy -fnative-types try.asn1+回车enter

  其中-S -fskeletons-copy -fnative-types参数可以在“D:\Program Files\asn1c\Help\asn1c-usage.pdf”使用手册查到相关说明。

  若执行成功,则有如下信息输出到控制台

  并可以看到在“D:\Program Files\asn1c”目录下,增加了许多文件,这些文件都是后面要用到的:

  三、在VS2010中创建asn.1的编解码demo工程

  1、创建win32 console工程asn1_demo

  2、将步骤二生成的所有.h和.c文件拷贝到asn1_demo工程文件夹下

  3、将.h和.c文件添加到工程中

  4、创建main.c文件,内容如下

  点击(此处)折叠或打开

  #include

  #include

  #include

  char tab[8];

  /*

  * This is a custom function which writes the

  * encoded output into a global test table

  */

  static int decode_callback(const void *buffer, size_t size, void *app_key)

  {

  static int i = 0;

  memcpy(&tab[i],buffer,size);

  i += size;

  }

  int main()

  {

  Rectangle_t *rectangle; /* Type to encode */

  asn_enc_rval_t ec; /* Encoder return value */

  /* Allocate the Rectangle_t */

  rectangle = (Rectangle_t*)calloc(1, sizeof(Rectangle_t)); /* not */

  if(!rectangle) {

  perror("calloc() failed");

  exit(71); /* better, EX_OSERR */

  }

  /* Initialize the Rectangle members */

  rectangle->height = 42; /* any random value */

  rectangle->width = 23; /* any random value */

  /* Encode the Rectangle type as BER (DER) */

  ec = der_encode(&asn_DEF_Rectangle,

  rectangle, decode_callback, tab);

  if(ec.encoded == -1) {

  fprintf(stderr,

  "Could not encode Rectangle (at %s)\n",

  ec.failed_type ? ec.failed_type->name : "unknown");

  exit(65); /* better, EX_DATAERR */

  } else {

  fprintf(stderr, "Created %s with BER encoded Rectangle\n",

  "");

  }

  /* Also print the constructed Rectangle XER encoded (XML) */

  xer_fprint(stdout, &asn_DEF_Rectangle, rectangle);

  return 0;

  }

  5、移除converter-sample.c

  6、编译,若出现头文件找不到问题,在工程属性的头文件包含路径下指定头文件路径即可。

  7、运行,将断点设于最有一句"return 0"处,可看到控制台显示如下,该xml格式的数据是55行执行的结果。

  此时,观察全局数组table,可以看到里面的内容即为Rectangle的编码后的十六进制数据为 30 06 02 01 2a 02 01 17。

  四、解码

  解码的example可查看用户手册“D:\Program Files\asn1c\Help\asn1c-usage.pdf”,和编码example类似,这里不做赘述。

  • 0
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值