真的好久没写博文了....(好像我每次都要来真么一句...)。不过既然开了坑,就一定要填下去~~

 

最近我的程序,多多少少也有一些进展~,抓包列表的那个界面及功能已经大体完成了,通过这个学习到了不少。现在来分享一下~~~

 

我的抓包的显示界面是这样的:

 

抓包界面

最初想了几个实现方式:

1.开启一个临时文件,将数据存入,在同时读出(即使用winpcap提供的dumpfile功能)

2.使用定时器,间隔刷新窗口,显示数据

3.使用某种触发方式,每抓到一个包,刷新一次。

 

在这几个方式里,我觉得最好的是临时文件的方式,可是苦于不知道如何实现(其实对于方法3,我也不知道实现方式。)。于是最先使用了,定时器方式。

在窗口初始化的时候,设置定时器(settimer()),然后,定时刷新。但是在实际中,我发现两个问题,一是、定时器触发间隔不好确定,如果定得太短,刷新太快,窗口更本不显示,如果定的太小,又有问题;二是、在定时器中加入循环,造成程序卡死。

这种方式不可行。

这时候,以前收藏的一篇文章,“在vs2008MFC下开发基于winpcap的网络嗅探器(IP,TCP,UDP)_百度文库”启发了我。他使用了线程,来完成写临时文件的工作。

我之前从来没有考虑过使用线程...(我真不是程序员啊...我搞网络方向的啊...)。不过既然现在有了这种解决方式,问题就简单了。但是具体做起来,我又实现了两种。

1.开一个线程写文件,在使用定时器,定时从文件中读数据。

2.开启两个线程,一个读,一个写。

这两个方式,都有一些问题,第一种方式,刷新闪烁,看着很不舒服。第二种方式,线程执行顺序不定,也许会产生问题。但是最后,我还是使用了第二种方式,为了防止读早于写,我使用ResumeThread和sleep,一方面延迟线程启动,一方面防止读取过快。

这样,就基本完成了。

另外,在这里,讲一个我遇到的问题

 

 
  
  1. /*6 byte MAC address*/ 
  2. typedef struct mac_address { 
  3.     u_char byte1; 
  4.     u_char byte2; 
  5.     u_char byte3; 
  6.     u_char byte4; 
  7.     u_char byte5; 
  8.     u_char byte6; 
  9. }mac_address; 
  10.  
  11. /*ethernet header*/ 
  12. typedef struct ethernet_header { 
  13.     mac_address daddr; 
  14.     mac_address saddr; 
  15.     u_short proto; 
  16. }ethernet_header; 

上面是我定义的MAC地址和以太网报头。

问题出在u_short proto这个字段上。

 
  
  1. eh = (ethernet_header *)pkt_data; 

eh是ethernet_header类型,pkt_data是一个串,就是截取的数据包的。

 

 
  
  1. eh->proto 

我使用这个字段来判断上层是IPv4,IPV6,ARP,RARP还是其他的协议。

ipv4此字段为0x0800,但是使用如下代码后,发现了问题

 
  
  1. 0x0800 == eh->proto 

这个判断永远不为真!!!

IPv4的包是最常见的包了,怎么会抓不到呢??在抓包的问题上,肯定不会有问题(即不可能抓不到),那么问题肯定出在eh->proto上。

我写了个小程序,来输出eh->proto的值,结果发现,输出的是8!!!怎么回事呢??

想了半天,觉得肯定是字节序在作祟~~

又去看了一下网络字节序和主机字节序,大约明白了。

我们先看看两种字节序的储存方式,

网络 字节序

网络字节序

从左往右,0->31,数据依次放入,读的时候,从左往右读,就OK了。

主机字节序

 

主机字节序

从左往右,31->0,数据依次放入,读的时候,从0位开始读,每一字节按从左到右读(字节序嘛~~)

这样一来,0800,是按网络字节序写入的。而u_short用主机字节序,于是就读出了0008,就是8了。

 

于是,是用htons()进行转换,问题解决~!!!!

在这里,我突然想到,之前那篇文章中写的关于sockaddr中的那个地址,上次好像写的不太对。

 

毕业设计(简易网络协议分析器)编写历程(五)完