Windows網絡編程實用教程:第6章 探測網絡中的在線設備_第1頁
Windows網絡編程實用教程:第6章 探測網絡中的在線設備_第2頁
Windows網絡編程實用教程:第6章 探測網絡中的在線設備_第3頁
Windows網絡編程實用教程:第6章 探測網絡中的在線設備_第4頁
Windows網絡編程實用教程:第6章 探測網絡中的在線設備_第5頁
已閱讀5頁,還剩89頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、第6章 探測網絡中的在線設備課程描述要對一個網絡進行管理,首先應該知道網絡中包括哪些設備和這些設備的在線狀態。通常應用程序從獲取本地網絡信息開始,計算本地子網中包含的所有可能的IP地址,然后使用類似ping命令的功能來發現本地網絡。本章將介紹獲取本地網絡信息和探測網絡中在線設備的方法。 本章知識點獲取本地計算機的網絡信息掃描子網中的地址6.1 獲取本地計算機的網絡信息6.1.1 使用ipconfig命令獲取本地網絡信息6.1.2 獲取本地網絡信息的開發接口IP Helper API6.1.3 獲取本地網絡適配器信息6.1.4 獲取本地主機名、域名和DNS服務器信息6.1.5 獲取本地計算機網絡

2、接口的基本信息6.1.6 獲取本地計算機IP地址表6.1.7 添加和刪除IP地址6.1.1 使用ipconfig命令獲取本地網絡信息在Windows操作系統中,可以使用ipconfig命令獲取本地網絡信息。在命令窗口中執行ipconfig命令。 查看詳細網絡信息執行下面的命令:ipconfig /all 6.1.2 獲取本地網絡信息的開發接口IP Helper APIIP Helper API可以實現的主要功能如下:獲取網絡配置的信息。管理網絡適配器(Network Adapter),也就是通常所說的網卡,它位于數據鏈路層。管理網絡接口(Interface)。接口表示節點上對應連接的部分,它位

3、于IP層,因此可以在接口上綁定IP地址。在IP Helper API中,網絡適配器和接口是一一對應的。管理IP地址。使用ARP協議。獲取IP和ICMP協議中的信息。管理路由信息。接收網絡事務的通知信息。接收TCP和UDP信息。引用IPHELPAPI.lib在Visual C+項目中,可以使用下面的語句引用IPHELPAPI.lib。#pragma comment(lib, IPHLPAPI.lib)也可以在項目屬性對話框中選擇“配置屬性”/“鏈接器”/“輸入”,然后在右側的“附加依賴項”中輸入IPHLPAPI.lib。6.1.3 獲取本地網絡適配器信息在iphlpapi.h中聲明了GetAda

4、ptersInfo()函數,調用該函數可以返回本地網絡適配器的基本信息,語法如下:DWORD GetAdaptersInfo( PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen );結構體IP_ADAPTER_INFO在iptypes.h中聲明,定義代碼如下:typedef struct _IP_ADAPTER_INFO struct _IP_ADAPTER_INFO* Next; DWORD ComboIndex; char AdapterNameMAX_ADAPTER_NAME_LENGTH + 4; char DescriptionMAX_

5、ADAPTER_DESCRIPTION_LENGTH + 4; UINT AddressLength; BYTE AddressMAX_ADAPTER_ADDRESS_LENGTH; DWORD Index; UINT Type; UINT DhcpEnabled; PIP_ADDR_STRING CurrentIpAddress; IP_ADDR_STRING IpAddressList; IP_ADDR_STRING GatewayList; IP_ADDR_STRING DhcpServer; BOOL HaveWins; IP_ADDR_STRING PrimaryWinsServer

6、; IP_ADDR_STRING SecondaryWinsServer; time_t LeaseObtained; time_t LeaseExpires; IP_ADAPTER_INFO, *PIP_ADAPTER_INFO;結構體IP_ADAPTER_INFO中定義的成員變量成員變量說明Next指定網絡適配器鏈表中的下一個網絡適配器ComboIndex預留變量AdapterName網絡適配器的名稱Description網絡適配器的描述信息AddressLength網絡適配器MAC地址的長度Address網絡適配器的MAC地址Index網絡適配器索引。當一個網絡適配器被禁用然后又重新啟用

