当前位置: 首页 > news >正文

Linux C 获取主机网卡名及 IP 的几种方法

  在进行 Linux 网络编程时,经常会需要获取本机 IP 地址,除了常规的读取配置文件外,本文罗列几种个人所知的编程常用方法,仅供参考,如有错误请指出。

方法一:使用 ioctl() 获取本地 IP 地址

  Linux 下可以使用 ioctl() 函数以及结构体 struct ifreq 和结构体struct ifconf 来获取网络接口的各种信息。具体过程是先通过 ictol 获取本地所有接口的信息保存到 ifconf 结构中,再从其中取出每个 ifreq 表示的接口信息。

如果本机的 IP 地址绑定在第一块网卡上,则只需指定网卡名称,无需获取所有网卡的信息即可获取,见如下函数:

int get_localip(const char * eth_name, char *local_ip_addr)
{int ret = -1;register int fd;struct ifreq ifr;if (local_ip_addr == NULL || eth_name == NULL){return ret;}if ((fd=socket(AF_INET, SOCK_DGRAM, 0)) > 0){strcpy(ifr.ifr_name, eth_name);if (!(ioctl(fd, SIOCGIFADDR, &ifr))){ret = 0;strcpy(local_ip_addr, inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));}}if (fd > 0){close(fd);}return ret;
}

如果想通过获取所有网络接口信息,示例代码如下:

