获取网络信息

实验五 获取网络信息

一、 实验目的

  1. 掌握主要的Winsock信息查询函数的功能和用法。
  2. 掌握IP Helper API提供的主要功能和编程方法步骤。
    二、实验内容
    1.Winsock信息查询函数:
    (1)根据域名获取远程计算机的IP地址;
    (2)获取本机的IP地址。
    2.使用IP Helper API获取本机的网络配置信息:
    (1)获取本机的MAC地址、IP地址、子网掩码等网络适配器信息。
    (2)获取本地主机名、域名和DNS服务器信息。
    (3)获取本地计算机IP地址表。
    三、实验原理

在这里插入图片描述

(1) gethostname()
主要功能:返回本地主机的标准主机名。
主要参数:一个缓冲区指针 *name和一个int类型的变量namelen,表示缓冲区的长度。
如果没有错误发生,gethostname()返回0。否则它返回SOCKET_ERROR。
数据结构:字符类型的数组。
(2) gethostbyaddr()
主要功能:返回对应于给定地址的主机信息。
主要参数:add指向网络字节顺序地址的指针、lenth 地址长度和type 地址类型,因为是针对ipv4 所以这边默认为 PE_INET。
如果没有错误发生,gethostbyaddr()返回如上所述的一个指向hostent结构的指针,否则,返回一个空指针
数据结构:需要定义一个名为hostent的结构体,用于函数返回,该结构是一个list列表,用于保存主机地址,顺序存储
(3) gethostbyname() 
主要功能:通过主机名字获取主机名字和地址等信息 
主要参数:const char FAR * addr 一个指向主机名的指针。
返回值:如果没有错误发生,gethostbyname()返回一个指向hostent结构的指针,否则,返回一个空指针
数据结构:需要定义一个名为hostent的结构体,用于函数返回,该结构是一个list列表,用于保存主机地址,顺序存储
(4) getprotobyname() 
主要功能:通过协议名获取协议名和协议号等信息 
主要参数:一个指向协议名的指针
返回值: 如果没有错误发生,getprotobyname()返回如上所述的一个指向protoent结构的指针,否则,返回一个空指针
数据结构:需要定义一个名为protoent的结构体,用于函数返回,该结构是一个list列表,用于保存协议信息
(5) getprotobynumber() 
主要功能 返回对应于给定协议号的相关协议信息。
主要参数:一个指向协议名的指针。
返回值: 如果没有错误发生,getprotobynumber()返回如上所述的一个指向protoent结构的指针,否则,返回一个空指针。
数据结构:需要定义一个名为protoent的结构体,用于函数返回,该结构是一个list列表,用于保存协议信息。(同4)
(6) getservbyname() 
主要功能:返回对应于给定服务名和协议名的相关服务信息
主要参数 一个指向服务名的指针和一个可选的指向协议名的指针
返回值 如果没有错误发生,getservbyname()返回如上所述的一个指向servent结构的指针,否则,返回一个空指针
数据结构:需要定义一个名为servent的结构体,用于函数返回,该结构是一个list列表,用于保存服务器信息。
(7) getservbyport() 
主要功能:返回对应于给定端口号和协议名的相关服务信息。
主要参数:给定的端口号,以网络字节顺序排列和指向协议名的指针(可选)
返回值 如果没有错误发生,getservbyport()返回如上所述的一个指向servent结构的指针,否则,返回一个空指针
数据结构 需要定义一个名为servent的结构体,用于函数返回,该结构是一个list列表,用于保存服务器信息,同(6)
四、实验步骤
(1)根据域名获取远程计算机的IP地址
1.首先调用库函数
在这里插入图片描述

2.在调用gethostbyname获取ip地址时,必须先调用WSASTART进行初始化,否则会报一个WSANOTINTIALISED错误

在这里插入图片描述

  1. 调用gethostbyname()获取指定主机名的主机信息,并对错误信息进行分析,若出现错误,将错误打印出来;若正常运行,将主机名对应的官方名称、别名、IP地址类型、IP地址长度、地址列表都打印出来。本次实验笔者对www.baidu.com进行了解析,实验结果如下。
    在这里插入图片描述
    在这里插入图片描述

(2)获取本机的IP地址
该实验和(1)实验实现过程基本相似,区别是获取本地的ip地址用到的函数是gethostname函数
在这里插入图片描述

最后获得的结果是
在这里插入图片描述