7、后,該適配器的索引將發生變化。因此該值并不是網絡適配器的唯一標識Type網絡適配器的類型,包括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等。這些值在IPIfCons.h中定義DhcpEnabled指定該網絡適配器上是否啟用了DHCP協議CurrentIpAddress預留變量IpAddressList與此網絡適配器相關聯的IP地址列表GatewayList該網絡適配器上定義的I

8、P地址的默認網關DhcpServer該網絡適配器上定義的DHCP服務器的IP地址HaveWins標明該網絡適配器是否啟用了WINSPrimaryWinsServer主WINS服務器的IP地址SecondaryWinsServer從WINS服務器的IP地址LeaseObtained當前的DHCP租借獲取的時間,只有在啟用DHCP時生效LeaseExpires當前的DHCP租借失效的時間,只有在啟用DHCP時生效【例6.1】通過一個實例來介紹如何使用Visual C+編寫獲取本地網絡信息的程序。實例是一個控制臺項目。1聲明頭文件在GetIPConfig.cpp中需要聲明程序中使用的頭文件,并引用I

9、PHLPAPI.lib,代碼如下:#include stdafx.h#pragma comment(lib, IPHLPAPI.lib) #include #include #include 2聲明變量在主函數_tmain()中,首先需要聲明程序中使用的變量,代碼如下:/ 指定獲取到的網絡信息結構體鏈表的指針IP_ADAPTER_INFO *pAdapterInfo;/ 保存獲取到的網絡信息結構體鏈表的長度ULONG ulOutBufLen;/ 返回調用編碼DWORD dwRetVal;/ 在輪循所有網絡適配器信息時使用的單個結構體變量PIP_ADAPTER_INFO pAdapter;3獲取

10、本地網絡適配器信息在獲取本地信息的過程中,需要兩次調用GetAdaptersInfo()函數。第1次調用可以獲取返回數據的大小,第2次調用使用前面獲取到的數據大小作為參數,獲取實際的IP_ADAPTER_INFO結構體內容,具體代碼如下:/ 為pAdapterInfo分配空間pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO);ulOutBufLen = sizeof(IP_ADAPTER_INFO);/ 第1次調用GetAdaptersInfo(),獲取返回結果的大小到ulOutBufLen中if(GetAdapte

11、rsInfo(pAdapterInfo, &ulOutBufLen) != ERROR_SUCCESS)free(pAdapterInfo);pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);/ 第2次調用GetAdaptersInfo(),獲取本地網絡信息到結構體pAdapterInfo中if(dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) != ERROR_SUCCESS)printf(GetAdaptersInfo Error! %dn, dwRetVal);4顯示本地

12、網絡適配器信息現在本地網絡信息已經讀取到pAdapterInfo鏈表中,因為本地計算機上可能安裝多個網絡適配器,所以需要使用While語句循環處理pAdapterInfo鏈表中的每個IP_ADAPTER_INFO結構體,并顯示其中的網絡信息,代碼如下:/ 從pAdapterInfo 獲取并顯示本地網絡信息pAdapter = pAdapterInfo;while(pAdapter)printf(網絡適配器名: tt%sn, pAdapter-AdapterName);printf(網絡適配器描述: t%snn, pAdapter-Description);printf(MAC地址: tt);/

