Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4374
  • 博文数量: 1
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 12
  • 用 户 组: 普通用户
  • 注册时间: 2014-06-23 10:06
文章分类
文章存档

2014年(1)

我的朋友
最近访客

分类: C/C++

2014-06-23 10:18:04

        最近在研究MMS的时候接触到了抽象语义记法ASN.1(Abstract Syntax Notation One),于是对它做了一番了解,下面将这几天的学习到的做下记录,以供以后偷懒。
        ASN.1是一种 ISO/ITU-T 标准,描述了一种对数据进行表示、编码、传输和解码的数据格式。它提供了一整套正规的格式用于描述对象的结构,而不管语言上如何执行及这些数据的具体指代,也不用去管到底是什么样的应用程序,也就是说这种记法独立于编程语言,具有平台无关性。关于它的更多的介绍百度文库有很多资源,这里提供一个 ISO/ITU-T 标准关于本部分标准的链接,全英文看起来是吃力了点,但慢慢品读下来往往会有想不到的收获。(),在search栏输入x.680~x.683或x.690可以查看到ASN.1的具体标准及编解码的方法,或者从获得相关文档。
        有了ASN.1和相关编码的概念之后,接下来就是如何用编程语言实现ASN.1的编解码了,下面结合开源编译器ASN1C对这部分做详细介绍。
       
        一、下载asn.1 编译器ASN1C
                在处下载,此处我选择了“Windows installer: ”,下载后双击安装即可。
                本文假设安装于“D:\Program Files\asn1c”。

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

点击(此处)折叠或打开

  1. RetangleTest DEFINITIONS ::=BEGIN
  2.     Rectangle ::= SEQUENCE{
  3.         height INTEGER,        -- Height of the rectangle
  4.         width INTEGER        -- Width of the rectangle
  5.     }
  6. 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文件,内容如下

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <Rectangle.h>

  4. char tab[8];
  5. /*
  6. * This is a custom function which writes the
  7. * encoded output into a global test table
  8. */
  9. static int decode_callback(const void *buffer, size_t size, void *app_key)
  10. {
  11.     static int i = 0;
  12.     
  13.     memcpy(&tab[i],buffer,size);

  14.     i += size;
  15. }



  16. int main()
  17. {
  18.     Rectangle_t *rectangle; /* Type to encode */
  19.     asn_enc_rval_t ec; /* Encoder return value */

  20.     /* Allocate the Rectangle_t */
  21.     rectangle = (Rectangle_t*)calloc(1, sizeof(Rectangle_t)); /* not */

  22.     if(!rectangle) {
  23.         perror("calloc() failed");
  24.         exit(71); /* better, EX_OSERR */
  25.     }

  26.     /* Initialize the Rectangle members */
  27.     rectangle->height = 42; /* any random value */
  28.     rectangle->width = 23; /* any random value */



  29.     /* Encode the Rectangle type as BER (DER) */
  30.     ec = der_encode(&asn_DEF_Rectangle,
  31.         rectangle, decode_callback, tab);

  32.     if(ec.encoded == -1) {
  33.         fprintf(stderr,
  34.             "Could not encode Rectangle (at %s)\n",
  35.             ec.failed_type ? ec.failed_type->name : "unknown");
  36.         exit(65); /* better, EX_DATAERR */
  37.     } else {
  38.         fprintf(stderr, "Created %s with BER encoded Rectangle\n",
  39.             "");
  40.     }

  41.     /* Also print the constructed Rectangle XER encoded (XML) */
  42.     xer_fprint(stdout, &asn_DEF_Rectangle, rectangle);
  43.     return 0;
  44. }
                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类似,这里不做赘述。

阅读(1076) | 评论(2) | 转发(0) |
0

上一篇:没有了

下一篇:没有了

给主人留下些什么吧!~~

zjqywsw112014-06-23 17:09:08

object_identifier.cl里的:
将  //unsigned LE __attribute__ ((unused)) = 1; 
改为:unsigned int LE = 1;

zjqywsw112014-06-23 17:07:56

本人在win7下 用vc6编译后,遇到个问题:当asn1中有UTCTIME类型时,编译不过~
解决方法(不知是否科学,有遇到该问题的可以参考下):
将如下代码屏蔽掉
generalizedTime.c里的:
/* setenv("TZ", "UTC", 1);*/
/* setenv("TZ", tzold, 1);*/
/* unsetenv("TZ");*/
// #warning "PLEASE STOP AND READ!"
// #warning "  timegm() is implemented via getenv(\"TZ\")tenv(\"TZ\"), which may be not thread-safe."
// #warning &q