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

C++本機のすべてのネットワークカードのIPとMACアドレス情報を取得する実装方法

一つのマシンには複数のネットワークインターフェースが存在する可能性がありますが、各インターフェースには一つのMACアドレスしかなく、各インターフェースは複数のIPアドレスを設定することができます。例えば、一般的なノートパソコンにはワイヤレスネットワークインターフェースと有線ネットワークインターフェース(LANインターフェース)の二種類があります。したがって、このマシンのすべてのネットワークインターフェースのIPとMACアドレス情報を取得するには、各インターフェースを順に取得し、その情報を順に取得する必要があります。Windows SDKでは、IP_ADAPTER_INFO構造体を使用してネットワークインターフェース情報を格納し、インターフェース名、インターフェース説明、インターフェースMACアドレス、インターフェースIPなどが含まれます。この構造体の主な説明は以下の通りです:

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;

複数のネットワークカードがあるため、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;// ネットワークテーブルのエントリ。この値はAddIPAddressと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);
  //GetAdaptersInfo関数を呼び出し、pIpAdapterInfoポインタ変数を埋める;stSizeパラメータは入力量であり、同時に出力量です
  int nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);
  //ネットワークカードの数を記録する
  int netCardNum = 0;
  //各ネットワークカード上のIPアドレスの数を記録する
  int IPnumPerNetCard = 0;
  if (ERROR_BUFFER_OVERFLOW == nRel)
  {
    //関数がERROR_BUFFER_OVERFLOWを返した場合
    //これにより、GetAdaptersInfoパラメータが渡されたメモリ空間が不足していることを示し、stSizeが必要な空間サイズを示しています
    //これがstSizeが入力量であり、同時に出力量である理由です
    //元のメモリ空間を解放する
    delete pIpAdapterInfo;
    //すべてのネットワークカード情報を格納するためのメモリ空間を再び確保する
    pIpAdapterInfo = (PIP_ADAPTER_INFO)new BYTE[stSize];
    //GetAdaptersInfo関数を再度呼び出し、pIpAdapterInfoポインタ変数を埋める
    nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);  
  }
  if (ERROR_SUCCESS == nRel)
  {
    //ネットワークカード情報を出力する
     //複数のネットワークカードがある可能性があるため、ループを通じて判断する
  while (pIpAdapterInfo)
  {
    cout << "ネットワークカード数:" <<++netCardNum<<endl;
    cout << "ネットワークカード名:" << pIpAdapterInfo->アダプタ名<<endl;
    cout << "ネットワークカード説明:" << pIpAdapterInfo->説明<<endl;
    switch(pIpAdapterInfo->タイプ)
    {
    case MIB_IF_TYPE_OTHER:
      cout << "ネットワークカードタイプ:" << "OTHER" << endl;
      break;
    case MIB_IF_TYPE_ETHERNET:
      cout << "ネットワークカードタイプ:" << "ETHERNET" << endl;
      break;
    case MIB_IF_TYPE_TOKENRING:
      cout << "ネットワークカードタイプ:" << "TOKENRING" << endl;
      break;
    case MIB_IF_TYPE_FDDI:
      cout<<"ネットワークカードのタイプ:"<<"FDDI"<<endl;
      break;
    case MIB_IF_TYPE_PPP:
      printf("PP\n");
      cout<<"ネットワークカードのタイプ:"<<"PPP"<<endl;
      break;
    case MIB_IF_TYPE_LOOPBACK:
      cout<<"ネットワークカードのタイプ:"<<"LOOPBACK"<<endl;
      break;
    case MIB_IF_TYPE_SLIP:
      cout<<"ネットワークカードのタイプ:"<<"SLIP"<<endl;
      break;
    default:
      break;
    }
    cout<<"ネットワークカードのMACアドレス:";
    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<<"ネットワークカードのIPアドレス:"<<endl;
      //ネットワークカードには複数のIPが存在する可能性があるため、ループを使用して判定する
      IP_ADDR_STRING *pIpAddrString = &(pIpAdapterInfo->IpAddressList);
      do 
      {
        cout<<"このネットワークカードのIP数:"<<++IPnumPerNetCard<<endl;
        cout<<"IPアドレス:"<<pIpAddrString->IpAddress.String<<endl;
        cout<<"サブネットアドレス:"<<pIpAddrString->IpMask.String<<endl;
        cout<<"ゲートウェイアドレス:"<<pIpAdapterInfo->GatewayList.IpAddress.String<<endl;
        pIpAddrString=pIpAddrString->Next;
      } while (pIpAddrString);
      pIpAdapterInfo = pIpAdapterInfo->Next;
      cout<<"--------------------------------------------------------------------"<<endl;
  }
  }
  //メモリを解放する
  if (pIpAdapterInfo)
  {
    delete pIpAdapterInfo;
  }
  return 0;
}

実行結果:

IPアドレスを取得する第二种方法:

#include <winsock.h>
#include <stdio.h>
#pragma comment(lib,"ws")2_32.lib") //wsにリンクするために使用されます2_32.libこのライブラリ
void CheckIP(void)//CheckIP関数、本機のIPアドレスを取得するために使用されます
{
 WORD wVersionRequested;//WORD型の変数、Winsockバージョンの値を保存するために使用されます
 WSADATA wsaData;
 char name[255];//ホスト名を保存するために使用されます
 PHOSTENT hostinfo;
 wVersionRequested=MAKEWORD(2,0);
 //MAKEWORD()関数を呼び出してWinsockバージョンを取得し、Winsockライブラリをロードするために使用します
 if(WSAStartup(wVersionRequested,&wsaData) == 0)
 {
 //Winsockライブラリをロードします。WSAStartup()関数の返値が0の場合、ロードが成功しました
 if(gethostname(name,sizeof(name))==0)
 {
  if((hostinfo = gethostbyname(name) )!= NULL)
  {
  //ホスト名を取得した場合、inet_ntoa()関数を呼び出してIPアドレスを取得します
  LPCSTR ip = inet_ntoa(*(struct in_addr *)*hostinfo->h_addr_list);
  printf("本機のIPアドレスは:%s\n",ip);//IPアドレスを出力します
  printf("本機の名前は:%s\n",name);
  }
 }
 WSACleanup();
 }
}
int main()
{
 CheckIP();//CheckIP()関数を呼び出してIPアドレスを取得し、出力します
 return 0;
}

これが編集者が皆様に提供したC++本機のすべてのネットワークカードのIPおよびMACアドレス情報の取得方法の全てを提供しました。皆様のサポートと歓声をどうぞ。

基礎教程
おすすめ