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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/21002.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Spring框架】SpringBoot统一功能处理

目录 用户登录权限校验用户登录拦截器排除所有静态资源练习&#xff1a;登录拦截器拦截器实现原理 统一异常处理统一数据返回格式为什么需要统⼀数据返回格式&#xff1f;统⼀数据返回格式的实现 用户登录权限校验 用户登录拦截器 1.自定义拦截器 package com.example.demo.…

shell centos 7 一键部署 KVM软件脚本

这个脚本有限地方还需要完善下 设计思路&#xff1a; 1、创建检查内核函数 check_kernel() 2、创建升级内核函数 update_kernel() 3、创建检查是否支持虚拟化函数 check_virtual() 4、创建检查操作系统函数 check_system() 5、创建检查网络函数 check_network() 6…

MicroPython ESP32网页实时更新DHT11数据显示

MicroPython ESP32网页实时更新DHT11数据显示 &#x1f4cc;相关篇《MicroPython ESP32 读取DHT11温湿度传感器数据》&#x1f4cd;《【Micropython esp32/8266】网页点灯控制示例》 ✨本例综合以上两篇文章内容实现&#xff1a;在本地网页中显示DHT11温度传感器数据。可以做到…

【Clion 2】使用技巧

一、TODO: 说明&#xff1a; 有时需要标记部分代码以供将来参考&#xff1a; 优化和改进的领域、可能的更改、要讨论的问题等等。 支持&#xff1a; TODO和FIXME小写和大写。这些模式可以在任何受支持的文件类型的行注释和块注释内使用。 创建TODO项 在要添加注释的代码行中…

大数据课程F3——HIve的基本操作

文章作者邮箱&#xff1a;yugongshiyesina.cn 地址&#xff1a;广东惠州 ▲ 本章节目的 ⚪ 掌握HIve的基本SQL语句和注意问题&#xff1b; ⚪ 掌握HIve的表结构&#xff1b; ⚪ 掌握HIve的数据类型&#xff1b; ⚪ 掌握HIve的基础函数和窗口函数&#xff1b; …

认识 SQL

文章目录 1.简介2.SQL 的组成3.SQL 是如何工作的&#xff1f;4.五种子语言5.SQL 注释参考文献 1.简介 SQL&#xff08;Structured Query Language&#xff0c;结构化查询语言&#xff09;是一种用于管理和操作关系型数据库的标准化查询语言。它是一种特定域语言&#xff08;DS…

Python web实战之 Django 的 MVC 设计模式详解

技术栈&#xff1a;Python、Django、HTML、CSS、JavaScript。 概要 在 Web 开发中&#xff0c;MVC&#xff08;Model-View-Controller&#xff09;模式是一种非常常见的设计模式&#xff0c;它可以帮助我们更好地管理代码&#xff0c;提高代码的可维护性。今天就介绍如何使用 …

前端性能优化的利器 ——— 浅谈JavaScript中的防抖和节流

防抖和节流函数是工作中两种常用的前端性能优化函数&#xff0c;今天我就来总结一下什么是防抖和节流&#xff0c;并详细说明一下如何在工作中应用防抖和节流函数 什么是防抖和节流? 在 JavaScript 中&#xff0c;防抖&#xff08;debounce&#xff09;和节流&#xff08;thr…

RTT(RT-Thread)线程管理(1.2W字详细讲解)

目录 RTT线程管理 线程管理特点 线程工作机制 线程控制块 线程属性 线程状态之间切换 线程相关操作 创建和删除线程 创建线程 删除线程 动态创建线程实例 启动线程 初始化和脱离线程 初始化线程 脱离线程 静态创建线程实例 线程辅助函数 获得当前线程 让出处…

数组中的第K个最大元 O(N)

给定整数数组 nums 和整数 k&#xff0c;请返回数组中第 k 个最大的元素。 请注意&#xff0c;你需要找的是数组排序后的第 k 个最大的元素&#xff0c;而不是第 k 个不同的元素。 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 1: 输入: [3,2,1,5,6,4], k 2…

