好几天没写了,这两天又堕落去了...加上学校每天喊着检查寝室卫生,却又迟迟不来人...坑爹呢!!!检查不合格...通报批评.....至于么...

先小小的发泄下~~呵呵~~这两天这破事搞得我烦死了...

下面进入正题。PS:吸取前次教训,直接用火狐...不过IE9出了,不知道怎么样呢?

上次以后,毕设进度继续龟速前进。今天就说说这次的一些问题吧

1.上篇文章,我说道了关于定义全局变量的问题,当时一个pcap_if_t的变量一直没办法弄成全局的,这两天仔细看了看,发现了这篇文章:http://blog.csdn.net/wt31016/archive/2008/12/13/3504848.aspx。里面关于MFC中定义全局变量的两种方法:定义在app类中;使用一个专用类,用静态变量搞定。有比较详细的介绍,有兴趣的可以看看。我还是用的静态变量的方法,觉得这样比较清晰些。在app类中定义的方式,我没试过,大家可以试试。

2.关于sockaddr的一些东西。上次我说了,我使用的IP地址转换成串的函数是来自于WinPcap的官方技术文档的,没有自己研究过。这两天,好好的看了下,感觉还是受益匪浅的,现在和大家分享下~~

先是代码:

IPV4的

 

 
  
  1. /*---ipv4地址转换---*/ 
  2. char* CDevStatus::iptos(u_long in) 
  3.     static char output[IPTOSBUFFERS][3*4+3+1]; 
  4.     static short which; 
  5.     u_char *p; 
  6.     p = (u_char *)∈ 
  7.     which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);         
  8.     _snprintf_s(output[which], sizeof(output[which]), sizeof(output[which]),"%d.%d.%d.%d", p[0], p[1], p[2], p[3]); 
  9.     return output[which]; 
  10.  

IPV6的:

 

 
  
  1. /*-------ipv6地址转换-----*/ 
  2. char* CDevStatus::ip6tos(struct sockaddr * sockaddr, char * address, int addrlen) 
  3.     socklen_t sockaddrlen; 
  4.  
  5.     #ifdef WIN32 
  6.     sockaddrlen = sizeof(struct sockaddr_in6); 
  7.     #else 
  8.     /*这个sockaddr_storage是个可以足够存储IPV4,V6或者其他地址类型数据的结构体,用于跨平台的开发*/ 
  9.     sockaddrlen = sizeof(struct sockaddr_storage); 
  10.     #endif 
  11.  
  12.     /*getnameinfo这个函数用于不依靠协议的获取地址信息的能力*/ 
  13.     if(getnameinfo(sockaddr,  
  14.         sockaddrlen,  
  15.         address,  
  16.         addrlen,  
  17.         NULL,  
  18.         0,  
  19.         NI_NUMERICHOST) != 0) address = NULL; 
  20.  
  21.     return address; 

不过要讲这些,我先说说关于sockaddr

这个是MSDN中,关于IPV4的sockaddr的定义

sockaddr_ipv4

有两个结构体,听同学说,好像是一个用来写入,一个用来读出???不太清楚,总之,这两个东西是可以相互转换的。相对sockaddr_in更方便获取信息一些。

这里,关于地址的内容,就是struct in_addr sin_addr这个字段了。这又是一个结构体,其内容如下

 

in_addr

其实一目了然,其中有一个共用体(不看到这个,我都不记得这个关键词了..)。公用体中是三个大小一样的结构体,分别是用u_char,u_short和u_long表示的IP地址。对于u_char很简单,一个元素表示点分十进制的一段;u_short倒是没试过,应该和后面的u_long差不多。

解释一下u_long,我的IP是:110.53.196.100。u_long的值是:1690580334。这个值是神马意思呢?放入计算机器里,就看的很清楚(win7下的这个计算器的程序员模式真不错~~呵呵)

 

u_long

注意中间的二进制位,从左往右,每8bit一读

0110 0100=100,1100 0100 = 196,0011 0101 =53,0110 1110=110。看吧,这就不就是IP地址吗?不过是反过来的,为啥呢?网络字节序,bigending。

其实从上面的解释中看,可以用u_char来转换,更直观些,我本来也想这样做,后来发现,由于有地址,掩码,广播地址等等,用u_char通用性不好(其实很重要的一点是,各种字符串之间的转换,我觉得太麻烦...有现成的代码,看懂再说)

关于IPV4的那段代码,主要的问题在于这句:

p = (u_char *)∈

这里是什么意思呢?其实就是用u_char的方式来读取u_long,一个8bit,一个32bit,读一次,刚好是一段。不过,值得注意的是,这里,p进行转换后,指向的是,u_long的最低位,如果写成数字的话,就是指向最右边一位,所以刚好,把网络字节序和主机字节序不同的问题解决了

另外,关于代码中

static char output[IPTOSBUFFERS][3*4+3+1];

其中的3*4+3+1,这个怎么说呢?3*4,就是指点分十进制最大可能的数字占的字节数(因为转换的时候,是字符)。如110.111.111.111,数字部分占了3*4=12个字符。3指的是那三个点;1,指结尾符/0。不过,我仍有一处不明,为什么它要定义一个12行的数组???实际程序中,只用到3行,不过可能是出于通用性考虑。

 

IPV4讲完了,说说IPV6吧

其实就结构体定义来说,和v4差不多,

 

 

 

从上面看,第一个想到的,是像使用ipv4地址时,使用u_char来直接显示,但是问题在于,IPV6采用冒分16进制,每一段时4个16进制数,不管用u_char还是用u_word,都显得太冗长。同时,16进制是4bit,一个u_char是8bit,每四个要打一个冒号,这样处理起来挺麻烦的。另外,IPV6有将中间连续的0转化为“::”的表示法,这样就更麻烦了。

我引用的程序里,使用了

getnameinfo

这个方法,要使用这个方法,以及定义sockaddr_t(这个就是int型),要加一个头文件#include <wspiapi.h>。这样处理是使用了跨协议的函数getnameifor(任何协议都可以使用它来获取信息)。具体的,我还没研究过。只知道sockaddr_storage也是一个跨协议的结构体。部分在注释里写了。

 

现在,显示接口信息的部分全部写完了,帖个成品图

 

 

捕获数据已经开始写了,希望能顺利~~~

 

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