本文是ROHC压缩官网单个IP包压缩示例教程的翻译,原文请参考:https://rohc-lib.org/presentation/getting-started/
关于ROHC的基础知识和ROHC库安装,请参考作者博客的相关文章。
以下是程序的详细创建过程,每一步都对要添加的代码位置做了前后说明,可以直接跳过这部分查看最后的完整程序
1. 新建测试程序文件
2. 搭建程序基本框架
#include
int main(int argc, char **argv)
{
printf("This program will compress one single IPv4 packet\n");
return 0;
}
3. 编译运行基本程序
4. 创建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数据包生成程序
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;
}
//声明状态变量
/* 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 */
以上程序说明
以上程序只是针对单个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;
}