English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

C++Método de obtenção de endereços IP e MAC de todas as interfaces de rede do computador

Um computador pode não ter apenas uma placa de rede, mas cada placa de rede tem apenas um endereço MAC, e cada placa de rede pode configurar vários endereços IP; como no notebook comum, há duas tipos de placas de rede sem fio e placas de rede com fio (interface de rede); portanto, para obter informações de IP e MAC de todas as placas de rede do computador, é necessário obter sequencialmente cada placa de rede e, em seguida, obter suas informações, etc.; No windows sdk, a estrutura IP_ADAPTER_INFO é usada para armazenar informações de placa de rede, incluindo nome de placa de rede, descrição de placa de rede, endereço MAC de placa de rede, IP de placa de rede, etc., a descrição principal da estrutura é como follows:

typedef struct _IP_ADAPTER_INFO {
  struct _IP_ADAPTER_INFO* Next;//Ponteiro para o próximo adaptador na lista
  DWORD ComboIndex;//Valor reservado
  char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4];//Nome do adaptador expresso por uma string ANSI
  char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4];//Descrição do adaptador expressa por uma string ANSI
  UINT AddressLength;//O comprimento do endereço de hardware calculado em bytes
  BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH];//O endereço de hardware representado por um array de BYTE
  DWORD Index;//Índice do adaptador
  UINT Type;//O tipo do adaptador, principalmente os seguintes tipos:
  /*
   *  MIB_IF_TYPE_OTHER   1
   *  MIB_IF_TYPE_ETHERNET   6
   *  MIB_IF_TYPE_TOKENRING   9
   *  MIB_IF_TYPE_FDDI   15
   *  MIB_IF_TYPE_PPP   23
   *  MIB_IF_TYPE_LOOPBACK   24
   *  MIB_IF_TYPE_SLIP   28
   */
  UINT DhcpEnabled;//Especificar se este adaptador deve habilitar DHCP
  PIP_ADDR_STRING CurrentIpAddress;//Valor reservado
  IP_ADDR_STRING IpAddressList;//O IPv deste adaptador;4地址链表
  IP_ADDR_STRING GatewayList;//O gateway IPv deste adaptador;4地址链表
  IP_ADDR_STRING DhcpServer;//该适配器的DHCP服务器的IPv4 地址链表
  BOOL HaveWins;
  IP_ADDR_STRING PrimaryWinsServer;
  IP_ADDR_STRING SecondaryWinsServer;
  time_t LeaseObtained;
  time_t LeaseExpires;
  } IP_ADAPTER_INFO,*PIP_ADAPTER_INFO;

由于可能有多个网卡,因此struct _IP_ADAPTER_INFO* Next字段为一个链表结构指针,由于一个网卡可能有多个IP,因此IP_ADDR_STRING字段也应该是一个链表结构,其信息如下所示:

typedef struct _IP_ADDR_STRING
{
  struct _IP_ADDR_STRING* Next; //指向同类型节点,即下一个IP(如果有多IP的话)
  IP_ADDRESS_STRING IpAddress; //IP地址信息
  IP_MASK_STRING IpMask; //IP子网掩码
  DWORD Context;// 网络表入口。这个值对应着AddIPAddredd和DeleteIPAddress函数中的NTEContext参数
} IP_ADDR_STRING;

综上所述,用下图来描述网卡的结构存储信息,也许更清晰:

在基本了解以上信息后,就可以调用GetAdaptersInfo函数来获取相关网卡信息了,其通用代码如下所示:

