项目总结 (2)

很累的一个月,为了赶项目天天码代码,第一次在看到代码的时候有想吐的感觉。

用 lua 作为配置文件

因为在之前的一个项目中师兄采用了网络作为前后端交互的方式,这样两部分分开调试比较方便,从此以后实验室的项目不管是否需要联网都采用这种方法,结果在项目中除了根据甲方的需求把控件拖来拖去之外剩下的就是解析各种各样的报文格式。

前段时间另一个项目需要写一个报文测试的小工具,就是有一堆自定义的报文格式,界面上有下拉条选择或者让用户自己输入某个字段的值,然后把报文发出去,收到返回信息并且把内容解析一下。我已经不怎么碰这个项目了,但是这次时间有点紧,于是哥又“被”当仁不让地充当临时工把活接了下来。在前一个项目中师兄使用了 xml 作为报文格式配置文件,这个小工具我打算用 lua 来试一下,也算是一个实际应用的机会。界面用了 qt,因为现在 qt 俨然成为本人实验室项目界面开发的默认工具了。

先说说使用 lua 作为配置文件吧。报文格式是常见的 TLV 格式(“T”表示 type,“L”表示长度,“V”表示数据),有些字段会有限定的范围:

packet = {
    "报文名称",
    {"字段名称1", "字段类型", 个数, {可选值1, "说明1"}, {可选值2}, {起始值, 结束值, 步长}, ...},
    ......
}

其中字段类型定义了一些常见的类型并规定了长度,例如“int”就是 4 字节,“double”就是 8 个字节等。个数表示该字段中包含了多少个这样的类型。例如…

阅读全文…

c 语言实现封装,继承和多态

封装

c 语言使用的 struct 没有访问控制,任何程序都能访问 struct 的成员。为了隐藏 struct 里的成员名称和位置,可以将具体的 struct 定义放在 .c 文件中,而在头文件中增加一个指向该结构体的指针。因为无法得知指针类型的具体定义,对这个私有结构体成员的访问只能通过提供的 set() 和 get() 函数。

下面是头文件 test.h 的定义:

#ifndef __TEST_H__
#define __TEST_H__

struct test {
    struct _test* t;
};

int test_constructor(struct test*);
int test_get(struct test*);
void test_set(struct test*, 

阅读全文…

项目总结 (1)

年前开始做这个项目,虽然主要的功能放假前已经完成,但是老板为了体现实验室的主题——并行计算,要求把一个简单的 hash 查找功能弄成复杂的“多线程并行计算”,尽管最后的多线程实现比串行的还慢(通过使用 gprof 分析发现花在同步上的开销超过了多线程带来的并行效益,因为实际的 hash 查找不怎么耗时间)。当然这些我是无力改变的,不过有个好处就是老板虽然不懂具体技术,但是却不会瞎指挥,所以在实现上倒是挺自由的,因此可以随便尝试自己想学的东西,只要最后项目完成就行。

好了,发完牢骚之后总结一下从中学到的东西吧。

生产者-消费者问题

我觉得所有的问题基本都可以归结为生产者-消费者问题:输入是生产者,程序处理是消费者。刚开始写的是串行的代码,使用惯用的套路:

int main(void)
{
    ......

    while ((rec = producer()))
        consumer(rec);

    ......
}

串行程序需要由 main() 函数驱动,主要逻辑由 main() 函数搭建,这样的话如果非要把多线程嵌到这个模型中,看起来会有点奇怪:

void* producer(void)
{
    /* blcok until data arrives */
    return get_resource_from(resource_pool);
}

void consumer(void* 

阅读全文…

使用 libpcap 分析网络报文 (2)

这里打算写写报文分析接口的设计。 一般来说,以太网的报文格式为:

+------------+-------------------+-----+
| eth header | ip/arp/... header | ... |
+------------+-------------------+-----+

例如手机上的一次网页请求的报文格式可能像下面这样:

+-----+----+-----+-----+----+-----+--------------+
| eth | ip | udp | gtp | ip | tcp | http request |
+-----+----+-----+-----+----+-----+--------------+

不同的应用对于不同协议的内容可能会有不同的需求。比方说,一个应用希望抓取 gtp 报头中的 pdp context,以此建立起某个手机号在某段时间内使用的是哪个 ip 的映射,它不关心上层应用的内容;另一个应用希望抓取内层 ip …

阅读全文…