13、 處理MAC地址for(int i=0; iAddressLength; i+)if(i=(pAdapter-AddressLength -1)printf(%.2Xn, (int)pAdapter-Addressi);elseprintf(%.2X-, (int)pAdapter-Addressi); 4顯示本地網絡適配器信息printf(IP地址: tt%sn, pAdapter-IpAddressList.IpAddress.String);printf(子網掩碼: tt%sn, pAdapter-IpAddressList.IpMask.String);printf(網關: ttt%s

14、n, pAdapter-GatewayList.IpAddress.String);printf(*n);if(pAdapter-DhcpEnabled)printf(啟用DHCP: tt是n);printf(DHCP服務器: tt%sn, pAdapter-DhcpServer.IpAddress.String);elseprintf(啟用DHCP: tt否n);/ 處理下一個網絡適配器pAdapter = pAdapter-Next;5釋放資源處理完成后,需要將釋放到pAdapter鏈表所占用的內存空間,代碼如下:/ 釋放資源if(pAdapterInfo)free(pAdapterInf

15、o);6暫停程序,等待用戶響應在顯示本地網絡信息后,程序處于暫停狀態,等待用戶響應,代碼如下:printf(nn);system(pause); return 0;system(pause);語句的功能是暫停系統的工作,并在控制臺輸出“按任意鍵繼續”。用戶按任意鍵后,程序繼續運行,執行return 0;語句退出_tmain()函數。6.1.4 獲取本地主機名、域名和DNS服務器信息調用GetNetworkParams()函數可以返回本地的網絡參數信息,包括本地的主機名、域名和DNS服務器列表等。GetNetworkParams()函數的語法如下:DWORD GetNetworkParams(

16、_out PFIXED_INFO pFixedInfo, _in PULONG pOutBufLen);參數pFixedInfo是輸出參數,它是一個指向緩沖區的指針,緩沖區中使用FIXED_INFO結構體保存獲取到的本地網絡參數信息;參數pOutBufLen是一個指向ULONG變量的指針,保存pFixedInfo緩沖區的大小。PFIXED_INFOPFIXED_INFO是指定結構體FIXED_INFO的指針,它在iptypes.h中聲明,定義代碼如下:typedef struct char HostNameMAX_HOSTNAME_LEN + 4; char DomainNameMAX_DOM

17、AIN_NAME_LEN + 4; PIP_ADDR_STRING CurrentDnsServer; IP_ADDR_STRING DnsServerList; UINT NodeType; char ScopeIdMAX_SCOPE_ID_LEN + 4; UINT EnableRouting; UINT EnableProxy; UINT EnableDns;FIXED_INFO, *PFIXED_INFO;【例6.2】介紹使用IP Helper API獲取本地網絡參數信息的具體代碼。首先創建一個Win32控制臺應用程序,項目名稱為GetNetworkParams,其主文件名為GetNe

18、tworkParams.cpp。1聲明頭文件在GetNetworkParams.cpp中需要聲明程序中使用的頭文件,并引用IPHLPAPI.lib,代碼如下:#include stdafx.h#include #include #include #pragma comment(lib, IPHLPAPI.lib)2聲明變量在主函數_tmain()中,首先需要聲明程序中使用的變量,代碼如下:/ 定義保存本地計算機網絡參數信息的結構體指針FIXED_INFO * FixedInfo;/ 保存獲取到的本地計算機網絡參數信息結構體鏈表的長度ULONG ulOutBufLen;/ 調用GetNetwor

19、kParams()函數的返回值DWORD dwRetVal;/ 保存所有DNS服務器的IP地址列表IP_ADDR_STRING * pIPAddr;3獲取本地網絡參數信息需要兩次調用GetNetworkParams()函數。第1次調用可以獲取返回數據的大小,第2次調用使用前面獲取到的數據大小作為參數,獲取實際的FIXED_INFO結構體內容,具體代碼如下:/ 為FixedInfo結構體分配內存空間FixedInfo = (FIXED_INFO *) GlobalAlloc( GPTR, sizeof( FIXED_INFO ) );/ 初始化ulOutBufLen變量值ulOutBufLen

20、= sizeof( FIXED_INFO );/ 第次調用GetNetworkParams()函數,獲取返回結果的大小到ulOutBufLen中if( ERROR_BUFFER_OVERFLOW = GetNetworkParams( FixedInfo, &ulOutBufLen ) ) GlobalFree( FixedInfo );FixedInfo = (FIXED_INFO *) GlobalAlloc( GPTR, ulOutBufLen );/ 第次調用GetNetworkParams()函數,以前面獲取的ulOutBufLen作為參數,if ( dwRetVal = GetNe

21、tworkParams( FixedInfo, &ulOutBufLen ) != ERROR_SUCCESS) printf( 調用GetNetworkParams()函數失敗。返回值: %08xn, dwRetVal );4顯示本地網絡參數信息else printf( 主機名: %sn, FixedInfo-HostName );printf( 域名: %sn, FixedInfo-DomainName ); printf(n=網絡信息=n); / 生成節點類型字符串 char* NodeType; 4顯示本地網絡參數信息 switch(FixedInfo-NodeType) case B

22、ROADCAST_NODETYPE: NodeType=Broadcase Node; break; case PEER_TO_PEER_NODETYPE: NodeType=Peer to Peer Node; break; case MIXED_NODETYPE: NodeType=Mixed Node; break; case HYBRID_NODETYPE: NodeType=Hybrid Node; break; default: NodeType=Unknown Node; break; 4顯示本地網絡參數信息printf(節點類型.:%d - %sn, FixedInfo-Nod

23、eType, NodeType); printf(是否啟用路由功能.:%sn, (FixedInfo-EnableRouting != 0) ? 是 : 否); printf(是否啟用ARP代理功能.:%sn, (FixedInfo-EnableProxy != 0) ? 是 : 否); printf(是否啟用DNS服務器.:%sn, (FixedInfo-EnableDns != 0) ? 是 : 否); printf( nDNS服務器列表:n );printf( %sn, FixedInfo - DnsServerList.IpAddress.String );pIPAddr = Fixe

24、dInfo - DnsServerList.Next; while ( pIPAddr ) printf( t%sn, pIPAddr -IpAddress.String );pIPAddr = pIPAddr -Next;IP_ADDR_STRING結構體typedef struct _IP_ADDR_STRING struct _IP_ADDR_STRING* Next; IP_ADDRESS_STRING IpAddress; IP_MASK_STRING IpMask; DWORD Context; IP_ADDR_STRING, *PIP_ADDR_STRING;5暫停程序,等待用戶

25、響應在顯示本地網絡信息后,程序處于暫停狀態,等待用戶響應,代碼如下:printf(nn);system(pause); return 0;6.1.5 獲取本地計算機網絡接口的基本信息1獲取本地計算機的網絡接口數量2獲取本地計算機網絡接口的基本信息1獲取本地計算機的網絡接口數量可以通過調用GetNumberOfInterfaces()函數獲取本地計算機的網絡接口數量,語法如下:DWORD GetNumberOfInterfaces( _out PDWORD pdwNumIf);參數pdwNumIf用于接受獲取到的本地計算機網絡接口數量。函數的返回值為DWORD類型,如果調用成功,則返回NO_ER

26、ROR;否則表示調用失敗。【例6.3】#include stdafx.h#include #include #include #pragma comment(lib, IPHLPAPI.lib)int _tmain(int argc, _TCHAR* argv)/ 用于獲取接口數量DWORD dwNumIf;/ 返回值DWORD dwRetVal;if(dwRetVal = GetNumberOfInterfaces(&dwNumIf) = NO_ERROR)printf(本地網絡接口數量為: %d, dwNumIf);elseprintf(調用GetNumberOfInterfaces()函

27、數時出現錯誤。);printf(nn);system(pause); return 0;2獲取本地計算機網絡接口的基本信息可以通過調用GetInterfaceInfo()函數獲取本地計算機網絡接口的基本信息,語法如下:DWORD GetInterfaceInfo( _out PIP_INTERFACE_INFO pIfTable, _inout PULONG dwOutBufLen);PIP_INTERFACE_INFOtypedef struct _IP_INTERFACE_INFO LONG NumAdapters; IP_ADAPTER_INDEX_MAP Adapter1;IP_INT

