本文共 3889 字,大约阅读时间需要 12 分钟。
导读: 前两天因为其他原因需要编写一段查询网络状态的代码,一开始的想法是查询注册表中的某个键值,后来查了老半天,虽然找到了那个键,但是比较麻烦,我在这里就不再赘述了,有兴趣的可以上网查相关的资料。如果你找不到,也可以给我消息,我可以提供给你。 因为查询注册表的方法实在麻烦,就转向与其它的方法获取网络状态。也就是确认网络的连通性如何。后来查到IpHlpApi[ip助手]里面有一个函数比较好用GetIfTable,通过调用该函数后查询其中返回的参数可以确认网络的连通性。下面是代码: //预定义几个结构 #define MAX_INTERFACE_NAME_LEN 256 #define MAXLEN_PHYSADDR 8 #define MAXLEN_IFDESCR 256 #define ANY_SIZE 1 typedef struct _MIB_IFROW { WCHAR wszName[MAX_INTERFACE_NAME_LEN]; DWORD dwIndex; DWORD dwType; DWORD dwMtu; DWORD dwSpeed; DWORD dwPhysAddrLen; BYTE bPhysAddr[MAXLEN_PHYSADDR]; DWORD dwAdminStatus; DWORD dwOperStatus; DWORD dwLastChange; DWORD dwInOctets; DWORD dwInUcastPkts; DWORD dwInNUcastPkts; DWORD dwInDiscards; DWORD dwInErrors; DWORD dwInUnknownProtos; DWORD dwOutOctets; DWORD dwOutUcastPkts; DWORD dwOutNUcastPkts; DWORD dwOutDiscards; DWORD dwOutErrors; DWORD dwOutQLen; DWORD dwDescrLen; BYTE bDescr[MAXLEN_IFDESCR]; } MIB_IFROW,*PMIB_IFROW; typedef struct _MIB_IFTABLE { DWORD dwNumEntries; MIB_IFROW table[ANY_SIZE]; } MIB_IFTABLE, *PMIB_IFTABLE; typedef DWORD (__stdcall *GIT)(PMIB_IFTABLE, PULONG, BOOL); GIT lpGetIfTable; //检查网络状态函数 //返回值:如果网络连通则返回 true,否则返回false bool _CheckNetGoto() { BOOL bResult=false; DWORD dwSize = 0; HINSTANCE hIphlpDll = LoadLibrary("iphlpapi.dll"); if (hIphlpDll == NULL) { return false;} lpGetIfTable = (GIT)GetProcAddress(hIphlpDll, "GetIfTable"); if (lpGetIfTable == NULL) {return false;} MIB_IFTABLE *pMIT = new MIB_IFTABLE[sizeof(MIB_IFTABLE)]; if (lpGetIfTable(pMIT, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) { delete []pMIT; pMIT = new MIB_IFTABLE[dwSize]; } //dwNumEntries alwayse>=1, and the last entry is loopback interface. if (lpGetIfTable(pMIT, &dwSize, 0) == NO_ERROR) { if (pMIT->dwNumEntries <= 1){ bResult = false; } else { for(int i=0; i<(pMIT->dwNumEntries); i++) if (pMIT->table[i].dwType <= 23) { bResult = pMIT->table[i].dwOperStatus; if (bResult) { delete []pMIT; FreeLibrary(hIphlpDll); return true; } } } } delete []pMIT; FreeLibrary(hIphlpDll); return bResult; } 下面对代码进行一点简单的解释。 好像2000 SP3以上就已经引入了IP助手,但是使用 IpHlpApi.lib 还需要其他一些头文件,引入库什么的。比较麻烦,为了一个GetIfTAble 而引入那么多垃圾,很不值。所以我在预定义处定义了GetIfTable();所需要的参数的类型定义。然后通过GetProcAddress得到 GetIfTable的地址,直接拿指针进行调用。省了很多麻烦。 函数的参数主要说说 PMIB_IFTABLE , 这个指向一个 typedef struct _MIB_IFTABLE { DWORD dwNumEntries; MIB_IFROW table[ANY_SIZE]; } MIB_IFTABLE, *PMIB_IFTABLE; 结构,dwNumEntries指出本机安装的网卡数。(后边会提到),table指向一系列 MIB_IFROW 结构,每个结构指定了当前网卡的状态。这个结构包括了一些很实用的信息,包括网卡的名字(注意,WCHAR类型),网卡描述字串,最大速率,索引,接收到的字节,发送的字节,连通状态,MAC地址等。(这也是一个获取本机MAC地址的好办法。)各取所需吧,我需要的是网络状态。 win 一共定义了6种网络状态: MIB_IF_OPER_STATUS_NON_OPERATIONAL :LAN adapter has been disabled, for example because of an address conflict. MIB_IF_OPER_STATUS_UNREACHABLE WAN :adapter that is not connected. MIB_IF_OPER_STATUS_DISCONNECTED :For LAN adapters: network cable disconnected. For WAN adapters: no carrier. MIB_IF_OPER_STATUS_CONNECTING : WAN adapter that is in the process of connecting. MIB_IF_OPER_STATUS_CONNECTED :WAN adapter that is connected to a remote peer. MIB_IF_OPER_STATUS_OPERATIONAL :Default status for LAN adapters 但是实际应用中,我发现基本上就用到这两种: MIB_IF_OPER_STATUS_NON_OPERATIONAL 网络不通时 MIB_IF_OPER_STATUS_OPERATIONAL 网络连通时 其他状态你可以自行测试。 另外要提的一点比较有趣的东西是,GetIfTable返回时候的 dwNumEntries 值,总是大于或者等于1。[在TCP/IP网络协议正确安装的情况下]后来经过确认,原来M$定义了以下几种网卡的类型: MIB_IF_TYPE_OTHER MIB_IF_TYPE_ETHERNET MIB_IF_TYPE_TOKENRING MIB_IF_TYPE_FDDI MIB_IF_TYPE_PPP MIB_IF_TYPE_LOOPBACK MIB_IF_TYPE_SLIP 第二种就是我们正确安装网卡后的类型。其中最值得注意的是 MIB_IF_TYPE_LOOPBACK 类型,从名字上我们可以看出是loopback,不好翻译,“回溯网卡”?无论你的网卡在不在使用,只要你的协议是正确的,调用GetIfTable总是会返回该类型的"网卡",从另外一个角度来考虑,为什么我们平时“ping 127.0.0.1”,其实不是ping的别人,就是ping的这块网卡,因为当tcp/ip协议正确安装的时候, MIB_IF_TYPE_LOOPBACK 网卡的状态总是 MIB_IF_OPER_STATUS_OPERATIONAL ,所以,无论你的网卡如何,你都能 ping 127.0.0.1了。原来就这么简单! 一个简单的扩展,你通过不断调用这个函数,就可以制作出一个网络流量分析的图来了。有兴趣的可以自己实现一下,别忘了发一份给我。 文章写的太简单,实际做的时候远没有那么复杂。而且,我也不知道安焦以前有没有发过类似的文章,如果重复的话。嘿嘿,绝对没有盗版的意思。 如果你有好的想法或者其他的问题,欢迎交流。这是我的几个朋友们开的论坛,我经常在线,欢迎大家来交流。 本文转自转载地址:http://yniob.baihongyu.com/