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

提交评论