28、ERFACE_INFO, *PIP_INTERFACE_INFO;typedef struct _IP_ADAPTER_INDEX_MAP ULONG Index; WCHAR NameMAX_ADAPTER_NAME;IP_ADAPTER_INDEX_MAP, *PIP_ADAPTER_INDEX_MAP;【例6.4】首先創建一個Win32控制臺應用程序,項目名稱為GetInterfaceInfo,其主文件名為GetInterfaceInfo.cpp。頭文件和庫文件#include stdafx.h#include #include #include #pragma comment(lib,

29、 IPHLPAPI.lib)分配和釋放內存空間/ 分配內存空間#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x) / 釋放內存空間#define FREE(x) HeapFree(GetProcessHeap(), 0, (x)在主函數_tmain()中聲明變量/ 保存網絡接口信息的結構體指針PIP_INTERFACE_INFO pInfo;/ 保存獲取數據的長度ULONG ulOutBufLen = 0;/ 返回結果DWORD dwRetVal = 0;/ _tmain()函數的返回結果int iReturn = 1;調用GetInter

30、faceInfo()函數/ 第次調用GetInterfaceInfo,獲取數據大小,保存到ulOutBufLen變量中dwRetVal = GetInterfaceInfo(NULL, &ulOutBufLen);if (dwRetVal = ERROR_INSUFFICIENT_BUFFER) pInfo = (IP_INTERFACE_INFO *) MALLOC(ulOutBufLen); if (pInfo = NULL) printf(無法分配GetInterfaceInfo函數需要的內存空間。n); return 1; 調用GetInterfaceInfo()函數/ 第次調用Get

