IP helper: GetIfTable 函數可以得到很多網絡狀態信息:網絡流量,網絡狀態等:

 

GetIfTable,

 

編程實現查詢網絡狀態[含c代碼]
前兩天因爲其他原因需要編寫一段查詢網絡狀態的代碼,一開始的想法是查詢註冊表中的某個鍵值,後來查了老半天,雖然找到了那個鍵,但是比較麻煩,我在這裏就不再贅述了,有興趣的可以上網查相關的資料。如果你找不到,也可以給我消息,我可以提供給你。
因爲查詢註冊表的方法實在麻煩,就轉向與其它的方法獲取網絡狀態。也就是確認網絡的連通性如何。後來查到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了。原來就這麼簡單!

一個簡單的擴展,你通過不斷調用這個函數,就可以製作出一個網絡流量分析的圖來了。有興趣的可以自己實現一下,別忘了發一份給我。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章