[腾讯云Cloud Studio实战训练营]无门槛使用GPT+Cloud Studio辅助编程完成Excel自动工资结算

目录 前言一、Cloud Studio产品介绍1.1 注册Cloud Studio 二、项目实验2.1 选择合适的开发环境2.2 实验项目介绍2.3 实验步骤三、总结 前言 chatgpt简单介绍: ChatGPT是一种基于GPT的自然语言处理模型&#xff0c;专门用于生成对话式文本。它是OpenAI于2021年发布的&#xff0…

突破传统监测模式:业务状态监控HM的新思路 | 京东云技术团队

一、传统监控系统的盲区&#xff0c;如何打造业务状态监控。 在系统架构设计中非常重要的一环是要做数据监控和数据最终一致性&#xff0c;关于一致性的补偿&#xff0c;已经由算法部的大佬总结过就不再赘述。这里主要讲如何去补偿&#xff1f;补偿的方案哪些&#xff1f;这就…

TCP/IP协议

TCP/IP 是一类协议系统&#xff0c;它是用于网络通信的一套协议集合 物理层 所谓的物理层&#xff0c;是指光纤、电缆或者电磁波等真实存在的物理媒介。这些媒介可以传送物理信号&#xff0c;比如亮度、电压或者振幅。对于数字应用来说&#xff0c;我们只需要两种物理信号来分别…

加强 Kubernetes 能力:利用 CRD 定义多版本资源的实现方式

姚灿武&#xff0c;Rancher 中国研发工程师&#xff0c;拥有 7 年云计算领域经验&#xff0c;热衷开源技术&#xff0c;在云原生相关技术领域拥有丰富的开发和实践经验。 CRD&#xff0c;即自定义资源定义&#xff08;Custom Resource Definition&#xff09;&#xff0c;是 Ku…

leetcode 435. 无重叠区间

2023.8.3 本题和引爆气球 这题非常类似&#xff0c;利用同样的思路可以解决&#xff0c;代码如下&#xff1a; class Solution { public:static bool cmp(vector<int>& a , vector<int>& b){if(a[0] b[0]) return a[1] < b[1];return a[0] < b[0];…

SpringBoot复习:(16)TomcatStarter

直接在idea里运行SpringBoot程序时&#xff0c;内嵌的tomcat容器会调用TomcatStarter这个类的onStartup方法。TomcatStarter继承自ServletContainerInitializer 其onStartup方法会调用ServletContextInitializer&#xff08;不是ServletContainerInitializer)的onStartup方法.…

Unity 引擎做残影效果——3、顶点偏移方式

Unity实现残影效果 大家好&#xff0c;我是阿赵。 继续讲Unity引擎的残影做法。这次的残影效果和之前两种不太一样&#xff0c;是通过顶点偏移来实现的。 具体的效果是这样&#xff1a; 与其说是残影&#xff0c;这种效果更像是移动速度很快时造成的速度线&#xff0c;所以在移…

C# 开发规范

控件命名规则 控件名简写 控件名简写LabellblTextBoxtxtButtonbtnLinkButtonlnkbtnImageButtonimgbtnDropDownListddlListBoxlstDataGriddgDataListdlCheckBoxchkCheckBoxListchklsRadioButtonrdoRadioButtonListrdoltImageimgPanelpnlCalendecldAdRotatorarTabletblRequiredF…

Flink On Yarn模式部署与验证

session运行模式 该模式下分为2步&#xff0c;即使用yarn-session.sh申请资源&#xff0c;然后 flink run提交任务。 1、申请资源yarn-session.sh #在server1执行命令 /usr/local/flink-1.13.5/bin/yarn-session.sh -tm 1024 -n 2 -s 1 -d #申请2个CPU、2g内存 # -tm 表示每个…

关于前后端分离

关于前后端分离 接下来&#xff0c;你将进入 前后端分离项目开发 模块。 这也是企业中比较常见的开发模式。 疑问&#xff1a; 什么是前后端分离&#xff1f;与之前的开发模式有什么区别&#xff1f;企业为什么要用前后端分离&#xff1f; 1. 什么是前后端分离&#xff1f;…