31、InterfaceInfo函數,獲取需要的實際數據dwRetVal = GetInterfaceInfo(pInfo, &ulOutBufLen);if (dwRetVal = NO_ERROR) printf(網絡適配器數量: %ldnn, pInfo-NumAdapters); for (int i = 0; i NumAdapters; i+) printf(網絡適配器索引%d: %ldn, i, pInfo-Adapteri.Index); printf(網絡適配器名稱%d: %wsnn, i, pInfo-Adapteri.Name); iReturn = 0; else if (d

32、wRetVal = ERROR_NO_DATA) printf(本地計算機上沒有支持IPv4的網絡適配器。n); iReturn = 0; else printf(GetInterfaceInfo調用失敗: %dn, dwRetVal); iReturn = 1;等待用戶響應/ 釋放內存空間FREE(pInfo);/ 按任意鍵繼續system(pause);return (iReturn);6.1.6 獲取本地計算機IP地址表可以通過調用GetIpAddrTable()函數獲取本地計算機網絡接口和IP地址的映射表,語法如下:DWORD GetIpAddrTable( _out PMIB_IPA

33、DDRTABLE pIpAddrTable, _inout PULONG pdwSize, _in BOOL bOrder);PMIB_IPADDRTABLE結構體typedef struct _MIB_IPADDRROW DWORD dwAddr; DWORD dwIndex; DWORD dwMask; DWORD dwBCastAddr; DWORD dwReasmSize; unsigned short unused1; unsigned short wType;MIB_IPADDRROW, *PMIB_IPADDRROW;【例6.5】下面介紹使用IP Helper API獲取本地IP

34、地址表的具體代碼。首先創建一個Win32控制臺應用程序,項目名稱為GetIpAddrTable,其主文件名為GetIpAddrTable.cpp。頭文件和庫文件#include stdafx.h#include #include #include #pragma comment(lib, iphlpapi.lib)#pragma comment(lib, ws2_32.lib)分配和釋放內存空間/ 分配內存空間#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x) / 釋放內存空間#define FREE(x) HeapFree(GetProc

35、essHeap(), 0, (x)在主函數_tmain()中聲明變量/ 網絡接口與IP地址映射表PMIB_IPADDRTABLE pIPAddrTable;/ 獲取數據的大小DWORD dwSize = 0;/ 調用GetIPAddrTable()函數的返回值DWORD dwRetVal = 0;/ 保存IP地址的結構體IN_ADDR IPAddr;/ 用于獲取錯誤信息LPVOID lpMsgBuf;調用GetIpAddrTable()函數 / 分配內存空間 pIPAddrTable = (MIB_IPADDRTABLE *) MALLOC(sizeof (MIB_IPADDRTABLE);

36、/ 第次調用GetIpAddrTable()函數,獲取數據的大小到dwSize if (pIPAddrTable) if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) = ERROR_INSUFFICIENT_BUFFER) FREE(pIPAddrTable); pIPAddrTable = (MIB_IPADDRTABLE *) MALLOC(dwSize); if (pIPAddrTable = NULL) printf(GetIpAddrTable()函數內存分配失敗n); exit(1); 調用GetIpAddrTable()函數 / 第次調用G

37、etIpAddrTable()函數,獲取實際數據 if ( (dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 ) != NO_ERROR ) printf(GetIpAddrTable()調用失敗: %dn, dwRetVal); if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBL

