本文尝试在上一篇文章http://blog.csdn.net/baidu_35692628/article/details/72848022示例的基础上进行改进,程序编译运行与示例中一致。
原程序实现的功能如下:
改进后的ROHC程序实现的功能如下:
示例程序中使用到的函数功能总结如下:
rohc_init_buf_empty() //将rohc_buf结构体数据部分初始化
rohc_comp_new2() //创建压缩器
rohc_comp_enable_profile() //压缩类设置profile-enable
rohc_buf_data() //获取data缓存的位置
rohc_buf_data_at() //获取给定偏离值offset的data缓存位置
rohc_buf_append() //在已有数据之后再添加一定长度数据,同时改变原data长度值
rohc_compress4() //压缩函数
rohc_comp_free() //释放压缩器资源
struct rohc_buf
{
struct rohc_ts time; //数据时间戳
uint8_t *data; //data缓存
size_t max_len; //缓存的最大长度
size_t offset; //data起始位置偏离值
size_t len; //data长度
}
/* IP数据包净荷 */
//==================
char *FAKE_PAYLOAD[PKT_NUM];
int pktNum = 0;
for (pktNum = 0; pktNum < PKT_NUM; pktNum++) //每个包长度相同,内容不同
{
int str_len = 472; //IP净荷长度;for IP
FAKE_PAYLOAD[pktNum] = (char *)malloc(sizeof(char) * BUFFER_SIZE);
FAKE_PAYLOAD[pktNum] = randstr(FAKE_PAYLOAD[pktNum], str_len);
}
/* 随机字符串生成函数 */
//====================
char *randstr(char *dest, int n)
{
int i,randnum;
char eleString[63] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
for (i = 0; i < n; i++)
{
srand(time(NULL)); //以当前时间来设置随机数种子
usleep(100); //每隔100ms更新一次,保证随机种子不同,程序延时的主要来源
randnum = rand()%62; //随机数生成函数
*dest = eleString[randnum]; //从字符串数组中取值
dest++;
}
*dest = '\0'; //字符串结束符
return (dest - n); //返回首地址
}
/* 报文结构体初始化函数 */
void rohc_buf_init_empty_p(struct rohc_buf *packet,uint8_t *buf,int len)
{
packet -> time.sec = 0;
packet -> time.nsec = 0;
packet -> data = buf; //数据指针
packet -> max_len = len;
packet -> offset = 0;
packet -> len = 0;
}
uint8_t *ip_buffer_p;
/* 定义存储多个IP数据包的结构体指针数组 */
int array_num;
struct rohc_buf *IpArray[PKT_NUM];
for (array_num = 0; array_num < PKT_NUM; array_num++)
{
IpArray[array_num] = (struct rohc_buf *)malloc(sizeof(struct rohc_buf));
//每个结构体数组元素的缓存空间,暂定为定长包
ip_buffer_p = (uint8_t *)malloc(sizeof(uint8_t) * BUFFER_SIZE);
//BUFFER_SIZE大小可变
rohc_buf_init_empty_p(IpArray[array_num], ip_buffer_p, BUFFER_SIZE);
//ip_buffer_p指针删除后影响缓存数据赋值吗-不影响,每次分配的空间都未释放
ip_buffer_p = NULL;
}
printf("size of IpArray is %ld \n",sizeof(IpArray));
/* 用默认参数创建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和UDP/IP */
if(!rohc_comp_enable_profiles(compressor, ROHC_PROFILE_IP, ROHC_PROFILE_UDP, -1))
{
fprintf(stderr, "failed to enable the IP-only and IP/UDP-Lite profiles\n");
rohc_comp_free(compressor);
return 1;
}
/* 生成100个相同内容的UDP数据包 */
// UDP报头赋值
udp_header = (struct udphdr *)rohc_buf_data(*(UdpArray[count])); //调用系统自带函数分配报头空间
udp_header -> source = htons(0x04d2); //源端口1234
udp_header -> dest = htons(0x04d3); //目的端口1235
(*(UdpArray[count])).len = 8;
udp_header -> len = htons((*(UdpArray[count])).len + strlen(FAKE_PAYLOAD[count]));
udp_header -> check = 0x0000; //此处UDP校验和使用全零不影响运行
// copy the payload just after the UDP header
// rohc_buf_append()函数会给rohc_buf结构体len字段赋值 = 数据包长度
rohc_buf_append(&(*(UdpArray[count])), (uint8_t *) FAKE_PAYLOAD[count], strlen(FAKE_PAYLOAD[count]));
/* 生成100个相同内容的IPv4数据包 */
printf("build a fake IP packet every time\n");
/* IP报头赋值 */
ip_header = (struct iphdr *) rohc_buf_data(*(IpArray[count]));
ip_header-> version = 4; /* we create an IP header version 4 */
ip_header-> ihl = 5; /* min. IPv4 header length (in 32-bit words) */
(*(IpArray[count])).len += ip_header->ihl * 4;
ip_header-> tos = 0; /* TOS is not important for the example */
ip_header-> tot_len = htons((*(IpArray[count])).len + ntohs(udp_header -> len));
printf("%ld\n",(*(IpArray[count])).len);
printf("%d\n",ntohs(udp_header -> len));
printf("%d\n", ntohs((ip_header->tot_len))); //主机字节序和网络字节序
//记录IP或UDP/IP包长
pkt_len[count] = ntohs((ip_header->tot_len));
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 = 17; /* protocol number */
// ip_header-> check = 0x3ba9; /* checksum */ //原程序直接赋值
ip_header-> saddr = htonl(0x01020304); /* source address 1.2.3.4 */
ip_header-> daddr = htonl(0x05060708); /* destination addr. 5.6.7.8 */
ip_header -> check = htons(IpCheckSum(ip_header,(*(IpArray[count])).len)); //字节序转换,否则出错
/* copy the payload just after the IP header */
rohc_buf_append(&(*(IpArray[count])), (uint8_t *) ((*(UdpArray[count])).data), ntohs(udp_header -> len));
//形参:(压缩器,ip_packet缓存地址,rohc_packet缓存地址)
rohc_status = rohc_compress4(compressor, (*(IpArray[count])), RohcArray[count]);
压缩率计算公式
这里统计所有数据包的总长和压缩字节数进行计算
文章只是尝试修改了ROHC官网的简单示例,没有涉及压缩机制和压缩算法的改进
压缩机制/算法改进需求还请参考完整的ROHC开发程序,github、codeforge等网站均可找到,建议在github寻找
2017.07.18