Linux下C获取所有可用网卡信息

在Linux下开发网络程序时,经常会遇到需要取本地网络接口名、IP、广播地址、子网掩码或者MAC地址等信息的需求,最常见的办法是配合宏SIOCGIFHWADDR、SIOCGIFADDR、SIOCGIFBRDADDR与SIOCGIFNETMASK作为参数调用函数ioctl分别获得MAC地址、IP地址、广播地址与子网掩码来实现。一次性获取此类信息的C语言代码实现如下。

#include <stdio.h>
#include <string.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <errno.h>

int getLocalInfo(void)
{
    int fd;
    int interfaceNum = 0;
    struct ifreq buf[16];
    struct ifconf ifc;
    struct ifreq ifrcopy;
    char mac[16] = {0};
    char ip[32] = {0};
    char broadAddr[32] = {0};
    char subnetMask[32] = {0};

    if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        perror("socket");

        close(fd);
        return -1;
    }

    ifc.ifc_len = sizeof(buf);
    ifc.ifc_buf = (caddr_t)buf;
    if (!ioctl(fd, SIOCGIFCONF, (char *)&ifc))
    {
        interfaceNum = ifc.ifc_len / sizeof(struct ifreq);
        printf("interface num = %dn", interfaceNum);
        while (interfaceNum-- > 0)
        {
            printf("ndevice name: %sn", buf[interfaceNum].ifr_name);

            //ignore the interface that not up or not runing  
            ifrcopy = buf[interfaceNum];
            if (ioctl(fd, SIOCGIFFLAGS, &ifrcopy))
            {
                printf("ioctl: %s [%s:%d]n", strerror(errno), __FILE__, __LINE__);

                close(fd);
                return -1;
            }

            //get the mac of this interface  
            if (!ioctl(fd, SIOCGIFHWADDR, (char *)(&buf[interfaceNum])))
            {
                memset(mac, 0, sizeof(mac));
                snprintf(mac, sizeof(mac), "%02x%02x%02x%02x%02x%02x",
                    (unsigned char)buf[interfaceNum].ifr_hwaddr.sa_data[0],
                    (unsigned char)buf[interfaceNum].ifr_hwaddr.sa_data[1],
                    (unsigned char)buf[interfaceNum].ifr_hwaddr.sa_data[2],

                    (unsigned char)buf[interfaceNum].ifr_hwaddr.sa_data[3],
                    (unsigned char)buf[interfaceNum].ifr_hwaddr.sa_data[4],
                    (unsigned char)buf[interfaceNum].ifr_hwaddr.sa_data[5]);
                printf("device mac: %sn", mac);
            }
            else
            {
                printf("ioctl: %s [%s:%d]n", strerror(errno), __FILE__, __LINE__);
                close(fd);
                return -1;
            }

            //get the IP of this interface  

            if (!ioctl(fd, SIOCGIFADDR, (char *)&buf[interfaceNum]))
            {
                snprintf(ip, sizeof(ip), "%s",
                    (char *)inet_ntoa(((struct sockaddr_in *)&(buf[interfaceNum].ifr_addr))->sin_addr));
                printf("device ip: %sn", ip);
            }
            else
            {
                printf("ioctl: %s [%s:%d]n", strerror(errno), __FILE__, __LINE__);
                close(fd);
                return -1;
            }

            //get the broad address of this interface  

            if (!ioctl(fd, SIOCGIFBRDADDR, &buf[interfaceNum]))
            {
                snprintf(broadAddr, sizeof(broadAddr), "%s",
                    (char *)inet_ntoa(((struct sockaddr_in *)&(buf[interfaceNum].ifr_broadaddr))->sin_addr));
                printf("device broadAddr: %sn", broadAddr);
            }
            else
            {
                printf("ioctl: %s [%s:%d]n", strerror(errno), __FILE__, __LINE__);
                close(fd);
                return -1;
            }

            //get the subnet mask of this interface  
            if (!ioctl(fd, SIOCGIFNETMASK, &buf[interfaceNum]))
            {
                snprintf(subnetMask, sizeof(subnetMask), "%s",
                    (char *)inet_ntoa(((struct sockaddr_in *)&(buf[interfaceNum].ifr_netmask))->sin_addr));
                printf("device subnetMask: %sn", subnetMask);
            }
            else
            {
                printf("ioctl: %s [%s:%d]n", strerror(errno), __FILE__, __LINE__);
                close(fd);
                return -1;

            }
        }
    }
    else
    {
        printf("ioctl: %s [%s:%d]n", strerror(errno), __FILE__, __LINE__);
        close(fd);
        return -1;
    }

    close(fd);

    return 0;
}