38、ANG_DEFAULT), / Default language (LPTSTR) & lpMsgBuf, 0, NULL) printf(t錯誤信息: %s, lpMsgBuf); LocalFree(lpMsgBuf); exit(1); 顯示pIPAddrTable結構體 printf(t記錄數量: %ldn, pIPAddrTable-dwNumEntries); for (i=0; i dwNumEntries; i+) printf(nt接口序號%d:t%ldn, i, pIPAddrTable-tablei.dwIndex); IPAddr.S_un.S_addr = (u_lo

39、ng) pIPAddrTable-tablei.dwAddr; printf(tIP地址%d: t%sn, i, inet_ntoa(IPAddr) ); IPAddr.S_un.S_addr = (u_long) pIPAddrTable-tablei.dwMask; printf(t子網掩碼%d: t%sn, i, inet_ntoa(IPAddr) ); IPAddr.S_un.S_addr = (u_long) pIPAddrTable-tablei.dwBCastAddr; printf(t廣播地址%d: t%s (%ld%)n, i, inet_ntoa(IPAddr), pIPA

40、ddrTable-tablei.dwBCastAddr); printf(t重組報文最大數量%d:t%ldn, i, pIPAddrTable-tablei.dwReasmSize); printf(t類型和狀態%d:, i); if (pIPAddrTable-tablei.wType & MIB_IPADDR_PRIMARY) printf(t主IP地址); if (pIPAddrTable-tablei.wType & MIB_IPADDR_DYNAMIC) printf(t動態IP地址); if (pIPAddrTable-tablei.wType & MIB_IPADDR_DISCO

41、NNECTED) printf(t斷開連接的接口對應的IP地址); if (pIPAddrTable-tablei.wType & MIB_IPADDR_DELETED) printf(t刪除的IP地址); if (pIPAddrTable-tablei.wType & MIB_IPADDR_TRANSIENT) printf(t臨時地址); printf(n); 釋放資源,等待用戶響應/ 釋放內存空間if (pIPAddrTable) FREE(pIPAddrTable); pIPAddrTable = NULL;printf(n);system(pause);return 0;例6.5的運

42、行界面6.1.7 添加和刪除IP地址一個網絡適配器上可以定義多個IP地址。調用AddIPAddress()函數可以向指定的網絡適配器中添加IP地址,調用DeleteIPAddress()函數可以刪除指定的IP地址。AddIPAddress()函數DWORD AddIPAddress( _in IPAddr Address, _in IPMask IpMask, _in DWORD IfIndex, _out PULONG NTEContext, _out PULONG NTEInstance);參數說明如下:Address,指定要添加的IP地址。IpMask,指定IP地址對應的子網掩碼。IfI

43、ndex,指定添加IP地址的網絡適配器的索引。NTEContext,如果調用AddIPAddress()函數成功,則指向一個與這個IP地址關聯的網絡表接口。之后可以在DeleteIPAddress()函數中使用該接口來刪除指定的IP地址。NTEInstance,如果調用成功,則指向與該IP地址相關聯的網絡表接口實例。DeleteIPAddress()DWORD DeleteIPAddress( _in ULONG NTEContext);參數UTEContext是前面調用AddIPAddress()函數時返回的與IP地址相關聯的網絡表接口。也就是說,DeleteIPAddress()函數只能刪

44、除使用AddIPAddress()函數添加的臨時IP地址。【例6.6】使用IP Helper API獲取添加和刪除IP地址。引用頭文件庫文件,代碼如下:#include stdafx.h#include #include #include #include #pragma comment(lib, iphlpapi.lib)#pragma comment(lib, ws2_32.lib)分配和釋放內存空間/ 分配內存空間#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x) / 釋放內存空間#define FREE(x) HeapFree(Ge

45、tProcessHeap(), 0, (x)在主函數_tmain()中聲明變量/ 調用GetIpAddrTable()函數中使用的結構體PMIB_IPADDRTABLE pIPAddrTable;/ 獲取數據的大小DWORD dwSize = 0;/ 調用GetIPAddrTable()函數的返回值DWORD dwRetVal = 0;/ 保存IP地址的結構體IN_ADDR IPAddr;/ IP地址對應的接口索引DWORD ifIndex;/ 要添加的IP地址和子網掩碼UINT iaIPAddress;UINT iaIPMask;/ 用于處理添加IP地址的返回變量ULONG NTEConte

