在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 = ;
struct ifreq buf[];
struct ifconf ifc;
struct ifreq ifrcopy;
char mac[] = {};
char ip[] = {};
char broadAddr[] = {};
char subnetMask[] = {}; if ((fd = socket(AF_INET, SOCK_DGRAM, )) < )
{
perror("socket"); close(fd);
return -;
} 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-- > )
{
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 -;
} //get the mac of this interface
if (!ioctl(fd, SIOCGIFHWADDR, (char *)(&buf[interfaceNum])))
{
memset(mac, , sizeof(mac));
snprintf(mac, sizeof(mac), "%02x%02x%02x%02x%02x%02x",
(unsigned char)buf[interfaceNum].ifr_hwaddr.sa_data[],
(unsigned char)buf[interfaceNum].ifr_hwaddr.sa_data[],
(unsigned char)buf[interfaceNum].ifr_hwaddr.sa_data[], (unsigned char)buf[interfaceNum].ifr_hwaddr.sa_data[],
(unsigned char)buf[interfaceNum].ifr_hwaddr.sa_data[],
(unsigned char)buf[interfaceNum].ifr_hwaddr.sa_data[]);
printf("device mac: %sn", mac);
}
else
{
printf("ioctl: %s [%s:%d]n", strerror(errno), __FILE__, __LINE__);
close(fd);
return -;
} //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 -;
} //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 -;
} //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 -; }
}
}
else
{
printf("ioctl: %s [%s:%d]n", strerror(errno), __FILE__, __LINE__);
close(fd);
return -;
} close(fd); return ;
} int main(void)
{
getLocalInfo(); return ;
}

使用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) < )
{
return -;
} 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 ;
} int main(void)
{
getSubnetMask(); return ;
}

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

Linux下C获取所有可用网卡信息的更多相关文章

  1. Linux下java获取CPU、内存、磁盘IO、网络带宽使用率

    一.CPU 使用proc文件系统,"proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间.它以文件系统的方式为访问系统内核数据的操作提供接口.用户和应用程序可以通过proc得 ...

  2. 虚拟机Linux下一直获取不到ip怎么办

    虚拟机Linux下一直获取不到ip怎么办 Ifconfig -a 只显示了本地的ip127.0.0.1 和另一个eth1 但是找不到ip地址. 需要做的是: 申请ipdhclient eth1 另外释 ...

  3. linux下自动获取并安装软件包 apt-get 的命令介绍

    apt-cache search package    搜索包 apt-cache show package    获取包的相关信息,如说明.大小.版本等 sudo apt-get install p ...

  4. Linux下编程获取本地IP地址的常见方法

    转载于:http://blog.csdn.net/k346k346/article/details/48231933 在进行linux网络编程时,经常用到本机IP地址.本文罗列一下常见方法,以备不时之 ...

  5. Linux下"负载均衡+高可用"集群的考虑点 以及 高可用方案说明(Keepalive/Heartbeat)

    当下Linux运维技术越来越受到企业的关注和追捧, 在某些企业, 尤其是牵涉到电子商务和电子广告类的网站,通常会要求作负载均衡和高可用的Linux集群方案.那么如何实施Llinux集群架构,才能既有效 ...

  6. Linux下手动获取当前调用栈

    被问到如何手动获取当前的调用栈,之前碰到过一时没记起来,现在回头整理一下. 其原理是:使用backtrace()从栈中获取当前调用各层函数调用的返回地址,backtrace_symbols()将对应地 ...

  7. Linux下实现获取远程机器文件

    创建公钥秘钥实现无密码登录后即可获取到文件内容了!! A:xxx.xxx.6.xxx B:xxx.xxx.xxx.x 一.创建 A机器 ssh-keygen -t rsa 二.拷贝——将生成的公钥复制 ...

  8. Linux下Python获取IP地址

    <lnmp一键安装包>中需要获取ip地址,有2种情况:如果服务器只有私网地址没有公网地址,这个时候获取的IP(即私网地址)不能用来判断服务器的位置,于是取其网关地址用来判断服务器在国内还是 ...

  9. Linux下wget获取ftp下目录下文件

    如果某个目录下有一个文件可以使用ftp命令: get xxx 如果是某个目录下有多个文件(且不需要获取目录下子文件夹下的内容): mget * 如果是某个目录下有子目录希望获取所有子目录: wget ...

随机推荐

  1. 趣味js【练习题】

    1.无限极函数递归,使每次的参数相乘 需求:add(1)(2)(3)(4)(5) 1.1首先要知道一个东西,就是function每次调用,都会默认执行tosting 1.2利用递归,每次返回的都是函数 ...

  2. JS原生Date类型方法的一些冷知识

    ps:由于Date()是js原生函数,不同浏览器的解析器对其实现方式并不同,所以返回值也会有所区别.本文测试未特别申明浏览器的情况下,均是指win7 x64+chrome 44.0.2403.155 ...

  3. POJ 1597 Function Run Fun

    记忆化搜索. #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> ...

  4. USACO 控制公司 Controlling Companies

    友情链接神犇520的博客 题目: 题目描述 有些公司是其他公司的部分拥有者,因为他们获得了其他公司发行的股票的一部分.(此处略去一句废话)据说,如果至少满足了以下三个条件之一,公司A就可以控制公司B了 ...

  5. Python-函数总结

    把程序分解成较小的部分,主要有3种方法. 函数(function) 对象(object) 模块(module) 本节我们先学习函数.函数是带名字的代码块,可以把多个逻辑封装起来.这样就可以在程序中可以 ...

  6. HDU 6199gems gems gems (DP)

    gems gems gems Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  7. hp

    命令组成hpacucli [parameter=value] 查看: 查看所有控制器状态 hpacucli ctrl all show 查看slot 0阵列信息详细状态 (可以查看物理磁盘和逻辑磁盘的 ...

  8. hdu 4819 二维线段树模板

    /* HDU 4819 Mosaic 题意:查询某个矩形内的最大最小值, 修改矩形内某点的值为该矩形(Mi+MA)/2; 二维线段树模板: 区间最值,单点更新. */ #include<bits ...

  9. POJ3450 Corporate Identity

    后缀数组. 解决多个字符串的最长公共子串. 采用对长度的二分,将子串按height分组,每次判断是否在每个字符串中都出现过. 复杂度O(NlogN) By:大奕哥 #include<cstrin ...

  10. 51nod2000 四边形分割平面 规律题

    观察样例,$ans(1) = 1, ans(2) = 10$,再手推一组,$ans(3) = 26$ 可以发现规律$ans(n) = (2n - 1)^2 + 1$ 如果还是没看出规律,那么打个程序去 ...