#include <stdio.h>
#include <net/if.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <netinet/in.h>int get_localip(const char * eth_name, char *local_ip_addr)
{int ret = -1;register int fd, intrface;struct ifreq ifr[32];struct ifconf ifc;if (local_ip_addr == NULL || eth_name == NULL){return ret;}if ((fd=socket(AF_INET, SOCK_DGRAM, 0)) > 0){ifc.ifc_len = sizeof ifr;ifc.ifc_buf = (caddr_t)ifr;if (!ioctl(fd, SIOCGIFCONF, (char*)&ifc)) //获取所有接口信息{intrface = ifc.ifc_len / sizeof(struct ifreq);while (intrface-- > 0){//Get IP Addressif (!(ioctl(fd, SIOCGIFADDR, (char*)&ifr[intrface]))){if(strcmp(eth_name, ifr[intrface].ifr_name) == 0){ret = 0;sprintf(local_ip_addr, "%s", inet_ntoa(((struct sockaddr_in*)(&ifr[intrface].ifr_addr))->sin_addr));break;}}}}}if (fd > 0){close(fd);}return ret;
}int main(int argc, const char **argv)
{int ret;char local_ip[20] = {0};ret = get_localip("eth0", local_ip);if (ret == 0){printf("local ip:%s\n", local_ip);}else{printf("get local ip failure\n");}return 0;
}

方法二:getsockname() 获取本地 IP 地址

  getsockname()用于获取一个已捆绑或已连接套接字的本地地址。若一个套接字与 INADDR_ANY 捆绑,也就是说该套接字可以用任意主机的地址,此时除非调用 connect()accept() 来连接,否则 getsockname() 将不会返回主机 IP 地址的任何信息。

示例代码:

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>#define PORT 80
#define SERVER_IP "192.168.10.31"int main(int argc, const char **argv)
{int ret = -1;socklen_t len;char buf[30] = {0};struct sockaddr_in server_addr, local_addr;int fd = socket(AF_INET, SOCK_STREAM, 0);//int fd = socket(AF_INET, SOCK_DGRAM, 0);if (fd <= 0){printf("fail to creat socket\n");return -1;}memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port   = htons(PORT);server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);if(connect(fd, (struct sockaddr*)&server_addr, sizeof(server_addr))<0){printf("connect error!!!\n");goto end;}len = sizeof(local_addr);memset(&local_addr,  0, sizeof(local_addr));ret = getsockname(fd, (struct sockaddr*)&local_addr, &len);if (ret == 0){printf("local ip is %s, local port is %d\n", inet_ntop(AF_INET, &local_addr.sin_addr, buf, sizeof(buf)), ntohs(local_addr.sin_port));}else{printf("getsockname failed, error=%d\n", errno);}end:if (fd){close(fd);}return ret;
}

方法三:getaddrinfo() 获取本地 IP 地址

  getaddrinfo() 可以完成网络主机中主机名和服务名到地址的映射,但是一般不能用来获取本地 IP 地址,当它用来获取本地 IP 地址时,返回的一般是 127.0.0.1 本地回环地址,且该函数仅仅支持 IPv4

示例代码:

#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h>// 获取本地IP时,一般都是127.0.0.1
int main(int argc, const char **argv)
{int ret;char host_name[128] = {0};struct addrinfo *res, *cur;struct sockaddr_in *addr;if (gethostname(host_name, sizeof(host_name)) < 0){printf("gethostname error\n");return -1;}ret = getaddrinfo(host_name, NULL, NULL, &res);if (ret != 0){printf("Error: error in getaddrinfo on hostname: %s\n", gai_strerror(ret));return -1;}for(cur = res; cur != NULL; cur = cur->ai_next){if(cur->ai_family == AF_INET){addr = (struct sockaddr_in*)cur->ai_addr;printf("local ip:%s\n", inet_ntoa(addr->sin_addr));}//char host[1024] = {0};//ret = getnameinfo(cur->ai_addr, cur->ai_addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST);//if(ret != 0)//{//	printf("getnameinfo: %s\n", gai_strerror(ret));//}//else//{//	printf("ip: %s\n", host);//}}freeaddrinfo(res);return 0;
}

方法四:gethostbyname() 获取本地 IP 地址

  gethostbyname()getaddrinfo() 的功能类似,一般用于通过主机名或者服务名,比如域名来获取主机的 IP 地址。但是要想获取本地 IP 地址的时候,一般获取的是回环地址 127.0.0.1

示例代码:

#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h>// 获取本地IP时,一般都是127.0.0.1
int main(int argc, const char **argv)
{int i = 0;char host_name[128] = {0};struct hostent *hptr;if (gethostname(host_name, sizeof(host_name)) < 0){printf("gethostname error\n");return -1;}if ((hptr=gethostbyname(host_name)) == NULL){printf("gethostbyname error\n");return -1;}while(hptr->h_addr_list[i] != NULL){printf("hostname: %s\n", hptr->h_name);printf("      ip: %s\n", inet_ntoa(*(struct in_addr*)hptr->h_addr_list[i]));i++;}return 0;
}

方法五:通过 getifaddrs() 获取本地 IP 地址

代码来自StackOverflow:http://stackoverflow.com/questions/212528/linux-c-get-the-ip-address-of-local-computer

这里解释一下代码中的 INET_ADDRSTRLENINET6_ADDRSTRLEN ,该宏变量是定义在 netinet/in.h 头文件中:

// FILE: netinet/in.h#define INET_ADDRSTRLEN 16 /* for IPv4 dotted-decimal */#define INET6_ADDRSTRLEN 46 /* for IPv6 hex string */

示例代码:

#include <stdio.h>
#include <sys/types.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>int main (int argc, const char * argv[])
{struct ifaddrs * ifAddrStruct=NULL;struct ifaddrs * ifa=NULL;void * tmpAddrPtr=NULL;getifaddrs(&ifAddrStruct);for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next){if (!ifa->ifa_addr){continue;}if (ifa->ifa_addr->sa_family == AF_INET) // check it is IP4{// is a valid IP4 AddresstmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;char addressBuffer[INET_ADDRSTRLEN];inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer);}else if (ifa->ifa_addr->sa_family == AF_INET6) // check it is IP6{// is a valid IP6 AddresstmpAddrPtr=&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;char addressBuffer[INET6_ADDRSTRLEN];inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer);}}if (ifAddrStruct!=NULL){freeifaddrs(ifAddrStruct);}return 0;
}

方法六:通过 popen() 调用 ifconfig 获取本地 IP 地址

  用popen() 建立一个管道,管道的一端执行命令 ifconfig,管道的另一端读取收到的数据并进行相应的解析。这种方法需要执行 shell 命令,配合正则表达式,效率较低,一般不采用。而这种方式其实更倾向于配置,原因就是使用简单。

示例代码:

#include <stdio.h>
#include <stdlib.h>#define ETH_NAME	"ens33"int main(int argc, const char *argv[])
{FILE *fp;char buf[256] = {0};char command[256] = {0};//char *fmt = "ifconfig %s|sed -n '2p'|sed -n 's#^.*dr:##gp'|sed -n 's#B.*$##gp'";char *fmt = "ifconfig %s|grep 'inet addr'|awk '{ print $2}' | awk -F: '{print $2}'";snprintf(command, sizeof(command), fmt, ETH_NAME);if((fp = popen(command, "r")) == NULL){perror("Fail to popen\n");return -1;}while(fgets(buf, sizeof(buf), fp) != NULL){printf("%s", buf);}pclose(fp);return 0;
}

参考文章

[1] https://blog.csdn.net/bailyzheng/article/details/7489656
[2] https://blog.csdn.net/k346k346/article/details/48231933
[3] https://blog.csdn.net/zhongmushu/article/details/89944990

相关文章:

Linux C 获取主机网卡名及 IP 的几种方法

在进行 Linux 网络编程时&#xff0c;经常会需要获取本机 IP 地址&#xff0c;除了常规的读取配置文件外&#xff0c;本文罗列几种个人所知的编程常用方法&#xff0c;仅供参考&#xff0c;如有错误请指出。 方法一&#xff1a;使用 ioctl() 获取本地 IP 地址 Linux 下可以使用…...

解密外接显卡:笔记本能否接外置显卡?如何连接外接显卡?

伴随着电脑游戏和图形处理的需求不断增加&#xff0c;很多笔记本电脑使用者开始考虑是否能够通过外接显卡来提升性能。然而&#xff0c;外接显卡对于笔记本电脑是否可行&#xff0c;以及如何连接外接显卡&#xff0c;对于很多人来说仍然是一个迷。本文将为您揭秘外接显卡的奥秘…...

list与erase()

运行代码&#xff1a; //list与erase() #include"std_lib_facilities.h" //声明Item类 struct Item {string name;int iid;double value;Item():name(" "),iid(0),value(0.0){}Item(string ss,int ii,double vv):name(ss),iid(ii),value(vv){}friend istr…...

Arcgis 分区统计majority参数统计问题

利用Arcgis 进行分区统计时&#xff0c;需要统计不同矢量区域中栅格数据的众数&#xff08;majority&#xff09;&#xff0c;出现无法统计majority参数问题解决 解决&#xff1a;利用copy raster工具&#xff0c;将原始栅格数据 64bit转为16bit...

vue2+wangEditor5富文本编辑器(图片视频自定义上传七牛云/服务器)

1、安装使用 安装 yarn add wangeditor/editor # 或者 npm install wangeditor/editor --save yarn add wangeditor/editor-for-vue # 或者 npm install wangeditor/editor-for-vue --save在main.js中引入样式 import wangeditor/editor/dist/css/style.css在使用编辑器的页…...

shell脚本练习--安全封堵脚本,使用firewalld实现

一.什么是安全封堵 安全封堵&#xff08;security hardening&#xff09;是指采取一系列措施来增强系统的安全性&#xff0c;防止潜在的攻击和漏洞利用。以下是一些常见的安全封堵措施&#xff1a; 更新和修补系统&#xff1a;定期更新操作系统和软件包以获取最新的安全补丁和修…...

双端冒泡排序

双端冒泡排序是对传统冒泡排序的改进&#xff0c;其主要改进在于同时从两端开始排序&#xff0c;相对于传统冒泡排序每次只从一端开始排序&#xff0c;这样可以减少排序的遍历次数。 传统冒泡排序从一端开始&#xff0c;每次将最大&#xff08;或最小&#xff09;的元素冒泡到…...

如何在Visual Studio Code中用Mocha对TypeScript进行测试

目录 使用TypeScript编写测试用例 在Visual Studio Code中使用调试器在线调试代码 首先&#xff0c;本文不是一篇介绍有关TypeScript、JavaScript或其它编程语言数据结构和算法的文章。如果你正在准备一场面试&#xff0c;或者学习某一个课程&#xff0c;互联网上可以找到许多…...

GO中Json的解析

一个json字串&#xff0c;想要拿到其中的数据&#xff0c;就需要解析出来 一、适用于json数据的结构已知的情况下 使用json.Unmarshal将json数据解析到结构体中 根据json字串数据的格式定义struct&#xff0c;用来保存解码后的值。这里首先定义了一个与要解析的数据结构一样的…...

chatgpt 提示词-关于数据科学的 75个词语

这里有 75 个 chatgpt 提示&#xff0c;可以立即将其用于数据科学或数据分析等。 1. 伪装成一个SQL终端 提示&#xff1a;假设您是示例数据库前的 SQL 终端。该数据库包含名为“用户”、“项目”、“订单”、“评级”的表。我将输入查询&#xff0c;您将用终端显示的内容进行…...

(自控原理)控制系统的数学模型

目录 一、时域数学模型 1、线性元件微分方程的建立 2、微分方程的求解方法​编辑 3、非线性微分方程的线性化 二、复域数学模型 1、传递函数的定义 2、传递函数的标准形式 3、系统的典型环节的传递函数 4、传递函数的性质 5、控制系统数学模型的建立 6、由传递函数求…...

Webpack5 cacheGroups

文章目录 一、 cacheGroups是什么&#xff1f;二、怎么使用cacheGroups&#xff1f;三、cacheGroups实际应用之一&#xff1f; 一、 cacheGroups是什么&#xff1f; 在Webpack 5中&#xff0c;cacheGroups是用于配置代码拆分的规则&#xff0c;它可以帮助你更细粒度地控制生成…...

前端面试的游览器部分(5)每篇10题

41.什么是浏览器的同步和异步加载脚本的区别&#xff1f;你更倾向于使用哪种方式&#xff0c;并解释原因。 浏览器的同步和异步加载脚本是两种不同的脚本加载方式&#xff0c;它们的主要区别在于加载脚本时是否阻塞页面的解析和渲染。 同步加载脚本&#xff1a; 同步加载脚本…...

数据挖掘七种常用的方法汇总

数据挖掘(Data Mining)就是从大量的、不完全的、有噪声的、模糊的、随机的实际应用数据中&#xff0c;提取隐含在其中的、人们事先不知道的、但又是潜在有用的信息和知识的过程。这个定义包括几层含义&#xff1a;数据源必须是真实的、大量的、含噪声的&#xff1b;发现的是用户…...

自然语言处理学习笔记(二)————语料库与开源工具

目录 1.语料库 2.语料库建设 &#xff08;1&#xff09;规范制定 &#xff08;2&#xff09;人员培训 &#xff08;3&#xff09;人工标注 3.中文处理中的常见语料库 &#xff08;1&#xff09;中文分词语料库 &#xff08;2&#xff09;词性标注语料库 &#xff08;3…...

Rust dyn - 动态分发 trait 对象

dyn - 动态分发 trait 对象 dyn是关键字&#xff0c;用于指示一个类型是动态分发&#xff08;dynamic dispatch&#xff09;&#xff0c;也就是说&#xff0c;它是通过trait object实现的。这意味着这个类型在编译期间不确定&#xff0c;只有在运行时才能确定。 practice tr…...

uniapp 中过滤获得数组中某个对象里id:1的数据

// 假设studentData是包含多个学生信息的数组 const studentData [{id: 1, name: 小明, age: 18},{id: 2, name: 小红, age: 20},{id: 3, name: 小刚, age: 19},{id: 4, name: 小李, age: 22}, ]; // 过滤获取id为1的学生信息 const result studentData.filter(item > ite…...

Django系列之Channels

1. Channels 介绍 Django 中的 HTTP 请求是建立在请求和响应的简单概念之上的。浏览器发出请求&#xff0c;Django服务调用相应的视图函数&#xff0c;并返回响应内容给浏览器渲染。但是没有办法做到 服务器主动推送消息给浏览器。 因此&#xff0c;WebSocket 就应运而生了。…...

HTTP——五、与HTTP协作的Web服务器

HTTP 一、用单台虚拟主机实现多个域名二、通信数据转发程序 &#xff1a;代理、网关、隧道1、代理2、网关3、隧道 三、保存资源的缓存1、缓存的有效期限2、客户端的缓存 一台 Web 服务器可搭建多个独立域名的 Web 网站&#xff0c;也可作为通信路径上的中转服务器提升传输效率。…...

pyspark笔记 Timestamp 类型的比较

最近写pyspark遇到的一个小问题。 假设我们有一个pyspark DataFrame叫做dart 首先将dart里面timestamp这一列转化成Timestamp类型 dartdart.withColumn(timestamp,col(timestamp).cast(TimestampType()))查看timestamp的前5个元素 dart.select(timestamp).show(5,truncateFal…...

SpringBoot 集成 Redis

本地Java连接Redis常见问题&#xff1a; bind配置请注释掉保护模式设置为noLinux系统的防火墙设置redis服务器的IP地址和密码是否正确忘记写访问redis的服务端口号和auth密码 集成Jedis jedis是什么 Jedis Client是Redis官网推荐的一个面向java客户端&#xff0c;库文件实现…...

黑客学习笔记(网络安全)

一、首先&#xff0c;什么是黑客&#xff1f; 黑客泛指IT技术主攻渗透窃取攻击技术的电脑高手&#xff0c;现阶段黑客所需要掌握的远远不止这些。 以前是完全涉及黑灰产业的反派角色&#xff0c;现在大体指精通各种网络技术的程序人员 二、为什么要学习黑客技术&#xff1f;…...

[openCV]基于拟合中线的智能车巡线方案V1

import cv2 as cv import os import numpy as np# 遍历文件夹函数 def getFileList(dir, Filelist, extNone):"""获取文件夹及其子文件夹中文件列表输入 dir&#xff1a;文件夹根目录输入 ext: 扩展名返回&#xff1a; 文件路径列表"""newDir d…...

MyBatis-Plus 和达梦数据库实现高效数据持久化

一、添加依赖 首先&#xff0c;我们需要在项目的 pom.xml 文件中添加 MyBatis-Plus 和达梦数据库的依赖&#xff1a; <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifac…...

已注销【888】

元神密码 - 飞书云文档 (feishu.cn)...

Ceph错误汇总

title: “Ceph错误汇总” date: “2020-05-14” categories: - “技术” tags: - “Ceph” - “错误汇总” toc: false original: true draft: true Ceph错误汇总 1、执行ceph-deploy报错 1.1、错误信息 ➜ ceph-deploy Traceback (most recent call last):File "/us…...

DataTable过滤某些数据

要过滤DataTable中的某些数据&#xff0c;可以使用以下方法&#xff1a; 使用Select方法&#xff1a;可以使用DataTable的Select方法来筛选满足指定条件的数据行。该方法接受一个字符串参数作为过滤条件&#xff0c;返回一个符合条件的数据行数组。 DataTable filteredTable …...

JAVASE---继承和多态

继承 比如&#xff0c;狗和猫&#xff0c;它们都是一个动物&#xff0c;有共同的特征&#xff0c;我们就可以把这种特征抽取出来。 像这样把相同的可以重新放到一个类里面&#xff0c;进行调用&#xff0c;这就是继承。 概念 继承(inheritance)机制&#xff1a;是面向对象程…...

Centos7升级gcc、g++版本(转载)

Centos7默认的 gcc版本是 4.8.5 默认使用yum install gcc安装出来的gcc版本也是是4.8.5。 1.首先查看自己的 gcc 版本 gcc -v g -v如果出现&#xff1a;bash: g: 未找到命令... 则安装g&#xff1a;遇到暂停时&#xff0c;输入y继续安装 yum install gcc-c然后输入&#xf…...

第一章:继承

系列文章目录 文章目录 系列文章目录前言继承的概念及定义继承的概念继承定义定义格式继承关系和访问限定符继承基类成员访问方式的变化 基类和派生类对象赋值转换&#xff08;公有继承&#xff09;继承中的作用域派生类的默认成员函数继承与友元继承与静态成员不能被继承的类复…...