46、xt = 0;ULONG NTEInstance = 0;/ 用于輸出錯誤信息的變量LPVOID lpMsgBuf;驗證IP地址格式 / 驗證命令行參數的數量 if (argc != 3) printf(usage: %s IPAddress SubnetMaskn, argv0); exit(1); / 驗證命令行參數中IP地址的格式是否正確 iaIPAddress = inet_addr(argv1); if (iaIPAddress = INADDR_NONE) printf(usage: %s IPAddress SubnetMaskn, argv0); exit(1); / 驗證命令

47、行參數中子網掩碼的格式是否正確 iaIPMask = inet_addr(argv2); if (iaIPMask = INADDR_NONE) printf(usage: %s IPAddress SubnetMaskn, argv0); exit(1); 調用GetIpAddrTable()函數 / 分配內存空間 pIPAddrTable = (MIB_IPADDRTABLE *) MALLOC(sizeof (MIB_IPADDRTABLE); if (pIPAddrTable = NULL) printf(Error allocating memory needed to call G

48、etIpAddrTablen); exit (1); else dwSize = 0;/ 第次調用GetIpAddrTable()函數,獲取數據的大小到dwSize if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) = ERROR_INSUFFICIENT_BUFFER) FREE(pIPAddrTable); pIPAddrTable = (MIB_IPADDRTABLE *) MALLOC(dwSize); if (pIPAddrTable = NULL) printf(Memory allocation failed for GetIpAddrTa

49、blen); exit(1); 調用GetIpAddrTable()函數 / 調用GetIpAddrTable()函數,獲取地址表數據 if (dwRetVal = GetIpAddrTable(pIPAddrTable, &dwSize, 0) = NO_ERROR) / 獲取當前IP地址對應的接口索引,在后面添加IP地址時使用 ifIndex = pIPAddrTable-table0.dwIndex; printf(ntInterface Index:t%ldn, ifIndex); IPAddr.S_un.S_addr = (u_long) pIPAddrTable-table0.dw

50、Addr; printf(tIP Address: t%s (%lu%)n, inet_ntoa(IPAddr), pIPAddrTable-table0.dwAddr); IPAddr.S_un.S_addr = (u_long) pIPAddrTable-table0.dwMask; printf(tSubnet Mask: t%s (%lu%)n, inet_ntoa(IPAddr), pIPAddrTable-table0.dwMask); IPAddr.S_un.S_addr = (u_long) pIPAddrTable-table0.dwBCastAddr; printf(tBr

51、oadCast Address:t%s (%lu%)n, inet_ntoa(IPAddr), pIPAddrTable-table0.dwBCastAddr); printf(tReassembly size: t%lunn, pIPAddrTable-table0.dwReasmSize); else printf(調用GetIpAddrTable失敗: %d.n, dwRetVal); if (pIPAddrTable) FREE(pIPAddrTable); exit(1); 釋放資源 if (pIPAddrTable) FREE(pIPAddrTable); pIPAddrTable

52、 = NULL; 添加IP地址的代碼/ 添加IP地址 if (dwRetVal = AddIPAddress(iaIPAddress, iaIPMask, ifIndex, &NTEContext, &NTEInstance) = NO_ERROR) printf(tIPv4地址成功添加.n, argv1); else printf(調用AddIPAddress()函數失敗: %dn, dwRetVal); if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE

53、_IGNORE_INSERTS, NULL, dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), / Default language (LPTSTR) & lpMsgBuf, 0, NULL) printf(錯誤: %s, lpMsgBuf); LocalFree(lpMsgBuf); exit(1); 刪除IP地址的代碼/ 刪除剛剛添加的IP地址 if (dwRetVal = DeleteIPAddress(NTEContext) = NO_ERROR) printf(tIPv4地址%s 被成功刪除.n, argv1); else pr

