真的好久没写博文了....(好像我每次都要来真么一句...)。不过既然开了坑,就一定要填下去~~
最近我的程序,多多少少也有一些进展~,抓包列表的那个界面及功能已经大体完成了,通过这个学习到了不少。现在来分享一下~~~
我的抓包的显示界面是这样的:
最初想了几个实现方式:
1.开启一个临时文件,将数据存入,在同时读出(即使用winpcap提供的dumpfile功能)
2.使用定时器,间隔刷新窗口,显示数据
3.使用某种触发方式,每抓到一个包,刷新一次。
在这几个方式里,我觉得最好的是临时文件的方式,可是苦于不知道如何实现(其实对于方法3,我也不知道实现方式。)。于是最先使用了,定时器方式。
在窗口初始化的时候,设置定时器(settimer()),然后,定时刷新。但是在实际中,我发现两个问题,一是、定时器触发间隔不好确定,如果定得太短,刷新太快,窗口更本不显示,如果定的太小,又有问题;二是、在定时器中加入循环,造成程序卡死。
这种方式不可行。
这时候,以前收藏的一篇文章,“在vs2008MFC下开发基于winpcap的网络嗅探器(IP,TCP,UDP)_百度文库”启发了我。他使用了线程,来完成写临时文件的工作。
我之前从来没有考虑过使用线程...(我真不是程序员啊...我搞网络方向的啊...)。不过既然现在有了这种解决方式,问题就简单了。但是具体做起来,我又实现了两种。
1.开一个线程写文件,在使用定时器,定时从文件中读数据。
2.开启两个线程,一个读,一个写。
这两个方式,都有一些问题,第一种方式,刷新闪烁,看着很不舒服。第二种方式,线程执行顺序不定,也许会产生问题。但是最后,我还是使用了第二种方式,为了防止读早于写,我使用ResumeThread和sleep,一方面延迟线程启动,一方面防止读取过快。
这样,就基本完成了。
另外,在这里,讲一个我遇到的问题
- /*6 byte MAC address*/
- typedef struct mac_address {
- u_char byte1;
- u_char byte2;
- u_char byte3;
- u_char byte4;
- u_char byte5;
- u_char byte6;
- }mac_address;
- /*ethernet header*/
- typedef struct ethernet_header {
- mac_address daddr;
- mac_address saddr;
- u_short proto;
- }ethernet_header;
上面是我定义的MAC地址和以太网报头。
问题出在u_short proto这个字段上。
- eh = (ethernet_header *)pkt_data;
eh是ethernet_header类型,pkt_data是一个串,就是截取的数据包的。
- eh->proto
我使用这个字段来判断上层是IPv4,IPV6,ARP,RARP还是其他的协议。
ipv4此字段为0x0800,但是使用如下代码后,发现了问题
- 0x0800 == eh->proto
这个判断永远不为真!!!
IPv4的包是最常见的包了,怎么会抓不到呢??在抓包的问题上,肯定不会有问题(即不可能抓不到),那么问题肯定出在eh->proto上。
我写了个小程序,来输出eh->proto的值,结果发现,输出的是8!!!怎么回事呢??
想了半天,觉得肯定是字节序在作祟~~
又去看了一下网络字节序和主机字节序,大约明白了。
我们先看看两种字节序的储存方式,
网络 字节序
从左往右,0->31,数据依次放入,读的时候,从左往右读,就OK了。
主机字节序
从左往右,31->0,数据依次放入,读的时候,从0位开始读,每一字节按从左到右读(字节序嘛~~)
这样一来,0800,是按网络字节序写入的。而u_short用主机字节序,于是就读出了0008,就是8了。
于是,是用htons()进行转换,问题解决~!!!!
在这里,我突然想到,之前那篇文章中写的关于sockaddr中的那个地址,上次好像写的不太对。
毕业设计(简易网络协议分析器)编写历程(五)完
转载于:https://blog.51cto.com/eaglexhh/540440