int main(void)
{
    getLocalInfo();

    return 0;
}

使用ioctl函数虽然可以获取所有的信息,但是使用起来比较麻烦,如果不需要获取MAC地址,那么使用getifaddrs函数来获取更加方便与简洁。值得一提的是,在MacOS或iOS系统上(如iPhone程序开发),上述iotcl函数没法获得mac地址跟子网掩码,这个使用,使用getifaddrs函数便更有优势了。下面是使用getiaddrs函数获取网卡信息的C语言代码实现。

#include <stdio.h>  
#include <ifaddrs.h>  
#include <arpa/inet.h>  

int getSubnetMask()
{
    struct sockaddr_in *sin = NULL;
    struct ifaddrs *ifa = NULL, *ifList;

    if (getifaddrs(&ifList) < 0)
    {
        return -1;
    }

    for (ifa = ifList; ifa != NULL; ifa = ifa->ifa_next)
    {
        if(ifa->ifa_addr->sa_family == AF_INET)
        {
            printf("n>>> interfaceName: %sn", ifa->ifa_name);

            sin = (struct sockaddr_in *)ifa->ifa_addr;
            printf(">>> ipAddress: %sn", inet_ntoa(sin->sin_addr));

            sin = (struct sockaddr_in *)ifa->ifa_dstaddr;
            printf(">>> broadcast: %sn", inet_ntoa(sin->sin_addr));

            sin = (struct sockaddr_in *)ifa->ifa_netmask;
            printf(">>> subnetMask: %sn", inet_ntoa(sin->sin_addr));
        }
    }

    freeifaddrs(ifList);

    return 0;
}

int main(void)
{
    getSubnetMask();

    return 0;
}

ifaddrs结构体定义如下:

struct ifaddrs   
{   
    struct ifaddrs  *ifa_next;    /* Next item in list */   
    char            *ifa_name;    /* Name of interface */   
    unsigned int     ifa_flags;   /* Flags from SIOCGIFFLAGS */   
    struct sockaddr *ifa_addr;    /* Address of interface */   
    struct sockaddr *ifa_netmask; /* Netmask of interface */   
    union   
    {   
        struct sockaddr *ifu_broadaddr; /* Broadcast address of interface */   
        struct sockaddr *ifu_dstaddr; /* Point-to-point destination address */   
    } ifa_ifu;   
    #define              ifa_broadaddr ifa_ifu.ifu_broadaddr   
    #define              ifa_dstaddr   ifa_ifu.ifu_dstaddr   
    void            *ifa_data;    /* Address-specific data */   
};

ifa_next指向链表的下一个成员;ifa_name是接口名称,以0结尾的字符串,比如eth0,lo;ifa_flags是接口的标识位(比如当IFF_BROADCAST或IFF_POINTOPOINT设置到此标识位时,影响联合体变量ifu_broadaddr存储广播地址或ifu_dstaddr记录点对点地址);ifa_netmask存储该接口的子网掩码;结构体变量存储广播地址或点对点地址(见括弧介绍ifa_flags);ifa_data存储了该接口协议族的特殊信息,它通常是NULL(一般不关注他)。

