1. 程式人生 > >Linux下C獲取所有可用網絡卡資訊

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地址。

相關推薦

LinuxC獲取所有可用資訊

在Linux下開發網路程式時,經常會遇到需要取本地網路介面名、IP、廣播地址、子網掩碼或者MAC地址等資訊的需求,最常見的辦法是配合巨集SIOCGIFHWADDR、SIOCGIFADDR、SIOCGIFBRDADDR與SIOCGIFNETMASK作為引數呼叫函式

C# 獲取本機資訊、個數、描述資訊、型別、速度等

程式碼比較簡單,直接上圖上碼。實現程式碼有註釋,以下是該例子的完整程式碼。引入名稱空間:using System.Net.NetworkInformation; using System.Net;完整程式碼:namespace NetworkInterfaceExample

c++獲取本機資訊(IP,MAC,閘道器,子掩碼)

int getIP_Mac_GateMac(int adapter, char** ip, int mac[6], int gateMac[6]) //adapter:選擇的網絡卡序號 {//PIP_ADAPTER_INFO結構體指標儲存本機網絡卡資訊PIP_ADAPT

LinuxC語言的socket編程

網絡編程 服務器 enter 編程 scanf 路由 client p s drl Server.c 1 #include <sys/types.h> 2 #include <sys/socket.h> 3 #include <n

linux程式設計獲取本機資訊

轉自:https://blog.csdn.net/shaderdx/article/details/78403437 ifaddrs結構體定義如下: struct ifaddrs    {      &

linux如何實現為一個繫結多個IP地址

Linux的網路裝置配置檔案存放在/etc/sysconfig/network-scripts裡面,對於乙太網的第一個網路裝置,配置檔名一般為 ifcfg-eth0 如果需要為第一個網路裝置繫結多一個IP地址,只需要在/

Linux 小米WIFI 的無線驅動

在小米的罈子裡看到了大神發的 小米WIFI 驅動 for Linux。於是就下載下來為自己的linux(Fedora 21 ,  kernel:3.17.8-300 )安裝小米WIFI 驅動。 過程記錄如下(其實也適用於 小度WIFI 和 360 WIFI ,只要用的是晶

linux中使用ifconfig命令檢視資訊時顯示為eth1,但是在network-scripts中只有ifcfg-eth0的配置檔案,並且裡面的NAME="eth0"

除了題目中的問題,其實在執行命令:service network restart時,會報錯: 解決辦法: 首先需要修改70-persistent-net.rules檔案: vim /etc/udev/rules.d/70-persistent-net.rules 然

linux中使用ifconfig命令檢視資訊時顯示為eth1,但是在network-scripts中只有ifcfg-eth0的配置檔案,並且裡面的NAME="eth0"。

除了題目中的問題,其實在執行命令:service network restart時,會報錯:  解決辦法: 首先需要修改70-persistent-net.rules檔案: vim /etc/udev/rules.d/70-persistent-net.rules 然後修改ifcfg-eth0檔案: v

C/C++:Windows程式設計—程式碼獲取本地所有資訊描述,IP地址,子掩碼,MAC地址)

先看效果 看程式碼 使用 GetAdaptersInfo 函式獲取網絡卡的所有資訊。 MSDN函式說明 https://docs.microsoft.com/en-us/windows/desktop/api/iphlpapi/nf-iphlpapi-getadapters

Linux利用ioctl函式獲取資訊

linux下的ioctl函式原型如下: #include <sys/ioctl.h> int ioctl(int handle, int cmd, [int *argc, int argv]) 函式成功返回0,失敗返回-1. 其相關命令介面如下:

linux通過c語言介面獲取資訊

方法一 通過ioctl的SIOCGIFCONF 例項1. 檢查特定的網絡卡是否存在 // ppp、wifi是否正常 static int check_ppp_wifi (int wifi_switch) { struct ifreq ifr

Linux用netstat查看狀態、端口狀態

服務端 哪些 ipv4 foreign udp協議 nat 進行 ets 當我 在linux一般使用netstat 來查看系統端口使用情況步。 netstat命令是一個監控TCP/IP網絡的非常有用的工具,它可以顯示路由表、實際的網絡連接以及每一個網絡接口設備的

linuxC獲取文件的大小

錯誤代碼 返回 system sys string 文件系統 識別碼 連接 chm 獲取文件大小這裏有兩種方法: 方法一、 範例: unsigned long get_file_size(const char *path) { unsigned lo

c# 多 由【網路介面卡名】獲取資訊,IP

c# 多網絡卡 由【網路介面卡名】獲取網絡卡資訊,IP 多網絡卡電腦中,網路介面卡的名字 多樣化! 專案中需要,根據網路介面卡 名字 獲取 單個網絡卡的IP: using System.Net.NetworkInformation;

Centos&Redhatbcm43142博通無線linux驅動之二

上次通過更換核心實現成功編譯驅動無線網絡卡,但是啟動到系統原核心下依然沒有bcm43142的驅動,遂準備在原核心下編譯驅動,記錄一下 ps:更推薦這種方法,避免因更換核心出現其他相容性問題 1.準備驅動包 hybrid-v35_64-nodebug-pcoem-6_30_223_271.tar.gz 點我下載

linuxC獲取系統時間的方法

asctime(將時間和日期以字串格式表示)   相關函式  time,ctime,gmtime,localtime   表頭檔案  #include<time.h>   定義函式  char * asctime(const struct tm * ti

linux中讀取資訊(ip, mask, mac)以及判斷物理網線是否插好的C程式---我親自試了一下,還不錯!

      說明: 我主要轉載如下兩篇文章, 但本文中加入了自己的一些描述       轉載地址一:http://blog.chinaunix.net/uid-20692625-id-3172833.html       轉載地址二:http://blog.chinaun

Linux系統關閉防火牆和檢視的命令

1.關閉防火牆   1)檢視防火牆狀態:service firewalld status 2)臨時關閉防火牆:service firewalld stop   3)檢視防火牆自啟動狀態:chkconfig firewalld 4)關閉防火牆自啟動:chkconfi

Linux c獲取當前時間(精確到秒和毫秒或者微秒)

獲取當前的時間的秒數和微秒數本方法需要用到gettimeofday()函式,該函式需要引入的標頭檔案是sys/time.h 。 函式說明int gettimeofday (struct timeval * tv, struct timezone * tz)