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

Metodo di ottenere l'indirizzo IP e l'indirizzo MAC di tutte le schede di rete del computer locale in C++

Un computer potrebbe avere più di una scheda di rete, ma ogni scheda di rete ha un'unica indirizzo MAC, e ogni scheda di rete potrebbe avere più indirizzi IP; come nei laptop comuni, ci sono schede di rete wireless e schede di rete cablate (interfaccia di rete via cavo); quindi, per ottenere le informazioni di IP e MAC di tutte le schede di rete del computer, è necessario ottenere in sequenza ogni scheda di rete e ottenere le informazioni di ciascuna di esse; nel SDK di Windows, l'informazione della scheda di rete è memorizzata nella struttura IP_ADAPTER_INFO, inclusi il nome della scheda di rete, la descrizione della scheda di rete, l'indirizzo MAC della scheda di rete, l'indirizzo IP della scheda di rete, ecc., la descrizione principale della struttura è come segue:

typedef struct _IP_ADAPTER_INFO {
  struct _IP_ADAPTER_INFO* Next;//指向链表中下一个适配器信息的指针
  DWORD ComboIndex;//预留值
  char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4];//使用ANSI字符串表示的适配器名称
  char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4];//使用ANSI字符串表示的适配器描述
  UINT AddressLength;//适配器硬件地址以字节计算的长度
  BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH];//硬件地址以BYTE数组所表示
  DWORD Index;//适配器索引
  UINT Type;//适配器类型,主要有以下几种:
  /*
   *  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;//指定这个适配器是否开启DHCP
  PIP_ADDR_STRING CurrentIpAddress;//预留值
  IP_ADDR_STRING IpAddressList;//该适配器的IPv4地址链表
  IP_ADDR_STRING GatewayList;//该适配器的网关IPv4地址链表
  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;

Poiché possono esserci più schede di rete, il campo struct _IP_ADAPTER_INFO* Next è un puntatore a struttura di elenco, poiché una scheda di rete può avere più IP, quindi il campo IP_ADDR_STRING dovrebbe anche essere una struttura di elenco, le informazioni sono le seguenti:

typedef struct _IP_ADDR_STRING
{
  struct _IP_ADDR_STRING* Next; // Puntatore a nodo dello stesso tipo, ovvero il prossimo IP (se ci sono più IP)
  IP_ADDRESS_STRING IpAddress; // Informazioni sull'indirizzo IP
  IP_MASK_STRING IpMask; // Maschera di sottorete IP
  DWORD Context; // Entrata della tabella di rete. Questo valore corrisponde al parametro NTEContext nelle funzioni AddIPAddress e DeleteIPAddress
} IP_ADDR_STRING;

Di conseguenza, l'immagine seguente può illustrare meglio la struttura di archiviazione delle informazioni delle schede di rete:

Dopo aver avuto una base di conoscenza di queste informazioni, è possibile chiamare la funzione GetAdaptersInfo per ottenere le informazioni relative alle schede di rete, il codice generico è il seguente:

#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);
  //调用GetAdaptersInfo函数,填充pIpAdapterInfo指针变量;其中stSize参数既是一个输入量也是一个输出量
  int nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);
  //记录网卡数量
  int netCardNum = 0;
  // Registra il numero di indirizzi IP per ogni scheda di rete
  int IPnumPerNetCard = 0;
  if (ERROR_BUFFER_OVERFLOW == nRel)
  {
    // Se la funzione restituisce ERROR_BUFFER_OVERFLOW
    // Questo significa che lo spazio di memoria passato ai parametri di GetAdaptersInfo non è sufficiente, e stSize è il valore di output che indica la dimensione dello spazio richiesto
    // Questo è anche per spiegare perché stSize è sia un input che un output
    // Libera l'area di memoria originale
    delete pIpAdapterInfo;
    // Richiede una nuova area di memoria per memorizzare tutte le informazioni sulla scheda di rete
    pIpAdapterInfo = (PIP_ADAPTER_INFO)new BYTE[stSize];
    // Chiama di nuovo la funzione GetAdaptersInfo per riempire il puntatore pIpAdapterInfo
    nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);  
  {}
  if (ERROR_SUCCESS == nRel)
  {
    // Output delle informazioni sulla scheda di rete
     // Potrebbe esserci più di una scheda di rete, quindi utilizzare un ciclo per determinare
  while (pIpAdapterInfo)
  {
    cout << "Numero di schede di rete: " << ++netCardNum << endl;
    cout << "Nome della scheda di rete: " << pIpAdapterInfo->AdapterName << endl;
    cout << "Descrizione della scheda di rete: " << pIpAdapterInfo->Description << endl;
    switch(pIpAdapterInfo->Type)
    {
    case MIB_IF_TYPE_OTHER:
      cout << "Tipo di scheda di rete: " << "OTHER" << endl;
      break;
    case MIB_IF_TYPE_ETHERNET:
      cout << "Tipo di scheda di rete: " << "ETHERNET" << endl;
      break;
    case MIB_IF_TYPE_TOKENRING:
      cout << "Tipo di scheda di rete: " << "TOKENRING" << endl;
      break;
    case MIB_IF_TYPE_FDDI:
      cout << "Tipo di scheda di rete: " << "FDDI" << endl;
      break;
    case MIB_IF_TYPE_PPP:
      printf("PP\n");
      cout << "Tipo di scheda di rete: " << "PPP" << endl;
      break;
    case MIB_IF_TYPE_LOOPBACK:
      cout << "Tipo di scheda di rete: " << "LOOPBACK" << endl;
      break;
    case MIB_IF_TYPE_SLIP:
      cout<<"Tipo di scheda di rete: "<<"SLIP"<<endl;
      break;
    default:
      break;
    {}
    cout<<"Indirizzo MAC della scheda di rete: ";
    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<<"Indirizzi IP della scheda di rete: "<<endl;
      //Possibile che la scheda di rete abbia più IP, quindi utilizzare un ciclo per il controllo
      IP_ADDR_STRING *pIpAddrString =&(pIpAdapterInfo->IpAddressList);
      do 
      {
        cout<<"Numero di IP su questa scheda di rete: "<<++IPnumPerNetCard<<endl;
        cout<<"Indirizzo IP: "<<pIpAddrString->IpAddress.String<<endl;
        cout<<"Indirizzo di sottorete: "<<pIpAddrString->IpMask.String<<endl;
        cout<<"Indirizzo di rete gateway: "<<pIpAdapterInfo->GatewayList.IpAddress.String<<endl;
        pIpAddrString=pIpAddrString->Next;
      } while (pIpAddrString);
      pIpAdapterInfo = pIpAdapterInfo->Next;
      cout<<"--------------------------------------------------------------------"<<endl;
  {}
  {}
  //Rilascio dello spazio di memoria
  if (pIpAdapterInfo)
  {
    delete pIpAdapterInfo;
  {}
  return 0;
{}

Risultato dell'esecuzione:

Secondo metodo per ottenere l'indirizzo IP:

#include <winsock.h>
#include <stdio.h>
//pragma comment(lib,"ws2_32.lib") //Utilizzato per collegarsi alla libreria ws2_32.lib
void CheckIP(void) // CheckIP function, used to obtain the computer IP address
{
 WORD wVersionRequested; // WORD type variable, used to store the value of the Winsock version
 WSADATA wsaData;
 char name[255]; // Used to store the hostname
 PHOSTENT hostinfo;
 wVersionRequested = MAKEWORD(2, 0);
 // Call the MAKEWORD() function to obtain the Winsock version, which is used to load the Winsock library
 if(WSAStartup(wVersionRequested, &wsaData) == 0)
 {
 // Load the Winsock library, if the return value of the WSAStartup() function is 0, it means that the loading is successful
 if(gethostname(name, sizeof(name)) == 0)
 {
  if((hostinfo = gethostbyname(name)) != NULL)
  {
  // If the hostname is obtained successfully, call the inet_ntoa() function to obtain the IP address
  LPCSTR ip = inet_ntoa(*(struct in_addr *)*hostinfo->h_addr_list);
  printf("The IP address of the computer is: %s\n", ip); // Output the IP address
  printf("The name of the computer is: %s\n", name);
  {}
 {}
 WSACleanup();
 {}
{}
int main()
{
 CheckIP(); // Call the CheckIP() function to obtain and output the IP address
 return 0;
{}

This is the full content of the implementation method of obtaining all network card IP and MAC addresses of the computer brought to you by the editor. I hope everyone will support and cheer for the tutorial~

Ti potrebbe interessare