报头压缩-ROHC报头压缩简单示例

序言

本文是ROHC压缩官网单个IP包压缩示例教程的翻译,原文请参考:https://rohc-lib.org/presentation/getting-started/

关于ROHC的基础知识和ROHC库安装,请参考作者博客的相关文章。

简单报头压缩程序

以下是程序的详细创建过程,每一步都对要添加的代码位置做了前后说明,可以直接跳过这部分查看最后的完整程序

  • 1. 新建测试程序文件

    • touch rohc_hello_world.c
    • gedit rohc_hello_world.c
  • 2. 搭建程序基本框架

    • 在源文件中输入
#include 

int main(int argc, char **argv)
{
    printf("This program will compress one single IPv4 packet\n");
    return 0;
}
  • 3. 编译运行基本程序

    • gcc -o rohc_hello_world -Wall rohc_hello_world.c
    • ./rohc_hello_world
  • 4. 创建IPv4包

    • 添加必要头文件
    • 定义数据缓存和净荷内容
    • 在主函数框架添加IPv4包生成程序
#include      /* for the IPv4 header */
#include          /* for strlen() */
#include   /* for the rohc_buf_*() functions */

/* 缓存大小,字节计 */
#define BUFFER_SIZE 2048

/* IPv4包的净荷内容 */
#define FAKE_PAYLOAD "hello, ROHC world!"
int main(int argc, char **argv)
{
    /* 待压缩的IP包缓存 */
    uint8_t ip_buffer[BUFFER_SIZE];
    /* 待压缩的IP包存储结构体 */
    struct rohc_buf ip_packet = rohc_buf_init_empty(ip_buffer, BUFFER_SIZE);
    /* IP报头 */
    struct iphdr *ip_header;
    size_t i;

    printf("This program will compress one single IPv4 packet\n");

    /* 创建简单的IPv4数据包 */
    printf("build a fake IP packet\n");
    ip_header = (struct iphdr *) rohc_buf_data(ip_packet);
    ip_header->version = 4;                         //we create an IP header version 4
    ip_header->ihl = 5;                             //min. IPv4 header length (in 32-bit words)
    ip_packet.len += ip_header->ihl * 4;
    ip_header->tos = 0;                             //TOS is not important for the example
    ip_header->tot_len = htons(ip_packet.len + strlen(FAKE_PAYLOAD));
    ip_header->id = 0;                              //ID is not important for the example
    ip_header->frag_off = 0;                        //No packet fragmentation
    ip_header->ttl = 1;                             //TTL is not important for the example
    ip_header->protocol = 134;                      //protocol number
    ip_header->check = 0x3fa9;                      //checksum
    ip_header->saddr = htonl(0x01020304);           //source address 1.2.3.4
    ip_header->daddr = htonl(0x05060708);           //destination addr. 5.6.7.8

    /* 将净荷复制到报头之后 */
    rohc_buf_append(&ip_packet, (uint8_t *) FAKE_PAYLOAD, strlen(FAKE_PAYLOAD));

    /* 输出新建的IP报文 */
    for(i = 0; i < ip_packet.len; i++)
    {
        printf("0x%02x ", rohc_buf_byte_at(ip_packet, i));
        if(i != 0 && ((i + 1) % 8) == 0)
        {
            printf("\n");
        }
    }
    if(i != 0 && (i % 8) != 0) /* be sure to go to the line */
    {
          printf("\n");
    }

    return 0;
}
  • 5. 编译运行IP数据包生成程序

    • 直接gcc -o rohc_hello_world -Wall rohc_hello_world.c编译会报错,因为缺少库文件
    • 通过 gcc -o rohc_hello_world -Wall $(pkg-config rohc –cflags) rohc_hello_world.c $(pkg-config rohc –libs)编译
  • 6. 创建ROHC压缩器

    • 添加必要头文件
    • 定义随机数生成函数
    • 声明压缩器类型
    • 压缩器创建
    • 添加压缩器回收函数
#include              /* required by time() */
#include    /* for rohc_comp_*() functions */
#define FAKE_PAYLOAD "hello, ROHC world!"

/* 每次调用都返回一个随机数 */
static int gen_random_num(const struct rohc_comp *const comp,
                              void *const user_context)
{
    return rand();
}


int main(int argc, char **argv)
{
    ...
}
//声明压缩器类型
int main(int argc, char **argv)
{

    struct rohc_comp *compressor;  /* the ROHC compressor */

    /* 待压缩的IP包缓存 */
    uint8_t ip_buffer[BUFFER_SIZE];
    ...
}
//压缩器创建
printf("This program will compress one single IPv4 packet\n");

/* 使用当前时间初始化随机数生成器 */
srand(time(NULL));

