有时候,总想验证一些奇怪的想法,干脆就写下来,以备后查。

想法:获取linux系统的网卡信息(1)网卡名称 (2)IPv4 (3)IPv6 (4)MAC地址 (5)是否回环地址 (6)是否物理网卡 (7)是否混杂模式 (8)发送字节数 (9)发送数据包数 (10)接收字节数 (11)接收数据包数;

1、在CentOS系统上,通过getifaddrs函数,可以获取 网卡名称、是否可用、是否混杂模式、IPv4、IPv6;但不能获取MAC地址,也无法判断是否虚拟网卡;

2、在iMacOS(FreeBSD)系统上,通过getifaddrs函数,可以获取 网卡名称、是否可用、是否混杂模式、IPv4、IPv6、MAC地址(AF_LINK);但无法判断是否虚拟网卡;

3、通过ioctl函数,可以获取 网卡名称、是否可用、是否混杂模式、IPv4、MAC地址;但不能获取IPv6,也无法判断是否虚拟网卡;

4、通过/proc/net/if_inet6,可以获取各个网卡的IPv6;

5、通过/sys/devices/virtual/net,可以获取各个虚拟网卡名称;

6、通过/proc/net/dev,可以获取各个网卡的流量;

// 获取linux下网卡信息;#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <string>
#include <arpa/inet.h>  /* for inet_ntop */
#include <net/if.h>       /* for ifconf */
#include <linux/sockios.h>    /* for net status mask */
#include <netinet/in.h>       /* for sockaddr_in */
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <dirent.h> /* for dirent opendir */
#include <ifaddrs.h> /* for getifaddrs */
#include <fstream> /* for ifstream */
#include <map>
#include <set>
#include <vector>#define BOOL2STR(value) (value ? "true" : "false")typedef struct _NETWORK_INTERFACE_CARD_INFO_
{std::string name;      // 网卡名称;std::string ipv4;      // IPv4地址;std::string ipv6;      // IPv6地址;std::string mac_addr;  // MAC地址;bool is_valid{ false };        // 是否可用;bool is_promisc{ false };      // 是否混杂模式;bool is_physical{ false };     // 是否物理网卡;bool is_loop{ false };         // 是否回环网卡;uint64_t send_bytes{ 0 };      // 发送字节数;uint64_t send_packets{ 0 };    // 发送数据包数;uint64_t recv_bytes{ 0 };      // 接收字节数;uint64_t recv_packets{ 0 };    // 接收数据包数;
}NETWORK_INTERFACE_CARD_INFO;// 获取虚拟网卡名称列表;
bool get_virtual_network_interface_card_name_list(std::set<std::string>& nic_names);// 获取指定网卡MAC地址;
std::string get_network_interface_card_mac_address(const std::string& nic_name);// 获取网卡基本信息;
// map_key : 网卡名称; map_value: 网卡基本信息;
bool get_network_interface_card_list(std::map<std::string, NETWORK_INTERFACE_CARD_INFO>& nics);// 获取网卡对应的数据流量;
bool get_network_interface_card_data_flow(std::map<std::string, NETWORK_INTERFACE_CARD_INFO>& nics);// 字符串切分
void easy_split(const std::string &str, const std::string &separator, std::vector<std::string> &result);int main(int argc, char* argv[])
{printf("hello from linux_ifconfig!\n");std::map<std::string, NETWORK_INTERFACE_CARD_INFO> nics;get_network_interface_card_list(nics);get_network_interface_card_data_flow(nics);for (const auto& item : nics) {const auto& nic = item.second;printf("--------------------------------\n");printf("name : %s\n", nic.name.c_str());printf("ipv4 : %s\n", nic.ipv4.c_str());printf("ipv6 : %s\n", nic.ipv6.c_str());printf("mac  : %s\n", nic.mac_addr.c_str());printf("valid : %s\n", BOOL2STR(nic.is_valid));printf("promisc : %s\n", BOOL2STR(nic.is_promisc));printf("physical : %s\n", BOOL2STR(nic.is_physical));printf("loop : %s\n", BOOL2STR(nic.is_loop));printf("send_bytes : %lu\n", nic.send_bytes);printf("send_packets : %lu\n",nic.send_packets);printf("recv_bytes : %lu\n", nic.recv_bytes);printf("recv_packets : %lu\n", nic.recv_packets);}return 0;
}// 获取虚拟网卡名称列表;
bool get_virtual_network_interface_card_name_list(std::set<std::string>& nic_names)
{DIR *dir = nullptr;struct dirent *dp = nullptr;if (!(dir = opendir("/sys/devices/virtual/net"))) {return false;}while ((dp = readdir(dir)) != nullptr) {if ((0 == strcmp(dp->d_name, ".")) || (0 == strcmp(dp->d_name, ".."))) {continue;}if (dp->d_type == DT_DIR) {nic_names.insert(dp->d_name);}}closedir(dir);return true;
}// 获取网卡MAC地址;
std::string get_network_interface_card_mac_address(const std::string& nic_name)
{int fd = socket(AF_INET, SOCK_DGRAM, 0);if (fd <= 0) {printf("socket failed. errno=%d, errstr=%s\n", errno, strerror(errno));return "";}struct ifreq nic;strcpy(nic.ifr_name, nic_name.c_str());int ret = ioctl(fd, SIOCGIFHWADDR, (char*)&nic);close(fd);if (ret < 0) {return "";}char mac_address[18] = { 0 };sprintf(mac_address, "%02x:%02x:%02x:%02x:%02x:%02x",(unsigned char)nic.ifr_hwaddr.sa_data[0],(unsigned char)nic.ifr_hwaddr.sa_data[1],(unsigned char)nic.ifr_hwaddr.sa_data[2],(unsigned char)nic.ifr_hwaddr.sa_data[3],(unsigned char)nic.ifr_hwaddr.sa_data[4],(unsigned char)nic.ifr_hwaddr.sa_data[5]);return mac_address;
}// 获取网卡基本信息;
// key : 网卡名称; value: 网卡基本信息
bool get_network_interface_card_list(std::map<std::string, NETWORK_INTERFACE_CARD_INFO>& nics)
{std::set<std::string> vnic_names;get_virtual_network_interface_card_name_list(vnic_names);struct ifaddrs* addrs = nullptr;int rv = getifaddrs(&addrs);if (rv != 0) {printf("getifaddrs failed. errno=%d, errstr=%s\n", errno, strerror(errno));return false;}struct ifaddrs *cur_addr = addrs;while (cur_addr != nullptr) {if (nics.count(cur_addr->ifa_name) == 0) {NETWORK_INTERFACE_CARD_INFO info;info.name = cur_addr->ifa_name;info.is_loop = (info.name == "lo");if (vnic_names.count(info.name) != 0) {info.is_physical = false;}else {info.is_physical = true;}nics[cur_addr->ifa_name] = info;}NETWORK_INTERFACE_CARD_INFO &info = nics[cur_addr->ifa_name];if (info.name.empty()) {info.name = cur_addr->ifa_name;}info.is_valid = (cur_addr->ifa_flags & IFF_UP) != 0;info.is_promisc = (cur_addr->ifa_flags & IFF_PROMISC) != 0;if (cur_addr->ifa_addr->sa_family == AF_INET) {void* tmpAddr = &((struct sockaddr_in*)cur_addr->ifa_addr)->sin_addr;char address[INET_ADDRSTRLEN] = { 0 };if (inet_ntop(AF_INET, tmpAddr, address, INET_ADDRSTRLEN) != nullptr) {info.ipv4 = address;}}if (cur_addr->ifa_addr->sa_family == AF_INET6) {void* tmpAddr = &((struct sockaddr_in6 *)(cur_addr->ifa_addr))->sin6_addr;char address[INET6_ADDRSTRLEN] = { 0 };if (inet_ntop(AF_INET6, tmpAddr, address, INET6_ADDRSTRLEN) != nullptr) {info.ipv6 = address;}}if (info.mac_addr.empty() && !info.is_loop) {info.mac_addr = get_network_interface_card_mac_address(info.name);}cur_addr = cur_addr->ifa_next;}freeifaddrs(addrs);return true;
}// 获取网卡对应的数据流量;
bool get_network_interface_card_data_flow(std::map<std::string, NETWORK_INTERFACE_CARD_INFO>& nics)
{std::ifstream ifs;ifs.open("/proc/net/dev");if (!ifs.is_open()) {return false;}std::string s;while (getline(ifs, s)) {if (s.find('|') != std::string::npos) {continue; // 去掉文件头;}std::vector<std::string> v;easy_split(s, " ", v);if (v.size() != 17) {break;}std::string nic_name = v[0].substr(0, v[0].length() - 1);if (nics.count(nic_name) != 0) {NETWORK_INTERFACE_CARD_INFO &info = nics[nic_name];info.recv_bytes = strtoll(v[1].c_str(), nullptr, 10);info.recv_packets = strtoll(v[2].c_str(), nullptr, 10);info.send_bytes = strtoll(v[9].c_str(), nullptr, 10);info.send_packets = strtoll(v[10].c_str(), nullptr, 10);}}return 0;
}void easy_split(const std::string &str, const std::string &separator, std::vector<std::string> &result)
{std::string::size_type pos1, pos2;size_t len = str.length();pos2 = str.find(separator);pos1 = 0;while (std::string::npos != pos2) {std::string substr = str.substr(pos1, pos2 - pos1);if (!substr.empty()) {result.emplace_back(substr);}pos1 = pos2 + separator.size();pos2 = str.find(separator, pos1);}if (pos1 != len) {std::string substr = str.substr(pos1);if (!substr.empty()) {result.emplace_back(substr);}}
}
构建命令
g++ main.cpp -std=c++11 -o linux-ifconfig

验证:获取linux系统的网卡信息相关推荐

  1. 获取 Linux 系统所有网卡信息

    功能介绍 获取 Linux 系统网卡数量(包括环回) 遍历每张网卡 打印网卡的 名称.MAC 地址.IP 地址.广播地址.子网掩码 源码 interface_info.c #include <s ...

  2. python相关linux_Python实现获取Linux系统基本信息

    Python实现获取Linux系统基本信息,获取信息如下: 主机名 系统版本 系统内核版本 总内存 CPU生厂商 CPU总核心数 服务器生厂商 服务器序列号 各网卡IP,MAC和网卡名信息 实现代码如 ...

  3. 使用Python获取Linux系统的各种信息

    From: http://www.jb51.net/article/52058.htm 这篇文章主要介绍了使用Python获取Linux系统的各种信息,例如系统类型.CPU信息.内存信息.块设备等,需 ...

  4. 获取linux系统序列号

    项目中需要获取服务器系统序列号,方法如下: /*** Method for get Linux Machine MotherBoard Serial Number** @return*/public ...

  5. 通过sysinfo获取Linux系统状态信息

      系统运行状态信息是我们关注的重点,通过当前系统的输出信息,如内存大小.进程数量.运行时间等,以便分析CPU负载.软硬件资源占用情况,确保系统高效和稳定.Linux系统中,提供sysinfo以获取相 ...

  6. 通过AD域验证登录Linux系统(Linux安装sssd加入Windows AD域)

    背景 有一台Centos 7 的Linux服务器,需要每个IT管理员都可以登录并进行维护,为了方便账户管理,统一认证,要求Linux服务器登录实现Windows AD域验证. 环境说明 AD域:Win ...

  7. 获取linux系统编码,Android获取IMEI码

    相比大家都知道,每部手机都有一个属于自己的字符串,这个字符串是全球唯一的:即使相同品牌,相同型号,它们彼此也不会雷同:这个码就是IEMI码. 有了IMEI码,我们就能很方便的区分出每一台机器,区分出机 ...

  8. linux怎么静态改为自动获取,Linux系统下设置静态IP或自动获取动态IP的简单方法...

    linux下为机器设置静态ip地址: 复制代码代码如下: vim /etc/sysconfig/network-scripts/ifcfg-eth0 修改这个文件内容如下形式: 复制代码代码如下: # ...

  9. linux系统查询网卡信息,Linux下如何查询电脑中的网卡详细信息呢?

    摘要: 下文讲述Linux操作系统下查看网卡详细信息的方法分享,如下所示: 实现环境: CentOS 实现思路: 使用ifconfig命令即可查看网卡信息,如下所示: [root@localhost ...

最新文章

  1. 单点登录系统用 8 张漫画就解释了
  2. 互联网1分钟 | 1009
  3. 树莓派AI视觉云台——3、树莓派系统的启动
  4. fft重叠帧_关于FFT实时频谱的几个基本概念 | 科创仪表局
  5. java slf4j日志级别_java - 在slf4j中设置运行时消息的日志级别 - 堆栈内存溢出
  6. Jenkins之Log Parse的使用
  7. 屏幕文字识别_手机长按屏幕2秒,能开启4个实用功能,一键提取图片上的文字...
  8. 怎么单选_第一届化妆品分类大赛丨用过的化妆刷、过期的口红…该怎么扔
  9. 关于STC-ISP软件程序烧录失败率高的解决办法
  10. Python3自然语言处理(5)——预处理
  11. Android实现QQ空间图片下拉变大效果(雷惊风)
  12. 程序计数器(PC ) 详解
  13. Minecraft 1.18.1、1.18.2模组开发 19.拼图结构建筑(JigSaw Structure)
  14. js实现点击切换checkbox背景图片
  15. 前端参数无法转为后端实体内部类_javaweb实现自动将前端的属性值(HttpServletRequest)转化为后台对应的实体类...
  16. Matlab入门基础详解
  17. FFmpeg MP4 m3u8 视频 相互转换
  18. 离散数学·集合论【自然数和基数】
  19. oracle日常运维
  20. 利用P2P技术做自有视频点播系统的加速,还需要和CDN一样部署很多服务器吗?

热门文章

  1. Java 获取指定日期
  2. 2022最常用且好用的IDEA插件
  3. 如何实现学生评语的导入
  4. 案例分析:回归-克里金方法生成气温表面图(1)
  5. Golang type assertion 类型断言
  6. 干净彻底的卸载MySQL
  7. CentOS6.5下使用NetHogs监控进程网络使用情况
  8. 圣思园——Java SE Lesson 6
  9. Java学习之路-----Java基础简介,基础语法,Java标识符,修饰符,关键字与注释
  10. java怎么在控制台输入数字,并保存到数组里?