(3)获取本机的MAC地址、IP地址、子网掩码等网络适配器信息。

  1. 是前几个实验不同的是,在调用该函数进行分析时,需要声明头文件
    在这里插入图片描述

  2. 之后在声明完变量后,创建一个链表pAdapterInfo,并为其分配空间,用于存储获取到的信息。
    在这里插入图片描述

  3. 两次调用getAdapterInfo函数,第一次调用获取返回数据大小, 第二调用需要将第一次调用获取的数据大小作为参数,获取真正的结构体信息。
    在这里插入图片描述

  4. 成功获取信息后,将链表中的信息打印出来,下面是笔者电脑上的信息。释放资源。
    在这里插入图片描述

(4)获取本地主机名、域名和DNS服务器信息。
该实验的实现方法和(3)类似,都需要两次调用函数,本次需要调用GetNetworkparams,第二次将第一次的返回结果作为参数,来获取真实的结构体内容。获取结果存放在链表中;最后,打印完成后,将资源释放。
在这里插入图片描述
在这里插入图片描述

最后获取到本机结果是:
在这里插入图片描述

(5)获取本地计算机IP地址表。
在获取本地计算机ip地址表时,需要调用的函数是:GetIpAddrTable(),也是需要进行两次调用,第一次结果作为第二次参数进行调用,获取实际数据;然后将结构体的数据打印出来,需要将DWORD类型的IP地址转换为字符串。最后释放资源。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

最后实验结果是:
在这里插入图片描述

五、实验小结
附:程序源代码
(1)根据域名获取远程计算机的IP地址;

#include "stdafx.h"

#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <windows.h>
#pragma comment(lib, "ws2_32.lib")

int main(int argc, char **argv)
{

    //-----------------------------------------
    // Declare and initialize variables
    WSADATA wsaData;
    int iResult;

    DWORD dwError;
    int i = 0;

    struct hostent *remoteHost;
    char *host_name;
    struct in_addr addr;

    char **pAlias;

    // Validate the parameters
    if (argc != 2) {
        printf("usage: GetHostIP hostname\n");
        return 1;
    }
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed: %d\n", iResult);
        return 1;
    }
    
    host_name = argv[1];
	

    printf("Calling gethostbyname with %s\n", host_name);
    remoteHost = gethostbyname(host_name);
    
    if (remoteHost == NULL) {
        dwError = WSAGetLastError();
        if (dwError != 0) {
            if (dwError == WSAHOST_NOT_FOUND) {
                printf("Host not found\n");
                return 1;
            } else if (dwError == WSANO_DATA) {
                printf("No data record found\n");
                return 1;
            } else {
                printf("Function failed with error: %ld\n", dwError);
                return 1;
            }
        }
    } else {
        printf("Function returned:\n");
        printf("\t Official name: %s\n", remoteHost->h_name);
        for (pAlias = remoteHost->h_aliases; *pAlias != 0; pAlias++) {
            printf("\tAlternate name #%d: %s\n", ++i, *pAlias);
        }
        printf("\tAddress type: ");
        switch (remoteHost->h_addrtype) {
        case AF_INET:
            printf("AF_INET\n");
            break;
        case AF_NETBIOS:
            printf("AF_NETBIOS\n");
            break;
        default:
            printf(" %d\n", remoteHost->h_addrtype);
            break;
        }
        printf("\tAddress length: %d\n", remoteHost->h_length);

        i = 0;
        if (remoteHost->h_addrtype == AF_INET)
        {
            while (remoteHost->h_addr_list[i] != 0) {
                addr.s_addr = *(u_long *) remoteHost->h_addr_list[i++];
                printf("\tIP Address #%d: %s\n", i, inet_ntoa(addr));
            }
        }
        else if (remoteHost->h_addrtype == AF_NETBIOS)
        {   
            printf("NETBIOS address was returned\n");
        }   
    }

	system("pause");
	WSACleanup();
    return 0;
}2)获取本机的IP地址。
#include "stdafx.h"

#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <windows.h>
#pragma comment(lib, "ws2_32.lib")