/* 默认参数初始化ROHC压缩器 */
printf("create the ROHC compressor\n");
compressor = rohc_comp_new2(ROHC_SMALL_CID, ROHC_SMALL_CID_MAX,
                                   gen_random_num, NULL);
if(compressor == NULL)
{
fprintf(stderr, "failed create the ROHC compressor\n");
return 1;
}

printf("build a fake IP packet\n");
//压缩器资源回收
/* 输出新建的IP数据包 */
for(i = 0; i < ip_packet.len; i++)
{
    printf("0x%02x ", rohc_buf_byte_at(ip_packet, i));
    if(i != 0 && ((i + 1) % 8) == 0)
        {
             printf("\n");
        }
}
if(i != 0 && (i % 8) != 0) /* be sure to go to the line */
{
    printf("\n");
}

/* 释放ROHC资源 */
printf("destroy the ROHC decompressor\n");
rohc_comp_free(compressor);

return 0;
}
  • 7. 压缩数据包
    • 声明状态变量
    • 添加压缩函数
    • 压缩结果输出
    • 添加profile使能函数
//声明状态变量
/* IP包缓存 */
uint8_t ip_buffer[BUFFER_SIZE];
/* IP数据包存储结构体 */
struct rohc_buf ip_packet = rohc_buf_init_empty(ip_buffer, BUFFER_SIZE);
/* IP报头结构体 */
struct iphdr *ip_header;

/* ROHC数据包缓存 */
uint8_t rohc_buffer[BUFFER_SIZE];
/* ROHC数据包存储结构体 */
struct rohc_buf rohc_packet = rohc_buf_init_empty(rohc_buffer, BUFFER_SIZE);

rohc_status_t rohc_status;
size_t i; 
//压缩函数,结果输出
/* 输出新建的IP数据包 */
for(i = 0; i < ip_packet.len; i++)
{
    printf("0x%02x ", rohc_buf_byte_at(ip_packet, i));
        if(i != 0 && ((i + 1) % 8) == 0)
        {
             printf("\n");
        }
}
if(i != 0 && (i % 8) != 0) /* be sure to go to the line */
{
    printf("\n");
}

/* 压缩IP报文 */
printf("compress the fake IP packet\n");
rohc_status = rohc_compress4(compressor, ip_packet, &rohc_packet);
if(rohc_status != ROHC_STATUS_OK)
{
    fprintf(stderr, "compression of fake IP packet failed: %s (%d)\n",
                  rohc_strerror(rohc_status), rohc_status);
    /* 清除压缩器,输出错误编号 */
        rohc_comp_free(compressor);
        return 1;
}

/* 输出ROHC数据包 */
printf("ROHC packet resulting from the ROHC compression:\n");
for(i = 0; i < rohc_packet.len; i++)
{
     printf("0x%02x ", rohc_buf_byte_at(rohc_packet, i));
     if(i != 0 && ((i + 1) % 8) == 0)
     {
           printf("\n");
     }
}
if(i != 0 && (i % 8) != 0) /* be sure to go to the line */
{
      printf("\n");
}

/* 释放压缩器资源 */
printf("destroy the ROHC decompressor\n");
rohc_comp_free(compressor);
//添加压缩profile
/* 默认参数创建ROHC压缩器 */
printf("create the ROHC compressor\n");
compressor = rohc_comp_new2(ROHC_SMALL_CID, ROHC_SMALL_CID_MAX,
                                   gen_random_num, NULL);
if(compressor == NULL)
{
     fprintf(stderr, "failed create the ROHC compressor\n");
     return 1;
}

/* IP-only profile */
printf("enable the IP-only compression profile\n");
if(!rohc_comp_enable_profile(compressor, ROHC_PROFILE_IP))
{
     fprintf(stderr, "failed to enable the IP-only profile\n");
     rohc_comp_free(compressor);
     return 1;
}

/* 创建IP数据包 */
printf("build a fake IP packet\n");
ip_header = (struct iphdr *) rohc_buf_data(ip_packet);
ip_header->version = 4; /* we create an IP header version 4 */
  • 8. 编译运行整个程序
    • gcc -o rohc_hello_world -Wall $(pkg-config rohc –cflags) rohc_hello_world.c $(pkg-config rohc –libs)
    • ./rohc_hello_world

程序说明

  • 以上程序说明

    • 以上程序只是针对单个IP数据包的压缩

    • 上述程序压缩后的结果比压缩前的数据包还长,原因在于刚开始压缩需要建立上下文信息等,如果压缩多个数据包会明显看到压缩效果

完整程序

#include   /* for the printf() function */

/* includes required to create a fake IP packet */
#include   /* for the IPv4 header */
#include       /* for the strlen() */
#include   /* for the rohc_buf_*() functions */

/* includes required to use the compression part of the ROHC library */
#include              /* required by time() */
#include    /* for rohc_comp_*() functions */

/* The size (in bytes) of the buffers used in the program */
#define BUFFER_SIZE 2048

