搞拓展性、灵活性的数据包过滤机制
来源:互联网 发布:linux cat 查看日志 编辑:程序博客网 时间:2024/05/20 10:53
/*搞拓展性、灵活性的数据包过滤机制
功能说明: 背景:
项目要求过滤掉上报比较频繁的高通数据包,由于APK的性能限制,最终决定在基线完成这个功能,但是由于手机代码不完整,所以只能在上报数据包的出口函数即log_commit中添加过滤机制,这里能够看到的仅仅是二进制码流,所以要将数据包解析出来,然后进行过滤判断。同时每个数据包,可以按照不同的时间跨度进行过滤。例如:有的数据包是1秒最多上报一次,如果多余一次则过滤掉多出来的。有的数据包则是500毫秒上报一次。
代码特点: 面临的两个难题:
1、可拓展性:最简单的方式添加或者删除一个要过滤的数据包,要能够匹配多种样式的判断条件
2、性能:由于是在log_commit中添加处理,就是说每一个数据包都会进行判断,因此性能很重要。
先看看最后的成品代码:
在 log_commit中插入IsFilterLogs来判断是否需要过滤,是则直接返回,不发送数据包。
c代码
void log_commit (PACK(void *) ptr)
{
if (ptr)
{
if(TRUE == IsFilterLogs((char*)ptr))
{
return;
}
//其他代码
}
过滤数据的具体处理
c代码
int IsFilterLogs(char* Msg)
{
BEGIN_FILTER
FILTER_LOG(FILTER_LOG0, 500)
FILTER_LOG(FILTER_LOG2, 200)
END_FILTER
}
如果需要添加一个过滤只需要添加一行 FILTER_LOG(FILTER_LOG2, 200)就可以了。FILTER_LOG2是logcode,200是时间跨度,单位MS。
我把所有的流程处理全部封装成宏隐藏起来。实现真正的OCP。
我们先看看宏展开后的代码:
c代码
int IsFilterLogs(char* Msg)
{
unsigned short LogCode = 0;
unsigned int TimeStamp = 0;
LogCode = *(unsigned short*)(Msg + 2);
TimeStamp = *(unsigned int*)(Msg + 4);
int ret = 0;
do
{
if(FILTER_LOG0 == LogCode)
{
static unsigned int LastTimeStamp = 0;
ret = IsFilterLog(TimeStamp, &LastTimeStamp, 500);
break;
}
if(FILTER_LOG2 == LogCode)
{
static unsigned int LastTimeStamp = 0;
ret = IsFilterLog(TimeStamp, &LastTimeStamp, 600);
break;
}
}while(0);
return ret;
}
其中IsFilterLog是具体的业务处理,不作讨论。
这里用到两个技巧:
1、do{}while(0)
所有需要过滤的数据包都是用if条件来判断的,有人会说你为什么不用表驱动,因为效率,表驱动需要循环,其效率没有直接的if判断来的快。
这个技巧可以让我在找到对应的logcode,并且处理完成以后,直接跳出while循环不再判断其他的logcode。
为什么不用if else?因为不好抽象,第一个if前面是没有else的。
为什么不用switch case?因为switch只能判断一种条件,如果这里仅仅是判断logcode,那没问题,如果需要两种判断,switch就不能满足了,不够灵活。
2、局部静态变量
静态变量其实是没有局部这种说法的,因为它不再栈上,而是在数据区,但是我们却可以通过这种方式来限制他的作用域,就说我可以在不同的作用域定义相同的静态变量,这样更加利于抽象。
为什么不用全局变量?因为全局变量要定义在函数外面,这样做不方便抽象,每添加一个过滤就要手动添加一个全局变量,不方便。
宏的封装
c代码
#define BEGIN_FILTER \
unsigned short LogCode = 0;\
unsigned int TimeStamp = 0;\
int ret = FALSE;\
LogCode = *(unsigned short*)(Msg + 2);\
TimeStamp = *(unsigned int*)(Msg + 4);\
do\
{
#define FILTER_LOG(logid, duration) \
if(logid == LogCode)\
{\
static unsigned int LastTimeStamp = 0;\
ret = IsFilterLog(TimeStamp, &LastTimeStamp, duration);\
break;\
}
#define END_FILTER \
}while(0);\
return ret;
将一个完成的功能拆分成三个宏的组合,抽象出变化的和不变的部分,后续添加删除过滤数据包仅仅会用到第二个宏。
更高的拓展性,如果需要其他样式的判断,那么只需要性添加一种宏就好了,比如后面我需要组装自定义数据包,就添加了一种宏
#define CUSTOM_PKT(logid, CustomPackagefun, IsFilter) \
if (FILTER_LOG1 == LogCode)\
{\
CustomPackagefun(Msg);\
ret = IsFilter;\
}
*/
#define FILTER_LOG0 0x5079U
#define FILTER_LOG1 0x5160U
#define FILTER_LOG2 0x5060U
#define BEGIN_FILTER \
unsigned short LogCode = 0;\
unsigned int TimeStamp = 0;\
int ret = FALSE;\
LogCode = *(unsigned short*)(Msg + 2);\
TimeStamp = *(unsigned int*)(Msg + 6);\
do\
{
#define FILTER_LOG(logid, duration) \
if(logid == LogCode)\
{\
static unsigned int LastTimeStamp = 0;\
ret = IsFilterLog(TimeStamp, &LastTimeStamp, duration);\
break;\
}
#define END_FILTER \
}while(0);\
return ret;
int IsFilterLog(unsigned int TimeStamp, unsigned int *pLastTimeStamp, unsigned int Duration)
{
int Counter = 0;
if (0 == *pLastTimeStamp)
{
*pLastTimeStamp = TimeStamp;
return FALSE;
}
Counter = TimeStamp - *pLastTimeStamp;
*pLastTimeStamp = TimeStamp;
Counter = Counter * 1.25;
if(Counter >= Duration)
{
return FALSE;
}
return TRUE;
}
int IsFilterLogs(char* Msg)
{
BEGIN_FILTER
FILTER_LOG(FILTER_LOG0, 500)
FILTER_LOG(FILTER_LOG2, 200)
END_FILTER
}
- 搞拓展性、灵活性的数据包过滤机制
- 基于netfilter机制的IP数据包过滤驱动模版
- 过滤数据包
- wireshark过滤抓取到的数据包
- Maven内置了三大特性:属性、Profile和资源过滤来支持构建的灵活性。
- Maven内置了三大特性:属性、Profile和资源过滤来支持构建的灵活性。
- Maven内置了三大特性:属性、Profile和资源过滤来支持构建的灵活性。
- android的过滤机制
- Android的过滤机制
- Android的过滤机制
- JavaScript的灵活性
- windows 数据包过滤结构图
- windows 数据包过滤结构图
- wireshark过滤数据包
- tcpdump 过滤数据包
- Wireshark 数据包过滤规则
- 过滤及分析数据包
- dubbo拓展点机制的IOC特性
- 1.3.线程基础_等待线程
- 阿里巴巴集团2013年净利润达35.61亿美元
- 自定义UICollectionViewLayout并添加UIDynamic
- asp.net log4net 设置
- 1.4.线程基础_线程组
- 搞拓展性、灵活性的数据包过滤机制
- 佛学中的生活哲理2
- 转:C++深入浅出之正则表达式(一)
- 快速排序
- eclipse安装aptana stadio 3 plugin插件
- Ubuntu搭建FTP服务器
- MAc下安装cocos2d-x
- CentOS5.6 部署haproxy代理做负载均衡
- 【Hibernate学习笔记】Hibernate的内置映射类型