内容简介:我想获得连接到我的计算机的所有NIC的以下详细信息:1)接口名称(例如eth0)2)如果Linux中存在这样的东西,则接口号(如
我想获得连接到我的计算机的所有NIC的以下详细信息:
1)接口名称(例如eth0)
2)如果 Linux 中存在这样的东西,则接口号(如 Windows )
3)NIC带宽容量和模式(例如1Gb / s全双工)
getifaddrs()
/ freeifaddrs()
获取所有接口的链接列表,然后使用ioctl(fd,SIOCGIFINDEX,struct ifreq *)获取每个接口的接口索引.由于接口是连续的并且总是列出(无论它们是否为(活动)),我选择使用ioctl(fd,SIOCGIFNAME,struct ifreq *)来循环枚举它们.在所有情况下,fd都是AF_INET套接字.
要获得接口的双工和速度,需要使用ioctl(fd,SIOCETHTOOL,struct ifreq *),ifr_data指向具有cmd = ETHTOOL_GSET的struct ethtool_cmd.
如果失败则ioctls应该返回-1,如果成功则返回非负值(零,我相信).
这是一个示例程序:
#include <unistd.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <netinet/ip.h> #include <net/if.h> #include <linux/ethtool.h> #include <linux/sockios.h> #include <string.h> #include <errno.h> #include <stdio.h> struct interface { int index; int flags; /* IFF_UP etc. */ long speed; /* Mbps; -1 is unknown */ int duplex; /* DUPLEX_FULL, DUPLEX_HALF, or unknown */ char name[IF_NAMESIZE + 1]; }; static int get_interface_common(const int fd, struct ifreq *const ifr, struct interface *const info) { struct ethtool_cmd cmd; int result; /* Interface flags. */ if (ioctl(fd, SIOCGIFFLAGS, ifr) == -1) info->flags = 0; else info->flags = ifr->ifr_flags; ifr->ifr_data = (void *)&cmd; cmd.cmd = ETHTOOL_GSET; /* "Get settings" */ if (ioctl(fd, SIOCETHTOOL, ifr) == -1) { /* Unknown */ info->speed = -1L; info->duplex = DUPLEX_UNKNOWN; } else { info->speed = ethtool_cmd_speed(&cmd); info->duplex = cmd.duplex; } do { result = close(fd); } while (result == -1 && errno == EINTR); if (result == -1) return errno; return 0; } int get_interface_by_index(const int index, struct interface *const info) { int socketfd, result; struct ifreq ifr; if (index < 1 || !info) return errno = EINVAL; socketfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); if (socketfd == -1) return errno; ifr.ifr_ifindex = index; if (ioctl(socketfd, SIOCGIFNAME, &ifr) == -1) { do { result = close(socketfd); } while (result == -1 && errno == EINTR); return errno = ENOENT; } info->index = index; strncpy(info->name, ifr.ifr_name, IF_NAMESIZE); info->name[IF_NAMESIZE] = '\0'; return get_interface_common(socketfd, &ifr, info); } int get_interface_by_name(const char *const name, struct interface *const info) { int socketfd, result; struct ifreq ifr; if (!name || !*name || !info) return errno = EINVAL; socketfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); if (socketfd == -1) return errno; strncpy(ifr.ifr_name, name, IF_NAMESIZE); if (ioctl(socketfd, SIOCGIFINDEX, &ifr) == -1) { do { result = close(socketfd); } while (result == -1 && errno == EINTR); return errno = ENOENT; } info->index = ifr.ifr_ifindex; strncpy(info->name, name, IF_NAMESIZE); info->name[IF_NAMESIZE] = '\0'; return get_interface_common(socketfd, &ifr, info); } int main(int argc, char *argv[]) { struct interface iface; int arg; int status = 0; if (argc > 1 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))) { fprintf(stderr, "\n"); fprintf(stderr, "Usage: %s { -h | --help }\n", argv[0]); fprintf(stderr, " %s\n", argv[0]); fprintf(stderr, " %s INTERFACE ...\n", argv[0]); fprintf(stderr, "\n"); return 1; } if (argc > 1) { for (arg = 1; arg < argc; arg++) { if (get_interface_by_name(argv[arg], &iface) != 0) { fprintf(stderr, "%s: No such interface.\n", argv[arg]); status = 1; continue; } printf("%s: Interface %d", iface.name, iface.index); if (iface.flags & IFF_UP) printf(", up"); if (iface.duplex == DUPLEX_FULL) printf(", full duplex"); else if (iface.duplex == DUPLEX_HALF) printf(", half duplex"); if (iface.speed > 0) printf(", %ld Mbps", iface.speed); printf("\n"); } } else { for (arg = 1; ; arg++) { if (get_interface_by_index(arg, &iface) != 0) break; printf("%s: Interface %d", iface.name, iface.index); if (iface.flags & IFF_UP) printf(", up"); if (iface.duplex == DUPLEX_FULL) printf(", full duplex"); else if (iface.duplex == DUPLEX_HALF) printf(", half duplex"); if (iface.speed > 0) printf(", %ld Mbps", iface.speed); printf("\n"); } } return status; }
如果将上面保存为iflist.c,则可以使用它进行编译
gcc -W -Wall -O3 iflist.c -o iflist
要查看用法,请运行iflist -h.要列出所有接口,请运行它而不带参数:
./iflist
以上将使用我描述的枚举方法.要仅列出特定接口,请运行命名接口:
./iflist eth0 lo
当然,仅为以太网接口列出双工和速度.
编辑添加:
如果上述程序没有为接口提供带宽和模式,这里有一个简化版本,它报告确切原因(错误).这个接口名称作为命令行参数;它没有枚举接口.
#include <unistd.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <netinet/ip.h> #include <net/if.h> #include <linux/ethtool.h> #include <linux/sockios.h> #include <string.h> #include <errno.h> #include <stdio.h> int ethernet_interface(const char *const name, int *const index, int *const speed, int *const duplex) { struct ifreq ifr; struct ethtool_cmd cmd; int fd, result; if (!name || !*name) { fprintf(stderr, "Error: NULL interface name.\n"); fflush(stderr); return errno = EINVAL; } if (index) *index = -1; if (speed) *speed = -1; if (duplex) *duplex = -1; fd = socket(AF_INET, SOCK_STREAM, 0); if (fd == -1) { const int err = errno; fprintf(stderr, "%s: Cannot create AF_INET socket: %s.\n", name, strerror(err)); fflush(stderr); return errno = err; } strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); ifr.ifr_data = (void *)&cmd; cmd.cmd = ETHTOOL_GSET; if (ioctl(fd, SIOCETHTOOL, &ifr) < 0) { const int err = errno; do { result = close(fd); } while (result == -1 && errno == EINTR); fprintf(stderr, "%s: SIOCETHTOOL ioctl: %s.\n", name, strerror(err)); return errno = err; } if (speed) *speed = ethtool_cmd_speed(&cmd); if (duplex) switch (cmd.duplex) { case DUPLEX_HALF: *duplex = 0; break; case DUPLEX_FULL: *duplex = 1; break; default: fprintf(stderr, "%s: Unknown mode (0x%x).\n", name, cmd.duplex); fflush(stderr); *duplex = -1; } if (index && ioctl(fd, SIOCGIFINDEX, &ifr) >= 0) *index = ifr.ifr_ifindex; do { result = close(fd); } while (result == -1 && errno == EINTR); if (result == -1) { const int err = errno; fprintf(stderr, "%s: Error closing socket: %s.\n", name, strerror(err)); return errno = err; } return 0; } int main(int argc, char *argv[]) { int arg, speed, index, duplex; if (argc < 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { fprintf(stderr, "\n"); fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv[0]); fprintf(stderr, " %s INTERFACE ...\n", argv[0]); fprintf(stderr, "\n"); return 0; } for (arg = 1; arg < argc; arg++) { if (ethernet_interface(argv[arg], &index, &speed, &duplex)) return 1; if (index == -1) printf("%s: (no interface index)", argv[arg]); else printf("%s: interface %d", argv[arg], index); if (speed == -1) printf(", unknown bandwidth"); else printf(", %d Mbps bandwidth", speed); if (duplex == 0) printf(", half duplex.\n"); else if (duplex == 1) printf(", full duplex.\n"); else printf(", unknown mode.\n"); } return 0; }
有问题吗?
翻译自:https://stackoverflow.com/questions/14264371/how-to-get-nic-details-from-a-c-program
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- dotnet 获取程序所在路径的方法
- Golang:通过小程序获取微信 openid
- 微信小程序与公众号获取openId的不同
- 微信小程序获取用户的 OpenId (附前端代码)
- express获取微信小程序二维码小记
- 小程序登录及用户信息和手机号的获取
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Java语言精粹
Jim Waldo / 王江平 / 电子工业出版社 / 2011-6 / 39.00元
这是一本几乎只讲java优点的书。 Jim Waldo先生是原sun微系统公司实验室的杰出工程师,他亲历并参与了java从技术萌生、发展到崛起的整个过程。在这《java语言精粹》里,jim总结了他所认为的java语言及其环境的诸多精良部分,包括:类型系统、异常处理、包机制、垃圾回收、java虚拟机、javadoc、集合、远程方法调用和并发机制。另外,他还从开发者的角度分析了在java技术周围......一起来看看 《Java语言精粹》 这本书的介绍吧!