使用API获取windows本地网卡信息

       GetAdaptersInfo和GetAdaptersAddresses函数可以获取到本地网卡的mac、IPV4地址、IPV6地址等各种信息。也可获取到有线网卡、环回网卡、隧道网、无线网卡等不同类型的网络信息。msdn推荐,在widows xp系统之后使用GetAdaptersAddresses函数。比如:使用GetAdaptersInfo() 获得本机网卡信息, 用在win8上有个问题, 蓝牙开启时读不到信息。

#include <string>
#include <WinSock2.h>
#include <windows.h>
#include <atlbase.h>
#include <Ws2tcpip.h>
#include <iphlpapi.h>  
#pragma  comment(lib,"Ws2_32.lib") //inet_ntop
#pragma  comment(lib,"Iphlpapi.lib") //GetAdaptersAddresses

int main(int argc, char * argv[])
{
	ULONG flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS;//包括 IPV4 ,IPV6 网关
	//flags |= GAA_FLAG_SKIP_DNS_SERVER; //不用返回DSN
	//flags |= GAA_FLAG_SKIP_MULTICAST; //不用返回多播地址
	//flags |= GAA_FLAG_SKIP_ANYCAST;//不用返回广播地址

	ULONG family = AF_UNSPEC;//返回包括 IPV4 和 IPV6 地址
	PIP_ADAPTER_ADDRESSES pAddresses = NULL;
	ULONG outBufLen = 0;
	DWORD dwRetVal = 0;
	PIP_ADAPTER_ADDRESSES pCurAddresses = NULL;
	PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;
	PIP_ADAPTER_ANYCAST_ADDRESS pAnycast = NULL;
	PIP_ADAPTER_MULTICAST_ADDRESS pMulticast = NULL;
	IP_ADAPTER_DNS_SERVER_ADDRESS *pDnServer = NULL;
	IP_ADAPTER_PREFIX *pPrefix = NULL;
	LPVOID lpMsgBuf = NULL;
	outBufLen = 15000;
	do
	{
		pAddresses = (IP_ADAPTER_ADDRESSES *)malloc(outBufLen);
		if (pAddresses == NULL)
			return 0;
		dwRetVal = GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);
		if (dwRetVal == ERROR_BUFFER_OVERFLOW)
		{
			free(pAddresses);
			pAddresses = NULL;
		}
		else
			break;
	} while (dwRetVal == ERROR_BUFFER_OVERFLOW);

	USES_CONVERSION;

	if (dwRetVal == NO_ERROR)
	{
		pCurAddresses = pAddresses;
		while (pCurAddresses)
		{
			printf("Adapter name:%s Description::%s Friendly name:%s\n", pCurAddresses->AdapterName, T2A(pCurAddresses->Description), T2A(pCurAddresses->FriendlyName));
			
			if (wcsstr(pCurAddresses->Description, _T("Bluetooth")) || wcsstr(pCurAddresses->Description, _T("bluetooth"))) //过滤蓝牙设备(一些蓝牙设备被当做以太网卡。)
			{
				pCurAddresses = pCurAddresses->Next;
				continue;
			}

			if (pCurAddresses->PhysicalAddressLength != 0)
			{
				char szMac[1024] = { 0 };
				sprintf_s(szMac, "%02X%02X%02X%02X%02X%02X", pCurAddresses->PhysicalAddress[0], pCurAddresses->PhysicalAddress[1],
					pCurAddresses->PhysicalAddress[2], pCurAddresses->PhysicalAddress[3], pCurAddresses->PhysicalAddress[4], pCurAddresses->PhysicalAddress[5]);
				printf("Adapter Mac:%s\n", szMac);
			}

			std::string strAapaterType = "";
			switch (pCurAddresses->IfType) //类型,列举了几种
			{
			case MIB_IF_TYPE_ETHERNET:
				strAapaterType = "以太网接口";
				break;
			case MIB_IF_TYPE_PPP:
				strAapaterType = "PPP接口";
				break;
			case MIB_IF_TYPE_LOOPBACK:
				strAapaterType = "软件回路接口";
				break;
			case MIB_IF_TYPE_SLIP:
				strAapaterType = "ATM网络接口";
				break;
			case IF_TYPE_IEEE80211:
				strAapaterType = "无线网络接口";
				break;
			}
			printf("网卡类型:%s\n", strAapaterType.c_str());
			pUnicast = pCurAddresses->FirstUnicastAddress;
			int nIndex = 1;
			while (pUnicast)//单播IP
			{
				char szIP[256] = { 0 };
				if (AF_INET == pUnicast->Address.lpSockaddr->sa_family)// IPV4 地址,使用 IPV4 转换
				{
					inet_ntop(PF_INET, &((sockaddr_in*)pUnicast->Address.lpSockaddr)->sin_addr, szIP, sizeof(szIP));
				}
				else if (AF_INET6 == pUnicast->Address.lpSockaddr->sa_family)// IPV6 地址,使用 IPV6 转换
				{
					inet_ntop(PF_INET6, &((sockaddr_in6*)pUnicast->Address.lpSockaddr)->sin6_addr, szIP, sizeof(szIP));
				}
				printf("单播 ip address index:%d ip:%s\n",nIndex, szIP);
				pUnicast = pUnicast->Next;
				nIndex++;
			}
			if (pCurAddresses->Dhcpv4Server.lpSockaddr)//IPV4 DHCP
			{
				char szDhcp[256] = { 0 };
				if (AF_INET == pCurAddresses->Dhcpv4Server.lpSockaddr->sa_family)
				{
					inet_ntop(PF_INET, &((sockaddr_in*)pCurAddresses->Dhcpv4Server.lpSockaddr)->sin_addr, szDhcp, sizeof(szDhcp));
				}
				else if (AF_INET6 == pCurAddresses->Dhcpv4Server.lpSockaddr->sa_family)
				{
					inet_ntop(PF_INET6, &((sockaddr_in6*)pCurAddresses->Dhcpv4Server.lpSockaddr)->sin6_addr, szDhcp, sizeof(szDhcp));
				}
				printf("Dhcpv4Server DHCP地址:%s\n", szDhcp);
			}
			nIndex = 1;
			pDnServer = pCurAddresses->FirstDnsServerAddress;
			while (pDnServer)//DNS
			{
				char szDNS[256] = { 0 };
				if (AF_INET == pDnServer->Address.lpSockaddr->sa_family)
				{
					inet_ntop(PF_INET, &((sockaddr_in*)pDnServer->Address.lpSockaddr)->sin_addr, szDNS, sizeof(szDNS));
				}
				else if (AF_INET6 == pDnServer->Address.lpSockaddr->sa_family)
				{
					inet_ntop(PF_INET6, &((sockaddr_in6*)pDnServer->Address.lpSockaddr)->sin6_addr, szDNS, sizeof(szDNS));
				}
				printf("DNS address index:%d address:%s\n", nIndex, szDNS);
				pDnServer = pDnServer->Next;
				nIndex++;
			}
			// MTU 
			printf("MTU:%u\n", pCurAddresses->Mtu);
			//发送速率
			printf("send speed:%lldbit/s\n", pCurAddresses->TransmitLinkSpeed);
			//接收速率
			printf("recv speed:%lldbit/s\n", pCurAddresses->ReceiveLinkSpeed);
			PIP_ADAPTER_GATEWAY_ADDRESS_LH pGateway = pCurAddresses->FirstGatewayAddress;
			nIndex = 1;
			while (pGateway)//网关
			{
				char szGateway[256] = { 0 };
				if (AF_INET == pGateway->Address.lpSockaddr->sa_family)
				{
					inet_ntop(PF_INET, &((sockaddr_in*)pGateway->Address.lpSockaddr)->sin_addr, szGateway, sizeof(szGateway));
				}
				else if (AF_INET6 == pGateway->Address.lpSockaddr->sa_family)
				{
					inet_ntop(PF_INET6, &((sockaddr_in6*)pGateway->Address.lpSockaddr)->sin6_addr, szGateway, sizeof(szGateway));
				}
				printf("gateway index:%d address:%s\n", nIndex, szGateway);
				pGateway = pGateway->Next;
				nIndex++;
			}
			if (pCurAddresses->Dhcpv6Server.lpSockaddr)//IPV6 DHCP
			{
				char szDhcp[256] = { 0 };
				if (AF_INET == pCurAddresses->Dhcpv6Server.lpSockaddr->sa_family)
				{
					inet_ntop(PF_INET, &((sockaddr_in*)pCurAddresses->Dhcpv6Server.lpSockaddr)->sin_addr, szDhcp, sizeof(szDhcp));
				}
				else if (AF_INET6 == pCurAddresses->Dhcpv6Server.lpSockaddr->sa_family)
				{
					inet_ntop(PF_INET6, &((sockaddr_in6*)pCurAddresses->Dhcpv6Server.lpSockaddr)->sin6_addr, szDhcp, sizeof(szDhcp));
				}
				printf("Dhcpv6Server DHCP地址:%s\n", szDhcp);
			}

			pCurAddresses = pCurAddresses->Next;
		}
	}
	else
	{
		printf("Call to GetAdaptersAddresses failed with error: %d\n", dwRetVal);
		if (dwRetVal == ERROR_NO_DATA)
		{
			printf("No addresses were found for the requested parameters\n");
		}
		else 
		{
			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("Error: %s\n", (char *)lpMsgBuf);
				LocalFree(lpMsgBuf);
				if (pAddresses)
				{
					free(pAddresses);
					pAddresses = NULL;
				}
				exit(1);
			}
		}
	}

	if (pAddresses)
	{
		free(pAddresses);
		pAddresses = NULL;
	}
    return 0;
}

注意:

1、error C2011: “sockaddr”:“struct”类型重定义错误,彻底解决windows.h和winsock2.h重定义。
解决办法:
方法1,#include <Windows.h>放在#include <WinSock2.h>后面。
方法2,在宏定义中加入以下这句话
       WIN32_LEAN_AND_MEAN

猜你喜欢

转载自blog.csdn.net/byxdaz/article/details/130537157