函数getifaddrs(int getifaddrs (struct ifaddrs **__ifap))获取本地网络接口信息,将之存储于链表中,链表头结点指针存储于__ifap中带回,函数执行成功返回0,失败返回-1,且为errno赋值。
很显然,函数getifaddrs用于获取本机接口信息,比如最典型的获取本机IP地址。
  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 获取电脑可用wifi的代码可以使用Linux下的命令行工具iwlist。 下面是使用C语言调用iwlist命令获取可用wifi列表的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_BUF_SIZE 1024 int main() { FILE *fp; char buffer[MAX_BUF_SIZE]; char cmd[] = "iwlist scan | grep 'ESSID' | awk '{print $NF}' | sed 's/\\\"//g'"; fp = popen(cmd, "r"); if (fp == NULL) { printf("Failed to run command\n" ); exit(1); } while (fgets(buffer, MAX_BUF_SIZE, fp) != NULL) { buffer[strcspn(buffer, "\n")] = 0; printf("%s\n", buffer); } pclose(fp); return 0; } ``` 这个程序调用了Linux下的命令行工具iwlist来扫描可用的wifi列表,然后使用grep、awk和sed命令进行过滤和格式化输出。通过调用popen()函数来执行命令,并通过fgets()函数逐行读取输出结果。 输出的结果是一个wifi名称的列表,每个名称占一行,可以进一步处理或显示给用户。 ### 回答2: 获取Linux电脑可用WiFi的代码可以通过使用C语言Linux系统提供的API来实现。首先,需要包含相关的头文件。然后,使用SIOCGIFCONF命令获取网络接口列表,并遍历列表找到无线网络接口。 以下是一个示例代码片段: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <net/if.h> #include <netinet/in.h> #include <arpa/inet.h> int main() { int sockfd; struct ifconf ifconf; struct ifreq ifreqs[20]; // 用于存储网络接口信息 char buf[128]; // 用于存储接口名字 sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { perror("socket"); exit(1); } ifconf.ifc_len = sizeof(ifreqs); // 设置ifconf的长度 ifconf.ifc_buf = (caddr_t) ifreqs; // 设置ifconf的缓冲区 if (ioctl(sockfd, SIOCGIFCONF, &ifconf) == -1) { perror("ioctl"); exit(1); } struct ifreq* ifr = ifconf.ifc_req; int numInterfaces = ifconf.ifc_len / sizeof(struct ifreq); // 获取网络接口数量 for (int i = 0; i < numInterfaces; i++) { struct ifreq* item = &(ifr[i]); ioctl(sockfd, SIOCGIFFLAGS, item); // 获取接口的标志位 if (item->ifr_flags & IFF_UP) { // 如果接口处于UP状态 if (item->ifr_flags & IFF_RUNNING) { // 如果接口处于Running状态 strncpy(buf, item->ifr_name, sizeof(buf)-1); buf[sizeof(buf)-1] = '\0'; printf("WiFi接口名字: %s\n", buf); } } } close(sockfd); return 0; } ``` 上述代码通过socket和ioctl函数调用来获取网络接口的信息,并检查接口的标志位来确定是否处于可用状态。最后,输出可用WiFi接口的名称。 请注意,代码中的错误检查和错误处理可能需要根据实际情况进行精细调整。此外,由于Linux系统中的网络接口命名可能因发行版而异,所以在其他Linux发行版上可能需要进行适当的修改。 ### 回答3: 在Linux下,可以使用C语言编写代码来获取电脑可用的WiFi。以下是一个简单的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #define MAX_BUFFER_SIZE 1024 int main() { FILE *fp; char buffer[MAX_BUFFER_SIZE]; // 执行iwlist命令获取WiFi列表信息 fp = popen("iwlist wlan0 scan", "r"); if (fp == NULL) { printf("Error executing iwlist command\n"); return 1; } // 逐行读取输出结果并解析 while (fgets(buffer, sizeof(buffer), fp) != NULL) { // 查找关键字来获取WiFi名称和信号强度 if (strstr(buffer, "ESSID:") != NULL) { char *ssidStart = strchr(buffer, '\"'); if (ssidStart != NULL) { char *ssidEnd = strchr(ssidStart + 1, '\"'); if (ssidEnd != NULL) { *ssidEnd = '\0'; // 将双引号替换为字符串结束符 printf("WiFi名称:%s\n", ssidStart + 1); } } } if (strstr(buffer, "Signal level=") != NULL) { char *signalStart = strstr(buffer, "Signal level="); if (signalStart != NULL) { char *signalEnd = strchr(signalStart + 1, ' '); if (signalEnd != NULL) { *signalEnd = '\0'; // 将空格替换为字符串结束符 printf("信号强度:%s\n", signalStart + 13); } } } } // 关闭文件指针 pclose(fp); return 0; } ``` 请注意,此示例代码使用了`iwlist`命令来扫描WiFi,并解析输出结果来获取WiFi名称和信号强度。需要确保已安装`iwlist`命令,并根据实际的无线网卡接口名称进行修改(如`wlan0`)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值