好几天没写了,这两天又堕落去了...加上学校每天喊着检查寝室卫生,却又迟迟不来人...坑爹呢!!!检查不合格...通报批评.....至于么...
先小小的发泄下~~呵呵~~这两天这破事搞得我烦死了...
下面进入正题。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的
- /*---ipv4地址转换---*/
- char* CDevStatus::iptos(u_long in)
- {
- static char output[IPTOSBUFFERS][3*4+3+1];
- static short which;
- u_char *p;
- p = (u_char *)∈
- which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
- _snprintf_s(output[which], sizeof(output[which]), sizeof(output[which]),"%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
- return output[which];
- }
IPV6的:
- /*-------ipv6地址转换-----*/
- char* CDevStatus::ip6tos(struct sockaddr * sockaddr, char * address, int addrlen)
- {
- socklen_t sockaddrlen;
- #ifdef WIN32
- sockaddrlen = sizeof(struct sockaddr_in6);
- #else
- /*这个sockaddr_storage是个可以足够存储IPV4,V6或者其他地址类型数据的结构体,用于跨平台的开发*/
- sockaddrlen = sizeof(struct sockaddr_storage);
- #endif
- /*getnameinfo这个函数用于不依靠协议的获取地址信息的能力*/
- if(getnameinfo(sockaddr,
- sockaddrlen,
- address,
- addrlen,
- NULL,
- 0,
- NI_NUMERICHOST) != 0) address = NULL;
- return address;
- }
不过要讲这些,我先说说关于sockaddr
这个是MSDN中,关于IPV4的sockaddr的定义
有两个结构体,听同学说,好像是一个用来写入,一个用来读出???不太清楚,总之,这两个东西是可以相互转换的。相对sockaddr_in更方便获取信息一些。
这里,关于地址的内容,就是struct in_addr sin_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下的这个计算器的程序员模式真不错~~呵呵)
注意中间的二进制位,从左往右,每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也是一个跨协议的结构体。部分在注释里写了。
现在,显示接口信息的部分全部写完了,帖个成品图
捕获数据已经开始写了,希望能顺利~~~
毕业设计(简易网络协议分析器)编写历程(四)完
转载于:https://blog.51cto.com/eaglexhh/524979