/* The payload for the fake IP packet */
#define FAKE_PAYLOAD "hello, ROHC world!"

/* return a random number every time it is called */
static int gen_random_num(const struct rohc_comp *const comp,
                          void *const user_context)
{
   return rand();
}

/* The main entry point of the program (arguments are not used) */
int main(int argc, char **argv)
{
   struct rohc_comp *compressor;  /* the ROHC compressor */

   /* the buffer that will contain the IPv4 packet to compress */
   uint8_t ip_buffer[BUFFER_SIZE];
   /* the packet that will contain the IPv4 packet to compress */
   struct rohc_buf ip_packet = rohc_buf_init_empty(ip_buffer, BUFFER_SIZE);
   /* the header of the IPv4 packet */
   struct iphdr *ip_header;

   uint8_t rohc_buffer[BUFFER_SIZE];
   /* the packet that will contain the resulting ROHC packet */
   struct rohc_buf rohc_packet = rohc_buf_init_empty(rohc_buffer, BUFFER_SIZE);

   rohc_status_t rohc_status;
   size_t i;

   /* print the purpose of the program on the console */
   printf("This program will compress one single IPv4 packet\n");

   /* initialize the random generator with the current time */
   srand(time(NULL));

   /* create a ROHC compressor with good default parameters */
   printf("create the ROHC compressor\n");
   compressor = rohc_comp_new2(ROHC_SMALL_CID, ROHC_SMALL_CID_MAX,
                               gen_random_num, NULL);
   if(compressor == NULL)
   {
      fprintf(stderr, "failed create the ROHC compressor\n");
      /* leave with an error code */
      return 1;
   }

   /* enable the IP-only compression profile */
   printf("enable the IP-only compression profile\n");
   if(!rohc_comp_enable_profile(compressor, ROHC_PROFILE_IP))
   {
      fprintf(stderr, "failed to enable the IP-only profile\n");
      /* cleanup compressor, then leave with an error code */
      rohc_comp_free(compressor);
      return 1;
   }

   /* create a fake IP packet for the purpose of this simple program */
   printf("build a fake IP packet\n");
   ip_header = (struct iphdr *) rohc_buf_data(ip_packet);
   ip_header->version = 4; /* we create an IP header version 4 */
   ip_header->ihl = 5; /* min. IPv4 header length (in 32-bit words) */
   ip_packet.len += ip_header->ihl * 4;
   ip_header->tos = 0; /* TOS is not important for the example */
   ip_header->tot_len = htons(ip_packet.len + strlen(FAKE_PAYLOAD));
   ip_header->id = 0; /* ID is not important for the example */
   ip_header->frag_off = 0; /* No packet fragmentation */
   ip_header->ttl = 1; /* TTL is not important for the example */
   ip_header->protocol = 134; /* protocol number */
   ip_header->check = 0x3fa9; /* checksum */
   ip_header->saddr = htonl(0x01020304); /* source address 1.2.3.4 */
   ip_header->daddr = htonl(0x05060708); /* destination addr. 5.6.7.8 */

   /* copy the payload just after the IP header */
   rohc_buf_append(&ip_packet, (uint8_t *) FAKE_PAYLOAD, strlen(FAKE_PAYLOAD));

   /* dump the newly-created IP packet on terminal */
   for(i = 0; i < ip_packet.len; i++)
   {
      printf("0x%02x ", rohc_buf_byte_at(ip_packet, i));
      if(i != 0 && ((i + 1) % 8) == 0)
      {
         printf("\n");
      }
   }
   if(i != 0 && (i % 8) != 0) /* be sure to go to the line */
   {
     printf("\n");
   }

   /* compress the fake IP packet */
   printf("compress the fake IP packet\n");
   rohc_status = rohc_compress4(compressor, ip_packet, &rohc_packet);
   if(rohc_status != ROHC_STATUS_OK)
   {
      fprintf(stderr, "compression of fake IP packet failed: %s (%d)\n",
              rohc_strerror(rohc_status), rohc_status);
      /* cleanup compressor, then leave with an error code */
      rohc_comp_free(compressor);
      return 1;
   }

   /* dump the ROHC packet on terminal */
   printf("ROHC packet resulting from the ROHC compression:\n");
   for(i = 0; i < rohc_packet.len; i++)
   {
      printf("0x%02x ", rohc_buf_byte_at(rohc_packet, i));
      if(i != 0 && ((i + 1) % 8) == 0)
      {
         printf("\n");
      }
   }
   if(i != 0 && (i % 8) != 0) /* be sure to go to the line */
   {
      printf("\n");
   }

   printf("destroy the ROHC decompressor\n");
   rohc_comp_free(compressor);

   /* leave the program with a success code */
   return 0;
}



2017.06.02

你可能感兴趣的:(广播/通信标准/协议)