English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
На одном компьютере может быть не один сетевой адаптер, но у каждого адаптера есть только один MAC-адрес, а каждый адаптер может быть настроен с несколькими IP-адресами; например, в обычном ноутбуке есть два типа сетевых адаптеров: беспроводной адаптер и проводной адаптер (вход для сетевого кабеля); поэтому, чтобы получить информацию о всех IP и MAC-адресах сетевых адаптеров на этом компьютере, необходимо последовательно получить информацию о каждом адаптере и затем получить информацию о каждом из них; в Windows SDK информация о сетевых адаптерах хранится в структуре IP_ADAPTER_INFO, включая имя адаптера, описание адаптера, MAC-адрес адаптера, IP-адрес адаптера и т.д., основное описание которой приведено ниже:
typedef struct _IP_ADAPTER_INFO { struct _IP_ADAPTER_INFO* Next;//Pointer to the next adapter information in the list DWORD ComboIndex;//Reserved value char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4];//Adapter name represented by ANSI string char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4];//Adapter description represented by ANSI string UINT AddressLength;//Length of the adapter hardware address in bytes BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH];//Hardware address represented as a BYTE array DWORD Index;//Adapter index UINT Type;//Adapter type, mainly the following types: /* * 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;//Specifies whether DHCP is enabled for this adapter PIP_ADDR_STRING CurrentIpAddress;//Reserved value IP_ADDR_STRING IpAddressList;//The IPv4 address list for this adapter IP_ADDR_STRING GatewayList;//The IPv4 gateway address list for this adapter IP_ADDR_STRING DhcpServer;//The IPv4 address list of the DHCP server for this adapter 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; //вход в таблицу сетей. Этот значений соответствует параметру NTEContext в функциях AddIPAddress и DeleteIPAddress } 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[]) { //переменная-пounter 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 //Это означает, что переданного пространства для памяти недостаточно, и функция возвращает стSize, который указывает на необходимое пространство //Это также объясняет, почему 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->AdapterName << endl; cout << "Описание сетевой карты: " << pIpAdapterInfo->Description << endl; switch(pIpAdapterInfo->Type) { 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,"ws2_32.lib") //用于链接到ws2_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; {}
Вот и все, что я хотел рассказать вам о том, как получить все IP и MAC адреса всех сетевых карт компьютера на C++,希望大家多多支持呐喊教程~