54、intf(t調用DeleteIPAddress()函數失敗: %dn, dwRetVal); exit(1); 配置命令行參數因為程序中使用了命令行參數,所以在調試和運行程序之前需要配置命令行參數。在系統菜單中選擇“項目”/“AddIPAddress屬性”,打開項目屬性對話框。6.2 掃描子網中的地址6.2.1 計算指定子網內包含的所有IP地址6.2.2 實現ping的功能6.2.3 掃描子網6.2.1 計算指定子網內包含的所有IP地址要掃描一個子網,首先需要計算該子網中包含的所有IP地址。可以根據子網中的一個IP地址和子網掩碼計算出該子網的網絡地址(該子網中最小的IP地址)和廣播地址(該子網

55、中最大的IP地址)。將IP地址與子網掩碼執行按位與運算,即可計算出子網的子網地址,公式如下: = & 將子網掩碼執行按位非操作,然后再將結果與IP地址執行按位或運算,即可計算出子網的廣播地址,公式如下: = | 【例6.7】下面通過一個實例程序來演示計算指定子網內包含所有IP地址的方法。實例是一個控制臺項目,項目名稱為CalculateSubnet,其主文件名為CalculateSubnet.cpp。運行界面如下:1聲明頭文件在CalculateSubnet.cpp中需要聲明程序中使用的頭文件,并引用Ws2_32.lib,代碼如下:#include stdafx.h#include Winso

56、ck2.h#pragma comment(lib, Ws2_32.lib)ws2_32.lib是Windows Sockets應用程序接口,用于支持Internet和網絡應用程序。2判斷命令行參數的數量int _tmain(int argc, _TCHAR* argv)if(argc != 3)printf(Usage: CalculateSubnet netaddr netmaskrnExample: CalculateSubnet );return 1;_tmain()函數有兩個參數,argc表示命令行參數的數量,argv數組表示命令行參數

57、的具體內容。可執行程序本身是第1個參數,因此在本例中如果命令行參數正確,則參數argc的值應該等于3。3判斷IP地址是否合法判斷IP地址是否合法的標準如下:字符串中必須包含3個逗號(.)。被逗號分隔的4個字符串的長度必須小于或等于3。被逗號分隔的4個字符串必須可以轉換成整數。被逗號分隔的4個字符串轉換成的整數不得大于255。程序中使用自定義函數IsValidIP()函數判斷IP地址是否合法。4計算網絡地址和廣播地址計算子網網絡地址和廣播地址的代碼如下:printf(netaddr: %sn, argv1);printf(netmask: %sn, argv2);unsigned long ln

58、etaddr = ntohl(inet_addr(argv1);unsigned long lnetmask = ntohl(inet_addr(argv2);unsigned long l_first_netaddr = lnetaddr & lnetmask;unsigned long l_broadcast = lnetaddr | lnetmask;5顯示IP地址的數量和列表/ 計算子網中包含有效IP地址的數量long num = l_broadcast - l_first_netaddr - 1;printf(Number of valid IPs: %dnn, num); / 顯示

59、子網中的IP地址printf(IPs in subnet: n=n);for(unsigned long i=l_first_netaddr+1; ii_type = ICMP_ECHO;/ 將類型設置為ICMP響應包 icmp_hdr-i_code = 0;/ 將編碼設置為 / 將編號設置為當前線程的編號 icmp_hdr-i_id = (USHORT)GetCurrentThreadId(); icmp_hdr-i_cksum = 0;/ 將校驗和設置為 icmp_hdr-i_seq = 0;/ 將序列號設置為 datapart = icmp_data + sizeof(IcmpHeade

60、r);/ 定義到數據部分 / 在數據部分隨便填充一些數據 memset(datapart,E, datasize - sizeof(IcmpHeader);3解析ICMP回應包decode_resp()函數的參數說明如下:buf,接收數據包的緩沖區。bytes,接收到數據的長度。from,發送數據包的IP地址。tid,用于接收ICMP數據包的線程ID。程序的運行過程如下:(1)計算IP數據包頭的長度。(2)如果指定的緩沖區長度小于IP包頭加上最小的ICMP包長度,則說明它包含的ICMP數據不完整或者不包含ICMP數據,函數返回-1。(3)定位到ICMP包頭的起始位置。(4)判斷ICMP包的類型

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論