int main(int argc, char **argv)
{

    //-----------------------------------------
    // Declare and initialize variables
    WSADATA wsaData;
    int iResult;

    DWORD dwError;
    int i = 0;

    struct hostent *remoteHost;
    char host_name[256];
    struct in_addr addr;

    char **pAlias;

    // Validate the parameters
    if (argc != 1) {
        printf("usage: GetLocalIP \n");
        return 1;
    }
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed: %d\n", iResult);
        return 1;
    }
    
	iResult = gethostname( host_name, sizeof( host_name ));
	if (iResult !=0) {
		printf("gethostname failed: %d\n",iResult);
		return 1;
	}	

    printf("Calling gethostbyname with %s\n", host_name);
    remoteHost = gethostbyname(host_name);
    
    if (remoteHost == NULL) {
        dwError = WSAGetLastError();
        if (dwError != 0) {
            if (dwError == WSAHOST_NOT_FOUND) {
                printf("Host not found\n");
                return 1;
            } else if (dwError == WSANO_DATA) {
                printf("No data record found\n");
                return 1;
            } else {
                printf("Function failed with error: %ld\n", dwError);
                return 1;
            }
        }
    } else {
        printf("Function returned:\n");
        printf("\tOfficial name: %s\n", remoteHost->h_name);

        for (pAlias = remoteHost->h_aliases; *pAlias != 0; pAlias++) {
            printf("\tAlternate name #%d: %s\n", ++i, *pAlias);
        }

        printf("\tAddress type: ");
        switch (remoteHost->h_addrtype) {
        case AF_INET:
            printf("AF_INET\n");
            break;
        case AF_NETBIOS:
            printf("AF_NETBIOS\n");
            break;
        default:
            printf(" %d\n", remoteHost->h_addrtype);
            break;
        }

        printf("\tAddress length: %d\n", remoteHost->h_length);

        i = 0;
        if (remoteHost->h_addrtype == AF_INET)
        {
            while (remoteHost->h_addr_list[i] != 0) {
                addr.s_addr = *(u_long *) remoteHost->h_addr_list[i++];
                printf("\tIP Address #%d: %s\n", i, inet_ntoa(addr));
            }
        }
        else if (remoteHost->h_addrtype == AF_NETBIOS)
        {   
            printf("NETBIOS address was returned\n");
        }   
    }

    return 0;
}3)获取本机的MAC地址、IP地址、子网掩码等网络适配器信息。

#include "stdafx.h"
#pragma comment(lib, "IPHLPAPI.lib") 
#include <winsock2.h> 
#include <iphlpapi.h> 
#include <stdio.h> 

int _tmain(int argc, _TCHAR* argv[])
{
	IP_ADAPTER_INFO *pAdapterInfo;
	ULONG  ulOutBufLen;
	DWORD dwRetVal;
	PIP_ADAPTER_INFO pAdapter;

	// 为pAdapterInfo分配空间
	pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));
	ulOutBufLen = sizeof(IP_ADAPTER_INFO);
	// 第1次调用GetAdaptersInfo(),获取返回结果的大小到ulOutBufLen中
	if(GetAdaptersInfo(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! %d\n", dwRetVal);
	}
	// 从pAdapterInfo 获取并显示本地网络信息
	pAdapter = pAdapterInfo;
	while(pAdapter)
	{
		printf("网络适配器名: \t\t%s\n", pAdapter->AdapterName);
		printf("网络适配器描述: \t%s\n\n", pAdapter->Description);
		printf("MAC地址: \t\t");
		for(int i=0; i<pAdapter->AddressLength; i++)
		{
			if(i==(pAdapter->AddressLength -1))
				printf("%.2X\n", (int)pAdapter->Address[i]);
			else
				printf("%.2X-", (int)pAdapter->Address[i]);
		}
		printf("IP地址: \t\t%s\n", pAdapter->IpAddressList.IpAddress.String);
		printf("子网掩码: \t\t%s\n", pAdapter->IpAddressList.IpMask.String);
		printf("网关: \t\t\t%s\n", pAdapter->GatewayList.IpAddress.String);
		printf("********************************************************************\n");
		if(pAdapter->DhcpEnabled)
		{
			printf("启用DHCP: \t\t是\n");
			printf("DHCP服务器: \t\t%s\n", pAdapter->DhcpServer.IpAddress.String);
		}
		else
		{
			printf("启用DHCP: \t\t否\n");
		}

		// 处理下一人网络适配器
		pAdapter = pAdapter->Next;
	}
	// 释放资源
	if(pAdapterInfo)
		free(pAdapterInfo);
	
	printf("\n\n");
	system("pause");   
	return 0;
}4)获取本地主机名、域名和DNS服务器信息。
// GetNetworkParams.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include <winsock2.h> 
#include <iphlpapi.h> 
#include <stdio.h>

#pragma comment(lib, "IPHLPAPI.lib") 

