现在的位置: 首页 > 综合 > 正文

查询网络状态

2014年09月05日 ⁄ 综合 ⁄ 共 3614字 ⁄ 字号 评论关闭

导读:
前两天因为其他原因需要编写一段查询网络状态的代码,一开始的想法是查询注册表中的某个键值,后来查了老半天,虽然找到了那个键,但是比较麻烦,我在这里就不再赘述了,有兴趣的可以上网查相关的资料。如果你找不到,也可以给我消息,我可以提供给你。
因为查询注册表的方法实在麻烦,就转向与其它的方法获取网络状态。也就是确认网络的连通性如何。后来查到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 else
{
for(int i=0; idwNumEntries); i++)
if (pMIT->table[i].dwType {
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://www.scdc.com.cn/yycnet/display.asp?id=1200000000000000000000026

抱歉!评论已关闭.