jackkcg
站務副站長
發表:891 回覆:1050 積分:848 註冊:2002-03-23
發送簡訊給我
|
http://www.zdnet.com.cn/developer/code/story/0,2000081534,39046680-2,00.htm
提取網路介面資訊
其中最主要的兩個函數是GetNumberOfInterfaces和GetInterfaceInfo,前者指出網路介面的個數,後者提取網路介面的資訊。對於第一個函數要說明的一點是它好象並沒有返回正確的值,因爲據MSDN描述:一個網路介面是網卡的邏輯抽象,它們是一對一的關係。而實際情況是我的機器上只有一張網卡,這個函數卻返回了2。實際上,因爲每個系統都附加有一個調試用的網路介面,這個介面的IP位址是127.0.0.1子網路遮罩是255.0.0.0。這個結果可以從程式的輸出看出來。由GetInterfaceInfo返回的IP_INTERFACE_INFO結構中也有一個NumAdapters整型的資料欄記錄了正確的網卡。然後對於GetInterfaceInfo要注意的是它也必須被調用兩次,第一次獲取緩衝大小,第二次才是取值。然後再次讓我感到其怪的是GetInterfaceInfo返回的IP_INTERFACE_INFO不象上面的結構是用鏈表,而是用的動態陣列的方法(到現在什麽線性結構都用上了),所以遍曆其中每一個元素的代碼變成: for(int i=0;iNumAdapters;i++)
{
cout<<"Adapter index:"
IP_INTERFACE_INFO結構的解釋如下: typedef struct _IP_INTERFACE_INFO {
LONG NumAdapters;
// 動態陣列中網路介面元素的個數,通過它來遍歷數
//組
IP_ADAPTER_INDEX_MAP Adapter[1];
// 網路介面資料陣列
} IP_INTERFACE_INFO,*PIP_INTERFACE_INFO;
其中的IP_ADAPTER_INDEX_MAP結構如下: typedef struct _IP_ADAPTER_INDEX_MAP {
ULONG Index;
// 網卡索引
WCHAR Name[MAX_ADAPTER_NAME];
// 網卡名
} IP_ADAPTER_INDEX_MAP, * PIP_ADAPTER_INDEX_MAP;
提取IP資訊
這部分顯然和提取網路介面資訊部分是相同的。
設置本地網路
設置的過程與提取過程其實是換湯不換藥。我不想在這裏演示每一個函數的用法,所以只使用了一個(我認爲)最常用的函數AddIPAddress。這個函數能夠設置本地網路的IP。但不幸的是,這個IP是臨時的,當系統重新啓動或者發生其他的PNP事件的時候這個IP就不存在了。那麽有人會問這有什麽用呢?實際上,每個網路介面卡都可以綁定多個IP,所以在網路環境惡劣的情況下(如校園網)同時預備多個IP以防斷線是有必要的。必須指出的是這種臨時的IP在網路通訊時可能導致的問題現在還沒有測試過,諸如CODEGURU,CSDN,MSDN,或者TECHREPUBLIC對這套API也沒有詳細的解釋(雖然它很有用)。
其他的API函數
這些函數能夠讓你察看或者設置網路資料報文方面的資訊。比方GetIpStatistics、GetIcmpStatistics函數能夠讓你查看當前IP資料報和ICMP資料報的流量,以及廢棄的資料報數量等等。使用這些函數你可以構建自己的網路監控程序檢察網路中的故障。你也可以使用SetIpStatistics 函數來設置相應的IP協定棧屬性,縮短或者延長IP資料報的缺省TTL值。然後你也可以使用GetIpForwardTable、CreateIpForwardEntry 、DeleteIpForwardEntry、SetIpForwardEntry來分別獲取IP路由表的資訊,創建路由表項,刪除路由表項和修改路由表項。也可以用GetBestRoute、 GetBestInterface獲得到達指定IP的最好的路由點和網路介面。
事實上,通過這些函數我們可以得到許多MIB變數(《使用TCP/IP協定實現網際互聯》第二卷),通過這些MIB變數,我們可以非常快速的製作一個網路管理軟體。
未涉及的部分
我們沒有涉及IP Helper API中SendARP函數的使用。實際上,這個函數是我使用這套API的主要原因,它能夠簡單的發送ARP資料包並返回目的機器的MAC位址。我使用這個函數製作了另一個簡單的IP查看程式,它能夠查看局域網上哪些IP正在使用,並能夠顯示它們的MAC位址。如果把這些資訊記錄在文件中,我就可以統計出一天中哪些傢夥的上網時間最長以及其上網的習性並能夠知道哪些人更換了他們的網卡,也可以分析出這個網路的使用情況(我在學校的高峰時段統計出一個網段的254個IP中竟有236個正在使用,可見增加網段的必要了)。我將在後面的文章中說明這個程式的製作。我們也沒有涉及這套API提供的當網路設置改變時向應用程式發出消息的非同步通知功能。因爲它們非常簡單,與WINSOCK中WSAAsyncSelect的使用方法是一樣的,就不再說明了。
後話
討論如何使用API函數也許會被一批"純粹"的程式師所鄙視。但每次看到有人在論壇上急切的詢問如何取得本機閘道,IP地址,路由之類的資訊的時候,我就覺得非常有必要介紹這一套API函數,它能夠(至少在我看來)滿足我們的大部分要求
演示程式源代碼
劉巍 - 高級程式師、軟體設計師,精通VC,VB,COM,PLATFORM SDK,DDK,TCP/IP。獨立開發過 多種windows應用程式,WDM USB驅動程式,網路應用程式。熟悉加密技術,熟悉LINUX下的C/C 開發。
責任編輯:小李(EMAIL:li_shuangzhen@zdnet.com.cn) 歡迎評論或投稿
http://www.zdnet.com.cn/i/developer/story/200208/39046680/code_1.htm
附:演示程式源代碼
// IpHelper.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "windows.h"
#include "iostream.h"
#include "iphlpapi.h"
typedef DWORD(CALLBACK * PGNOINTERFACE)(PDWORD);//GetNumberOfInterfaces
typedef DWORD(CALLBACK * PGAINFO)(PIP_ADAPTER_INFO,PULONG);//GetAdaptersInfo
typedef DWORD(CALLBACK * PGIINFO)(PIP_INTERFACE_INFO,PULONG );//GetInterfaceInfo
typedef DWORD(CALLBACK * PGIAT)(PMIB_IPADDRTABLE,PULONG,BOOL);//GetIpAddrTable
typedef DWORD(CALLBACK * PAIA)(IPAddr,IPMask,DWORD,PULONG,PULONG);//AddIPAddress
int main(int argc, char* argv[])
{
DWORD index=0;
//函數指標
PGAINFO pGAInfo;
//載入IP Helper API 所需的庫文件
HINSTANCE hInst;//實例控制碼
hInst=LoadLibrary("iphlpapi.dll");
if(!hInst)
cout<<"iphlpapi.dll not supported in this platform!\n";
cout<<"net adapters information:"<Index;
//物理位址的長度
cout<<"hardware address length: "AddressLength;i )
cout<<(unsigned int)pInfo->Address[i];
cout<IpAddressList);
while(pAddTemp)/*遍曆IP列表中的每一個元素*/
{
coutNext;
}
//顯示當前使用的IP位址
//因爲在離線狀態下pInfo->CurrentIpAddress被置空,所以有必要做檢查
if(pInfo->CurrentIpAddress)
{
cout<<"current ip using:"<CurrentIpAddress;
while(pAddTemp)/*遍曆IP列表中的每一個元素*/
{
coutNext;
}
}
else
cout<<"network malfunctioning,no ip is in use!\n"<DhcpServer);
while(pAddTemp)/*遍曆IP列表中的每一個元素*/
{
coutNext;
}
//將當前指標移向下一個
pInfo=pInfo->Next;
}
delete pInfoTemp;//回收無用記憶體
//------------------------------------》獲得網卡資料部分結束
cout<table[i].dwAddr)&0x00FF))<<"." <<(unsigned int)((LOWORD(pIPTable->table[i].dwAddr)>>8))<<"." <<(unsigned int)((HIWORD(pIPTable->table[i].dwAddr)&0x00FF))<<"." <<(unsigned int)((HIWORD(pIPTable->table[i].dwAddr))>>8)<table[i].dwMask)&0x00FF))<<"." <<(unsigned int)((LOWORD(pIPTable->table[i].dwMask)>>8))<<"." <<(unsigned int)((HIWORD(pIPTable->table[i].dwMask)&0x00FF))<<"." <<(unsigned int)((HIWORD(pIPTable->table[i].dwMask))>>16)<table[i].dwBCastAddr)&0x00FF))<<"." <<(unsigned int)((LOWORD(pIPTable->table[i].dwBCastAddr)>>8))<<"." <<(unsigned int)((HIWORD(pIPTable->table[i].dwBCastAddr)&0x00FF))<<"." <<(unsigned int)((HIWORD(pIPTable->table[i].dwBCastAddr))>>16)<
------ **********************************************************
哈哈&兵燹
最會的2大絕招 這個不會與那個也不會 哈哈哈 粉好
Delphi K.Top的K.Top分兩個字解釋Top代表尖端的意思,希望本討論區能提供Delphi的尖端新知
K.表Knowlege 知識,就是本站的標語:Open our mind
|