int _tmain(int argc, _TCHAR* argv[])
{		
	FIXED_INFO * FixedInfo;
	ULONG    ulOutBufLen;
    DWORD    dwRetVal;
    IP_ADDR_STRING * pIPAddr;

	// 为FixedInfo结构体分配内存空间
	FixedInfo = (FIXED_INFO *) GlobalAlloc( GPTR, sizeof( FIXED_INFO ) );
	// 初始化ulOutBufLen变量值
    ulOutBufLen = sizeof( FIXED_INFO );
    
	// 第1次调用GetNetworkParams()函数,获取返回结果的大小到ulOutBufLen中
    if( ERROR_BUFFER_OVERFLOW == GetNetworkParams( FixedInfo, &ulOutBufLen ) ) {
        GlobalFree( FixedInfo );
		FixedInfo = (FIXED_INFO *) GlobalAlloc( GPTR, ulOutBufLen );
	}

	// 第2次调用GetNetworkParams()函数,以前面获取的ulOutBufLen作为参数,
    if ( dwRetVal = GetNetworkParams( FixedInfo, &ulOutBufLen ) != ERROR_SUCCESS) {
        printf( "调用GetNetworkParams()函数失败。返回值: %08x\n", dwRetVal );
    }
    else {
		printf( "主机名: %s\n", FixedInfo->HostName );
		printf( "域名: %s\n", FixedInfo->DomainName );
		
		 printf("\n==========网络信息==========\n"); 

		 // 生成节点类型字符串
     	 char* NodeType; 
		 switch(FixedInfo->NodeType) 
         { 
             case BROADCAST_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; 
         } 


		printf("节点类型...................:%d - %s\n", FixedInfo->NodeType, NodeType); 
        printf("是否启用路由功能...........:%s\n", (FixedInfo->EnableRouting != 0) ? "是" : "否"); 
        printf("是否启用ARP代理功能........:%s\n", (FixedInfo->EnableProxy != 0) ? "是" : "否"); 
        printf("是否启用DNS服务器..........:%s\n", (FixedInfo->EnableDns != 0) ? "是" : "否"); 

		printf( "\nDNS服务器列表:\n" );
		printf( "%s\n", FixedInfo->DnsServerList.IpAddress.String );

		pIPAddr = FixedInfo->DnsServerList.Next;
        while ( pIPAddr ) {
			printf( "\t%s\n", pIPAddr->IpAddress.String );
			pIPAddr = pIPAddr->Next;
        }
    }

	printf("\n\n");
	system("pause");   
	return 0;
}5)获取本地计算机IP地址表。
// GetIpAddrTable.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <winsock2.h>
#include <iphlpapi.h>
#include <stdio.h>

#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")

#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))

int _tmain(int argc, _TCHAR* argv[])
{
	    int i;
    
    PMIB_IPADDRTABLE pIPAddrTable;
    DWORD dwSize = 0;
    DWORD dwRetVal = 0;
    IN_ADDR IPAddr;
    LPVOID lpMsgBuf;
    // 分配内存空间
    pIPAddrTable = (MIB_IPADDRTABLE *) MALLOC(sizeof (MIB_IPADDRTABLE));
    // 第1次调用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);
        }
    }
    // 第2次调用GetIpAddrTable()函数,获取实际数据
    if ( (dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 )) != NO_ERROR ) { 
		printf("GetIpAddrTable()调用失败: %d\n", dwRetVal);
        if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),     
                          (LPTSTR) & lpMsgBuf, 0, NULL)) {
            printf("\t错误信息: %s", lpMsgBuf);
            LocalFree(lpMsgBuf);
        }
        exit(1);
    }

    printf("\t记录数量: %ld\n", pIPAddrTable->dwNumEntries);
    for (i=0; i < (int) pIPAddrTable->dwNumEntries; i++) {
        printf("\n\t接口序号[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwIndex);
        IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr;
        printf("\tIP地址[%d]:     \t%s\n", i, inet_ntoa(IPAddr) );
        IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwMask;
        printf("\t子网掩码[%d]:    \t%s\n", i, inet_ntoa(IPAddr) );
        IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwBCastAddr;
        printf("\t广播地址[%d]:      \t%s (%ld%)\n", i, inet_ntoa(IPAddr), pIPAddrTable->table[i].dwBCastAddr);
        printf("\t重组报文最大数量[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwReasmSize);
        printf("\t类型和状态[%d]:", i);
        if (pIPAddrTable->table[i].wType & MIB_IPADDR_PRIMARY)
            printf("\t主IP地址");
        if (pIPAddrTable->table[i].wType & MIB_IPADDR_DYNAMIC)
            printf("\t动态IP地址");
        if (pIPAddrTable->table[i].wType & MIB_IPADDR_DISCONNECTED)
            printf("\t断开连接的接口对应的IP地址");
        if (pIPAddrTable->table[i].wType & MIB_IPADDR_DELETED)
            printf("\t删除的IP地址");
        if (pIPAddrTable->table[i].wType & MIB_IPADDR_TRANSIENT)
            printf("\t临时地址");
        printf("\n");
    }

    if (pIPAddrTable) {
        FREE(pIPAddrTable);
        pIPAddrTable = NULL;
    }

	printf("\n");
	system("pause");
	return 0;
}
  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

半夏风情

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值