#include <WinSock2.h>
#include <Iphlpapi.h>
#include <iostream>
using namespace std;
#pragma comment(lib,"Iphlpapi.lib") //需要添加Iphlpapi.lib库
int main(int argc, char* argv[])
{
  //PIP_ADAPTER_INFO结构体指针存储本机网卡信息
  PIP_ADAPTER_INFO pIpAdapterInfo = new IP_ADAPTER_INFO();
  //获得结构体大小,用于GetAdaptersInfo参数
  unsigned long stSize = sizeof(IP_ADAPTER_INFO);
  //Chama a função GetAdaptersInfo, preenche o ponteiro pIpAdapterInfo; onde o parâmetro stSize é tanto um valor de entrada quanto um valor de saída
  int nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);
  //Registrar o número de placas de rede
  int netCardNum = 0;
  //Registrar o número de endereços IP por placa de rede
  int IPnumPerNetCard = 0;
  if (ERROR_BUFFER_OVERFLOW == nRel)
  {
    //Se o retorno da função for ERROR_BUFFER_OVERFLOW
    //Isso indica que o espaço de memória passado para os parâmetros GetAdaptersInfo é insuficiente, e o stSize传出, representa o tamanho do espaço necessário
    //Isso também explica por que stSize é tanto um valor de entrada quanto um valor de saída
    //Liberar o espaço de memória original
    delete pIpAdapterInfo;
    //Requere espaço de memória novamente para armazenar todas as informações sobre as placas de rede
    pIpAdapterInfo = (PIP_ADAPTER_INFO)new BYTE[stSize];
    //Chama novamente a função GetAdaptersInfo, preenche o ponteiro pIpAdapterInfo
    nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);  
  }
  if (ERROR_SUCCESS == nRel)
  {
    //Saída de informações sobre a placa de rede
     //Pode haver várias placas de rede, portanto, é necessário usar um loop para verificar
  while (pIpAdapterInfo)
  {
    cout << "Número de placas de rede: " <<++netCardNum<<endl;
    cout << "Nome da placa de rede: " << pIpAdapterInfo->NomeDoAdapter<<endl;
    cout << "Descrição da placa de rede: " << pIpAdapterInfo->Descrição<<endl;
    switch(pIpAdapterInfo->Tipo)
    {
    case MIB_IF_TYPE_OTHER:
      cout << "Tipo de placa de rede: " << "OUTRO" << endl;
      break;
    case MIB_IF_TYPE_ETHERNET:
      cout << "Tipo de placa de rede: " << "ETHERNET" << endl;
      break;
    case MIB_IF_TYPE_TOKENRING:
      cout << "Tipo de placa de rede: " << "TOKENRING" << endl;
      break;
    case MIB_IF_TYPE_FDDI:
      cout<<"Tipo de placa de rede: "<<"FDDI"<<endl;
      break;
    case MIB_IF_TYPE_PPP:
      printf("PP\n");
      cout<<"Tipo de placa de rede: "<<"PPP"<<endl;
      break;
    case MIB_IF_TYPE_LOOPBACK:
      cout<<"Tipo de placa de rede: "<<"LOOPBACK"<<endl;
      break;
    case MIB_IF_TYPE_SLIP:
      cout<<"Tipo de placa de rede: "<<"SLIP"<<endl;
      break;
    default:
      break;
    }
    cout<<"Endereço MAC da placa de rede: ";
    for (DWORD i = 0; i < pIpAdapterInfo->AddressLength; i++)
      if (i < pIpAdapterInfo->AddressLength-1)
      {
        printf("%02X-", pIpAdapterInfo->Address[i]);
      }
      else
      {
        printf("%02X\n", pIpAdapterInfo->Address[i]);
      }
      cout<<"Endereços IP da placa de rede: "<<endl;
      //Pode haver múltiplos IPs na placa de rede, portanto, é necessário verificar pelo loop
      IP_ADDR_STRING *pIpAddrString =&(pIpAdapterInfo->IpAddressList);
      do 
      {
        cout<<"Número de IPs na placa de rede: "<<++IPnumPerNetCard<<endl;
        cout<<"Endereço IP: "<<pIpAddrString->IpAddress.String<<endl;
        cout<<"Endereço de sub-rede: "<<pIpAddrString->IpMask.String<<endl;
        cout<<"Endereço de gateway: "<<pIpAdapterInfo->GatewayList.IpAddress.String<<endl;
        pIpAddrString=pIpAddrString->Next;
      } while (pIpAddrString);
      pIpAdapterInfo = pIpAdapterInfo->Next;
      cout<<"--------------------------------------------------------------------"<<endl;
  }
  }
  //Liberar espaço de memória
  if (pIpAdapterInfo)
  {
    delete pIpAdapterInfo;
  }
  return 0;
}

Resultados da execução:

A segunda maneira de obter o endereço IP é:

#include <winsock.h>
#include <stdio.h>
#pragma comment(lib,"ws")2_32.lib") //Usado para linkar ao ws2_32.lib esta biblioteca
void CheckIP(void)//Função CheckIP, usada para obter o endereço IP do computador
{
 WORD wVersionRequested;//Variável do tipo WORD, usada para armazenar o valor da versão Winsock
 WSADATA wsaData;
 char name[255];//Usado para armazenar o nome do host
 PHOSTENT hostinfo;
 wVersionRequested=MAKEWORD(2,0);
 //Chame a função MAKEWORD() para obter a versão Winsock, usada para carregar a biblioteca Winsock
 if(WSAStartup(wVersionRequested,&wsaData) == 0)
 {
 //Carregar a biblioteca Winsock, se o valor de retorno da função WSAStartup() for 0, significa que a carga foi bem-sucedida
 if(gethostname(name,sizeof(name))==0)
 {
  if((hostinfo = gethostbyname(name) )!= NULL)
  {
  //Se obter o nome do host com sucesso, chame a função inet_ntoa() para obter o endereço IP
  LPCSTR ip = inet_ntoa(*(struct in_addr *)*hostinfo->h_addr_list);
  printf("O endereço IP do computador é:%s\n",ip);//Exibir endereço IP
  printf("O nome do computador é:%s\n",name);
  }
 }
 WSACleanup();
 }
}
int main()
{
 CheckIP();//Chame a função CheckIP() para obter e exibir o endereço IP
 return 0;
}

Isso é o que o editor trouxe para vocês sobre C++Aqui está a implementação completa de como obter todas as informações de IP e MAC de todas as interfaces de rede do computador local, esperamos que vocês apoiem e gritem tutorial~

Você também pode gostar