使用c语言库asn1c对asn文件格式实现编解码

Posted luffy5459

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用c语言库asn1c对asn文件格式实现编解码相关的知识,希望对你有一定的参考价值。

    针对asn文件编解码工作,asn1c这个开源工具对c/c++的支持非常好。可以很方便的安装和使用,目前这个工具是开源的,最新版本是0.9.28,项目地址:github.com/vlm/asn1c。官方文档地址:Open Source ASN.1 Compiler: asn1c 0.9.28

    这个工具在linux上的安装很方便。

    这个工具还有一个很方便的地方在于,它可以直接将asn文件转化为c语言项目所需要的的头文件和源文件。

    下面通过一个简单的示例来演示如何通过asn1c这个工具来实现asn格式数据编解码。

     1、准备asn文件:

RectangleTest DEFINITIONS ::= BEGIN
Rectangle ::= SEQUENCE 
  height INTEGER,
  width INTEGER

END

      2、在该文件当前目录运行生成命令

asn1c -gen-PER *.asn

    运行该命令,会在本目录下生成很多头文件和源代码文件。其中包含一个拥有main主函数的测试代码,一般我们不使用这个源代码来运行示例,自己编写一个。

     3、自己编写一个main.c代码如下:

#include <stdio.h>
#include <sys/types.h>
#include "Rectangle.h"
static int write_out(const void *buffer,size_t size,void *key)

  FILE *out_fp = key;
  return (fwrite(buffer,1,size,out_fp)==size)?0:-1;

int main()

  Rectangle_t *rect;
  asn_enc_rval_t ec;
  rect = calloc(1,sizeof(Rectangle_t));
  //init rect
  rect->width = 23;
  rect->height = 42;
  const char* filename = "Test";
  FILE *fp = fopen(filename,"wb");
  ec = uper_encode(&asn_DEF_Rectangle,rect,write_out,fp);
  if(ec.encoded==-1)
    printf("encode error.\\n");
  else
    printf("encode ok,result in %s.\\n",filename);
  
  return 0;

    这段代码很简单,主要定义了一个写入函数,作为uper_encode的回调函数,在这个函数里面,将编码后的结果写入文件,这个文件在本示例里面用Test命名。

     4、 编译,运行,如果不出错,那么就是编码成功。这里稍微提一下,编译命令:

gcc -o main -I. *.c

    这里的-I.参数指的是,包含本目录。 

     5、这个结果还不好验证。但是我们可以通过一个asn在线编译器进行验证。 在这个页面,有三个视图,在最左边的视图,我们手动输入我们上面的asn文件内容:

 

    在第二个部分,我们通过json格式把代码中的参数设置进去。

    点击第二个试图中的Encode,如果没有报错,那么页面最右侧的第三个控制台输出试图里面就会显示编码结果,各个类型的都会列出来,这里我们关注这个示例中的uper类型,结果是012a0117。

 

    这个是通过三方网站来验证我们的编码结果。

    接着我们把linux上的编码结果文件Test下载到windows上,使用notepad++打开,通过hex插件,可以查看16进制表示,结果与上面的编码是一致的:

 

    至此,我们通过一个简单的示例,实现了asn编码。编码类型采用的是uper,因为这个在实际中使用的很广泛。

    6、接着改动main.c文件,实现解码功能,大致意思是读取Test文件,然后通过asn1c提供的解码方法uper_decode()解码。代码如下:

#include <stdio.h>
#include <sys/types.h>
#include "Rectangle.h"
int main()

  Rectangle_t *rect;
  asn_dec_rval_t dc;
  char buf[20];
  rect = calloc(1,sizeof(Rectangle_t));
  const char* filename = "Test";
  FILE *fp = fopen(filename,"r");
  size_t size;
  size = fread(buf,1,sizeof buf,fp);
  asn_codec_ctx_t *opt_codec_ctx = 0;
  dc = uper_decode(opt_codec_ctx,&asn_DEF_Rectangle,(void **)&rect,buf,size,0,0);
  if(dc.code==-1)
    printf("decode error.\\n");
  else
    printf("decode ok,rect's width=%d,height=%d.\\n",rect->width,rect->height);
  
  return 0;

     7、编译,运行代码,打印截图如下:

    解码成功。 

以上是关于使用c语言库asn1c对asn文件格式实现编解码的主要内容,如果未能解决你的问题,请参考以下文章

ASN.1编解码:asn1c的版本分析-诺基亚

ASN.1编解码:asn1cenber和unber

ASN.1编解码:asn1c-ORAN-E2AP

ASN.1编解码:asn1c-ORAN-E2AP编解码示例

ASN.1编解码:ORAN-E2AP分析

asn1 编码与解码