一、前言
本文主要介绍Linux和Windows下使用C语言获取各种硬件信息,包括CPU序列号、硬盘序列号、网卡信息(包括网卡名字、IP地址、MAC地址、网卡是否插入网线等)。
二、代码实现
Linux下所需包含的头文件
#include <linux/hdreg.h>
#include <fcntl.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if.h>
#include <unistd.h>
#include <sys/io.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <sys/ioctl.h>
Windows下所需包含的头文件
#include <iostream>
#include <string>
#include <windows.h>
#include <iphlpapi.h>
2.1 获取CPU序列号
- Linux下获取CPU序列号,也就是id,经过实测发现,相同厂家相同型号的CPU的序列号是一样的。
/**
* @brief getCpuId 获取Linux下的CPU序列号
* @param id 存储获取到的CPU序列号的字符串变量
* @return 0:获取成功 其他返回值:获取失败
*/
int getCpuId(char *id)
{
unsigned int s1,s2;
asm volatile
( "movl $0x01,%%eax ; \n\t"
"xorl %%edx,%%edx ;\n\t"
"cpuid ;\n\t"
"movl %%edx , %0;\n\t"
"movl %%eax , %1;\n\t"
:"=m"(s1),"=m"(s2)
);
if(0 == s1 && 0 == s2) {
return -1;
}
char cpu_id[32] = {0};
sprintf(cpu_id, "%08X-%08X", htonl(s2), htonl(s1));
strcpy(id, cpu_id);
return 0;
}
- Windows下获取CPU序列号,也就是id,经过实测发现,相同厂家相同型号的CPU的序列号是一样的。
/**
* @brief GetCpuByCmd 获取windows下的CPU序列号
* @param ider 获取到的CPU序列号的字符串变量
* @return true:获取成功 false:获取失败
*/
bool GetCpuByCmd(string &ider)
{
//CPU序列号
const long MAX_COMMAND_SIZE = 64; //命令行输出缓冲大小
WCHAR szFetCmd[] = L"wmic cpu get processorid"; //获取CPU序列号命令行
const string strEnSearch = "ProcessorId"; //CPU序列号前导信息
BOOL bret = FALSE;
HANDLE hReadPipe = NULL; //读取管道
HANDLE hWritePipe = NULL; //写入管道
PROCESS_INFORMATION pi; //进程信息
STARTUPINFO si; //控制命令行窗口信息
SECURITY_ATTRIBUTES sa; //安全属性
char szBuffer[MAX_COMMAND_SIZE + 1] = {0}; //放置命令行结果的输出缓存区
string strBuffer;
unsigned long count = 0;
long ipos = 0;
memset(&pi , 0 , sizeof(pi));
memset(&si , 0 , sizeof(si));
memset(&sa , 0 , sizeof(sa));
//初始化管道
pi.hProcess = NULL;
pi.hThread = NULL;
si.cb = sizeof(STARTUPINFO);
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
//创建管道
bret = CreatePipe(&hReadPipe , &hWritePipe , &sa , 0);
if(!bret) {
CloseHandle(hWritePipe);
CloseHandle(hReadPipe);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
//设置命令行窗口的信息为指定的读写管道
GetStartupInfo(&si);
si.hStdError = hWritePipe;
si.hStdOutput = hWritePipe;
si.wShowWindow = SW_HIDE; //隐藏命令行窗口
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
//创建获取命令行的进程
bret = CreateProcess(NULL , szFetCmd , NULL , NULL , TRUE , 0 , NULL , NULL , &si , &pi);
if(!bret) {
CloseHandle(hWritePipe);
CloseHandle(hReadPipe);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
//读取返回的数据
WaitForSingleObject(pi.hProcess , 500);
bret = ReadFile(hReadPipe , szBuffer , MAX_COMMAND_SIZE , &count , 0);
if(!bret) {
CloseHandle(hWritePipe);
CloseHandle(hReadPipe);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
//查找CPU序列号
bret = FALSE;
strBuffer = szBuffer;
ipos = strBuffer.find(strEnSearch);
if(ipos < 0) { //没有找到
CloseHandle(hWritePipe);
CloseHandle(hReadPipe);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
else {
strBuffer = strBuffer.substr(ipos + strEnSearch.length());
}
memset(szBuffer , 0x00 , sizeof(szBuffer));
strcpy_s(szBuffer , strBuffer.c_str());
//去掉中间的空格\r\n
char temp[512];
memset(temp , 0 , sizeof(temp));
int index = 0;
for(size_t i = 0 ; i < strBuffer.size() ; i++) {
if(strBuffer[i] != ' ' && strBuffer[i] != '\n' && strBuffer[i] != '\r') {
temp[index] = strBuffer[i];
index++;
}
}
ider = temp;
return true;
}
2.2 获取硬盘序列号
- Linux下获取硬盘序列号。
/**
* @brief removeBlank 删除字符串中的空格
* @param str 需要处理的字符串
* @return 无返回值
*/
void removeBlank(char *str)
{
char *str_c = str;
int i,j=0;
for(i=0;str[i]!='\0';i++) {
if(str[i]!=' ') {
str_c[j++]=str[i];
}
}
str_c[j]='\0';
str = str_c;
}
/**
* @brief getDiskId 获取Linux下的硬盘序列号
* @param hd_name 硬盘所在位置 例:/dev/sda
* @param id 存储获取到的硬盘序列号的字符串变量
* @return 0:获取成功 其他返回值:获取失败
*/
int getDiskId(char *hd_name, char *id)
{
struct hd_driveid hid;
int fd = open(hd_name,O_RDONLY | O_NONBLOCK);
if(fd <0) {
perror("open fd");
return -1;
}
if(ioctl(fd,HDIO_GET_IDENTITY,&hid)<0) {
perror("ioctl");
return -1;
}
close(fd);
char disk_id[32] = {0};
sprintf(disk_id, "%s", hid.serial_no);
removeBlank(disk_id); //删除字符串中的空格
strcpy(id, disk_id);
return 0;
}
- Windows下获取硬盘序列号。
/**
* @brief GetDiskByCmd 获取windows下的硬盘序列号
* @param ider 获取到的硬盘序列号的字符串变量
* @return true:获取成功 false:获取失败
*/
bool GetDiskByCmd(string &ider)
{
//硬盘序列号
const long MAX_COMMAND_SIZE = 64; //命令行输出缓冲大小
WCHAR szFetCmd[] = L"wmic diskdrive get serialnumber"; //获取CPU序列号命令行
const string strEnSearch = "SerialNumber"; //CPU序列号前导信息
BOOL bret = FALSE;
HANDLE hReadPipe = NULL; //读取管道
HANDLE hWritePipe = NULL; //写入管道
PROCESS_INFORMATION pi; //进程信息
STARTUPINFO si; //控制命令行窗口信息
SECURITY_ATTRIBUTES sa; //安全属性
char szBuffer[MAX_COMMAND_SIZE + 1] = {0}; //放置命令行结果的输出缓存区
string strBuffer;
unsigned long count = 0;
long ipos = 0;
memset(&pi, 0, sizeof(pi));
memset(&si, 0, sizeof(si));
memset(&sa, 0, sizeof(sa));
//初始化管道
pi.hProcess = NULL;
pi.hThread = NULL;
si.cb = sizeof(STARTUPINFO);
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
//创建管道
bret = CreatePipe(&hReadPipe, &hWritePipe, &sa, 0);
if(!bret) {
CloseHandle(hWritePipe);
CloseHandle(hReadPipe);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
//设置命令行窗口的信息为指定的读写管道
GetStartupInfo(&si);
si.hStdError = hWritePipe;
si.hStdOutput = hWritePipe;
si.wShowWindow = SW_HIDE; //隐藏命令行窗口
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
//创建获取命令行的进程
bret = CreateProcess(NULL, szFetCmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
if(!bret) {
CloseHandle(hWritePipe);
CloseHandle(hReadPipe);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
//读取返回的数据
WaitForSingleObject(pi.hProcess , 500);
bret = ReadFile(hReadPipe, szBuffer, MAX_COMMAND_SIZE, &count, 0);
if(!bret) {
CloseHandle(hWritePipe);
CloseHandle(hReadPipe);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
//查找CPU序列号
bret = FALSE;
strBuffer = szBuffer;
ipos = strBuffer.find(strEnSearch);
if(ipos < 0) { //没有找到
CloseHandle(hWritePipe);
CloseHandle(hReadPipe);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
else {
strBuffer = strBuffer.substr(ipos + strEnSearch.length());
}
memset(szBuffer, 0x00, sizeof(szBuffer));
strcpy_s(szBuffer, strBuffer.c_str());
//去掉中间的空格\r\n
char temp[512];
memset(temp , 0 , sizeof(temp));
int index = 0;
for(size_t i = 0; i < strBuffer.size(); i++) {
if(strBuffer[i] != ' ' && strBuffer[i] != '\n' && strBuffer[i] != '\r') {
temp[index] = strBuffer[i];
index++;
}
}
ider = temp;
return true;
}
2.3 获取网卡信息
- Linux下获取网卡信息,包括网卡名字、IP地址、MAC地址、是否已经插入网线等信息。
//网卡信息结构体1
typedef struct __net_iface {
int sum_n;
char net_name1[20];
char net_name2[20];
char net_name3[20];
char net_name4[20];
char net_name5[20];
char net_ip1[16];
char net_ip2[16];
char net_ip3[16];
char net_ip4[16];
char net_ip5[16];
char net_mac1[32];
char net_mac2[32];
char net_mac3[32];
char net_mac4[32];
char net_mac5[32];
}net_iface;
//网卡信息结构体2
struct net_iface_1 {
struct net_iface_1 *next; //指向下一个网卡信息结构体的地址
char net_name[20]; //网卡名字
char net_ip[16]; //网卡IP
};
/**
* @brief get_iface_name 获取网口名字
* @param get_iface OUT 结构体
* @return 成功返回1 错误返回负数
*/
int get_iface_name(net_iface *get_iface)
{
int sock_get_iface;
struct ifconf ifc_get_iface;
struct ifreq *ifr_get_iface;
//初始化 ifconf
char buf[512];
ifc_get_iface.ifc_len = 512;
ifc_get_iface.ifc_buf = buf;
memset(get_iface,0,sizeof(net_iface));
sock_get_iface = socket(AF_INET,SOCK_DGRAM,0);
if(sock_get_iface < 0) {
perror("SOCKET:");
return -1;
}
if(ioctl(sock_get_iface ,SIOCGIFCONF,&ifc_get_iface) < 0) {
perror("ioctl");
return -1;
}
ifr_get_iface = (struct ifreq*)buf;
get_iface->sum_n = ifc_get_iface.ifc_len/sizeof(struct ifreq);
int control_n = 1;
for(int i = (ifc_get_iface.ifc_len/sizeof(struct ifreq)); i > 0; i--) {
if(strcmp(inet_ntoa(((struct sockaddr_in*)&(ifr_get_iface->ifr_addr))->sin_addr),"127.0.0.1") == 0) {
ifr_get_iface++;
get_iface->sum_n--;
continue;
}
else {
switch (control_n) {
case 1:
strcpy(get_iface->net_name1,ifr_get_iface->ifr_name);
strcpy(get_iface->net_ip1,inet_ntoa(((struct sockaddr_in*)&(ifr_get_iface->ifr_addr))->sin_addr));
break;
case 2:
strcpy(get_iface->net_name2,ifr_get_iface->ifr_name);
strcpy(get_iface->net_ip2,inet_ntoa(((struct sockaddr_in*)&(ifr_get_iface->ifr_addr))->sin_addr));
break;
case 3:
strcpy(get_iface->net_name3,ifr_get_iface->ifr_name);
strcpy(get_iface->net_ip3,inet_ntoa(((struct sockaddr_in*)&(ifr_get_iface->ifr_addr))->sin_addr));
break;
case 4:
strcpy(get_iface->net_name4,ifr_get_iface->ifr_name);
strcpy(get_iface->net_ip4,inet_ntoa(((struct sockaddr_in*)&(ifr_get_iface->ifr_addr))->sin_addr));
break;
case 5:
strcpy(get_iface->net_name5,ifr_get_iface->ifr_name);
strcpy(get_iface->net_ip5,inet_ntoa(((struct sockaddr_in*)&(ifr_get_iface->ifr_addr))->sin_addr));
break;
default:
break;
}
}
control_n++;
ifr_get_iface++;
}
close(sock_get_iface);
return 1;
}
/**
* @brief getNetMac 获取Linux下的所有网卡MAC序列号(最多五个网卡设备)
* @param get_iface 存储网卡信息的结构体
* @return 0:获取成功 其他返回值:获取失败
*/
int getNetMac(net_iface *get_iface)
{
int i = 0;
int sock;
get_iface_name(get_iface);
//printf("get_iface->sum_n: %d\n",get_iface->sum_n);
for(i=1;i<=get_iface->sum_n;i++) {
switch(i) {
case 1:
if((sock = socket(AF_INET,SOCK_STREAM,0))<0) {
perror("socket");
return 2;
}
struct ifreq ifreq1;
strcpy(ifreq1.ifr_name,get_iface->net_name1);
printf("%s ",ifreq1.ifr_name);
if(ioctl(sock,SIOCGIFHWADDR,&ifreq1)<0) {
perror("ioctl ");
return 3;
}
sprintf(get_iface->net_mac1,"%02x:%02x:%02x:%02x:%02x:%02x",
(unsigned char)ifreq1.ifr_hwaddr.sa_data[0],
(unsigned char)ifreq1.ifr_hwaddr.sa_data[1],
(unsigned char)ifreq1.ifr_hwaddr.sa_data[2],
(unsigned char)ifreq1.ifr_hwaddr.sa_data[3],
(unsigned char)ifreq1.ifr_hwaddr.sa_data[4],
(unsigned char)ifreq1.ifr_hwaddr.sa_data[5]);
printf("MAC1: %s\n",get_iface->net_mac1);
close(sock);
break;
case 2:
if((sock = socket(AF_INET,SOCK_STREAM,0))<0) {
perror("socket");
return 2;
}
struct ifreq ifreq2;
strcpy(ifreq2.ifr_name,get_iface->net_name2);
printf("%s ",ifreq2.ifr_name);
if(ioctl(sock,SIOCGIFHWADDR,&ifreq2)<0) {
perror("ioctl ");
return 3;
}
sprintf(get_iface->net_mac2,"%02x:%02x:%02x:%02x:%02x:%02x",
(unsigned char)ifreq2.ifr_hwaddr.sa_data[0],
(unsigned char)ifreq2.ifr_hwaddr.sa_data[1],
(unsigned char)ifreq2.ifr_hwaddr.sa_data[2],
(unsigned char)ifreq2.ifr_hwaddr.sa_data[3],
(unsigned char)ifreq2.ifr_hwaddr.sa_data[4],
(unsigned char)ifreq2.ifr_hwaddr.sa_data[5]);
printf("MAC2: %s\n",get_iface->net_mac2);
close(sock);
break;
case 3:
if((sock = socket(AF_INET,SOCK_STREAM,0))<0) {
perror("socket");
return 2;
}
struct ifreq ifreq3;
strcpy(ifreq3.ifr_name,get_iface->net_name3);
printf("%s ",ifreq3.ifr_name);
if(ioctl(sock,SIOCGIFHWADDR,&ifreq3)<0) {
perror("ioctl ");
return 3;
}
sprintf(get_iface->net_mac3,"%02x:%02x:%02x:%02x:%02x:%02x",
(unsigned char)ifreq3.ifr_hwaddr.sa_data[0],
(unsigned char)ifreq3.ifr_hwaddr.sa_data[1],
(unsigned char)ifreq3.ifr_hwaddr.sa_data[2],
(unsigned char)ifreq3.ifr_hwaddr.sa_data[3],
(unsigned char)ifreq3.ifr_hwaddr.sa_data[4],
(unsigned char)ifreq3.ifr_hwaddr.sa_data[5]);
printf("MAC3: %s\n",get_iface->net_mac3);
close(sock);
break;
case 4:
if((sock = socket(AF_INET,SOCK_STREAM,0))<0) {
perror("socket");
return 2;
}
struct ifreq ifreq4;
strcpy(ifreq4.ifr_name,get_iface->net_name4);
printf("%s ",ifreq4.ifr_name);
if(ioctl(sock,SIOCGIFHWADDR,&ifreq4)<0) {
perror("ioctl ");
return 3;
}
sprintf(get_iface->net_mac4,"%02x:%02x:%02x:%02x:%02x:%02x",
(unsigned char)ifreq4.ifr_hwaddr.sa_data[0],
(unsigned char)ifreq4.ifr_hwaddr.sa_data[1],
(unsigned char)ifreq4.ifr_hwaddr.sa_data[2],
(unsigned char)ifreq4.ifr_hwaddr.sa_data[3],
(unsigned char)ifreq4.ifr_hwaddr.sa_data[4],
(unsigned char)ifreq4.ifr_hwaddr.sa_data[5]);
printf("MAC4: %s\n",get_iface->net_mac4);
close(sock);
break;
case 5:
if((sock = socket(AF_INET,SOCK_STREAM,0))<0) {
perror("socket");
return 2;
}
struct ifreq ifreq5;
strcpy(ifreq5.ifr_name,get_iface->net_name5);
printf("%s ",ifreq5.ifr_name);
if(ioctl(sock,SIOCGIFHWADDR,&ifreq5)<0) {
perror("ioctl ");
return 3;
}
sprintf(get_iface->net_mac5,"%02x:%02x:%02x:%02x:%02x:%02x",
(unsigned char)ifreq5.ifr_hwaddr.sa_data[0],
(unsigned char)ifreq5.ifr_hwaddr.sa_data[1],
(unsigned char)ifreq5.ifr_hwaddr.sa_data[2],
(unsigned char)ifreq5.ifr_hwaddr.sa_data[3],
(unsigned char)ifreq5.ifr_hwaddr.sa_data[4],
(unsigned char)ifreq5.ifr_hwaddr.sa_data[5]);
printf("MAC5: %s\n",get_iface->net_mac5);
close(sock);
break;
}
}
return 0;
}
/**
* @brief check_nic 检测网卡是否已经插上网线
* @param eth_name IN 网卡名字
* @return 0:网卡已插上网线 -1:网卡未插上网线 其他返回值:错误
*/
int check_nic(const char *net_name)
{
struct ifreq ifr;
int skfd = socket(AF_INET, SOCK_DGRAM, 0);
if(skfd < 0) {
qDebug("socket error: %s [%s]\n", strerror(errno), __FUNCTION__);
return -2;
}
strcpy(ifr.ifr_name, net_name);
if(ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) {
close(skfd);
return -3;
}
if(ifr.ifr_flags & IFF_RUNNING) {
close(skfd);
return 0; //网卡已插上网线
}
else {
close(skfd);
return -1;
}
}
/**
* @brief get_iface_info 获取本地所有网卡名字和IP
* @param netIface 网卡信息结构体指针,用户自行分配存储空间
* @param outBuffLen netIface分配的存储空间大小,若与实际获取到的数据总大小不一致,则将实际的总大小返回
* @return 0:成功
* 1:outBuffLen与实际获取到的数据总大小不一致,将实际的大小赋值给outBuffLen并返回
* -1:错误
* 使用步骤注意:
* 1、malloc申请 netIface 堆内存空间,初始化 outBuffLen 变量的值
* 2、调用一次该函数,目的是确定实际outBuffLen的大小
* 3、判断返回值,如果返回1,则释放netIface堆内存空间,根据outBuffLen的大小重新分配堆内存空间;
* 如果返回0,证明获取网卡信息成功,直接跳过第3、4步
* 4、再一次调用该函数,若成功返回,则网卡信息获取完成
* 5、遍历获取网卡信息,根据结构体的 next 指针即可遍历指向下一个网卡信息的地址,直到 next 为空
*/
int get_iface_info(net_iface_1 *netIface, unsigned int *outBuffLen)
{
int sock_get_iface;
struct ifconf ifc_get_iface;
struct ifreq *ifr_get_iface;
//初始化 ifconf
char buf[512];
ifc_get_iface.ifc_len = 512;
ifc_get_iface.ifc_buf = buf;
sock_get_iface = socket(AF_INET,SOCK_DGRAM,0);
if(sock_get_iface < 0) {
perror("SOCKET:");
return -1;
}
if(ioctl(sock_get_iface ,SIOCGIFCONF,&ifc_get_iface) < 0) {
perror("ioctl");
return -1;
}
unsigned int num = (ifc_get_iface.ifc_len/sizeof(struct ifreq)); //网卡个数
if(*outBuffLen != num * sizeof(net_iface_1)) {
*outBuffLen = num * sizeof(net_iface_1);
return 1;
}
memset(netIface, 0, *outBuffLen);
ifr_get_iface = (struct ifreq*)buf;
for(unsigned int i=0; i<num; i++) {
strcpy(netIface[i].net_name, ifr_get_iface->ifr_name);
strcpy(netIface[i].net_ip, inet_ntoa(((struct sockaddr_in*)&(ifr_get_iface->ifr_addr))->sin_addr));
if(i == num - 1) {
netIface[i].next = NULL;
}
else {
netIface[i].next = netIface + (i + 1);
}
ifr_get_iface++;
}
close(sock_get_iface);
return 0;
}
- Windows下获取网卡信息,包括网卡名字、IP地址、MAC地址、是否已经插入网线等信息。
// 网卡信息结构体
typedef struct _adapter_info {
struct _adapter_info *next; //指向下一个网卡信息结构体的地址
char name[MAX_ADAPTER_NAME_LENGTH + 4]; //网卡名字
unsigned long index; //网卡索引号
char ipAddr[16]; //网卡IP地址
char gateway[16]; //网卡网关
char ipMask[16]; //网卡掩码
char macAddr[20]; //网卡物理地址
}adapterInfo;
/**
* @brief getAdaptersInfo 获取网卡(网络适配器)的基本信息
* @param infoList 获取到的各个网卡(网络适配器)的信息链表
* @return int 0:成功
* 1:outBuffLen与实际获取到的数据总大小不一致,将实际的大小赋值给outBuffLen并返回
* -1:失败
* 使用步骤注意:
* 1、malloc申请pInfo堆内存空间,初始化outBuffLen变量的值
* 2、调用一次该函数,目的是确定实际outBuffLen的大小
* 3、判断返回值,如果返回1,则释放pInfo堆内存空间,根据outBuffLen的大小重新分配堆内存空间;
* 如果返回0,证明获取网卡信息成功,直接跳过第3、4步
* 4、再一次调用该函数,若成功返回,则网卡信息获取完成
* 5、遍历获取网卡信息,根据结构体的next指针即可遍历指向下一个网卡信息的地址,直到next为空
*/
int getAdaptersInfo(adapterInfo *pInfo, unsigned int *outBuffLen)
{
PIP_ADAPTER_INFO pAdapterInfo;
PIP_ADAPTER_INFO pAdapter = NULL;
ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
pAdapterInfo = (PIP_ADAPTER_INFO)malloc(ulOutBufLen);
DWORD dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen); //第一次调用 getAdaptersInfo 获取 ulOutBufLen 的大小
if(dwRetVal == ERROR_BUFFER_OVERFLOW) {
free(pAdapterInfo);
pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);
dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen);
}
if(dwRetVal == NO_ERROR) {
pAdapter = pAdapterInfo;
unsigned int adapterNum = 0;
while(pAdapter) {
adapterNum++;
pAdapter = pAdapter->Next;
}
if(*outBuffLen != adapterNum * sizeof(adapterInfo)) {
*outBuffLen = adapterNum * sizeof(adapterInfo);
if(pAdapterInfo != NULL) {
free(pAdapterInfo);
pAdapterInfo = NULL;
pAdapter = NULL;
}
return 1;
}
memset(pInfo, 0, *outBuffLen);
pAdapter = pAdapterInfo;
unsigned int currNum = 0;
while(pAdapter) {
memcpy(pInfo[currNum].name, pAdapter->AdapterName, sizeof(pAdapter->AdapterName)); //网卡名字
pInfo[currNum].index = pAdapter->Index; //网卡索引号
memcpy(pInfo[currNum].ipAddr, pAdapter->IpAddressList.IpAddress.String,
sizeof(pAdapter->IpAddressList.IpAddress.String)); //网卡IP地址
memcpy(pInfo[currNum].gateway, pAdapter->GatewayList.IpAddress.String,
sizeof(pAdapter->GatewayList.IpAddress.String)); //网卡网关地址
memcpy(pInfo[currNum].ipMask, pAdapter->IpAddressList.IpMask.String,
sizeof(pAdapter->IpAddressList.IpMask.String)); //网卡IP地址掩码
char macAddr[sizeof(pInfo[currNum].macAddr)];
memset(macAddr, 0, sizeof(macAddr));
sprintf(macAddr, "%02X-%02X-%02X-%02X-%02X-%02X", pAdapter->Address[0], pAdapter->Address[1],
pAdapter->Address[2], pAdapter->Address[3], pAdapter->Address[4], pAdapter->Address[5]);
memcpy(pInfo[currNum].macAddr, macAddr, sizeof(macAddr)); //网卡物理地址
if(currNum == adapterNum - 1) {
pInfo[currNum].next = NULL;
}
else {
pInfo[currNum].next = pInfo + (currNum + 1);
}
currNum++;
pAdapter = pAdapter->Next;
}
if(pAdapterInfo != NULL) {
free(pAdapterInfo);
pAdapterInfo = NULL;
pAdapter = NULL;
}
return 0;
}
else {
if(pAdapterInfo != NULL) {
free(pAdapterInfo);
pAdapterInfo = NULL;
}
printf("Call to tcpclient_getAdaptersInfo_1 failed.\n");
}
return -1;
}
/**
* @brief getAdapterState 获取网卡(网络适配器)的状态
* @param infoList 网卡(网络适配器)索引号
* @return int 0:正常 -1:网卡状态异常 -2:获取网卡状态失败
*/
int getAdapterState(unsigned long index)
{
MIB_IFROW info;
memset(&info, 0, sizeof(MIB_IFROW));
info.dwIndex = index;
if(GetIfEntry(&info) != NOERROR) {
printf("ErrorCode = %d\n", GetLastError());
return -2;
}
if(info.dwOperStatus == IF_OPER_STATUS_NON_OPERATIONAL || //局域网适配器禁用,例如地址冲突
info.dwOperStatus == IF_OPER_STATUS_UNREACHABLE || //WAN适配器未连接
info.dwOperStatus == IF_OPER_STATUS_DISCONNECTED || //局域网适配器:网线未插入 WAN适配器:无信号
info.dwOperStatus == IF_OPER_STATUS_CONNECTING) {
return -1;
}
else if(info.dwOperStatus == IF_OPER_STATUS_OPERATIONAL ||
info.dwOperStatus == IF_OPER_STATUS_CONNECTED) {
return 0;
}
}