Linux编程获取本机IP地址的几种方法

2023-11-16

在进行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 Address
				if (!(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 "14.215.177.38"

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 */

示例代码:

#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 Address
            tmpAddrPtr=&((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 Address
            tmpAddrPtr=&((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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux编程获取本机IP地址的几种方法 的相关文章

  • 期货交易服务行业调研报告 - 市场现状分析与发展前景预测

    期货交易服务市场的企业竞争态势 该报告涉及的主要国际市场参与者有Daniels Trading Saxo Tradovate NinjaTrader AGT Futures CQG Gain Capital Group ABLWSYS Sm
  • MIPS系统网络的配置

    4 MIPS系统网络的配置 模拟MPIS系统 并配置MIPS系统网络 01 安装依赖文件 sudo apt get install uml utilities bridge utils 02 修改Ubuntu主机网络配置 将Ubuntu系统
  • 单目测距(yolo目标检测+标定+测距代码)

    单目测距 目标检测 标定 测距 实时感知本车周围物体的距离对高级驾驶辅助系统具有重要意义 当判定物体与本车距离小于安全距离时便采取主动刹车等安全辅助功能 这将进一步提升汽车的安全性能并减少碰撞的发生 上一章本文完成了目标检测任务 接下来需要
  • 一枚芯片的成本是多少?(2)芯片硬件成本

    芯片硬件成本 计算封装和测试的成本这个没有具体的公式 只是测试的价格大致和针脚数的二次方成正比 封装的成本大致和针脚乘功耗的三次方成正比 如果CPU X采用40nm低功耗工艺的自主芯片 其测试成本约为2美元 封装成本约为6美元 因40nm低
  • nodejs调用mongodb!!!

    Nodejs调用MongoDB 要在 MongoDB 中创建一个数据库 首先我们需要创建一个 MongoClient 对象 然后配置好指定的 URL 和 端口号 如果数据库不存在 MongoDB 将创建数据库并建立连接 导入MongoDB包
  • 华为VS谷歌:万物互联,谁主沉浮?

    一 一周两套操作系统发布 6月2日 华为通过直播形式举行了鸿蒙HarmonyOS 2及华为全场景新品发布会 关于该发布会的详细内容老猿在 鸿蒙最新功能及承载设备详解 HarmonyOS 2及华为全场景新品发布会全纪录 进行了详细介绍 在此不
  • 【科普】一文读懂以太网PHY芯片

    物理层器件PHY Physical Layer Interface Devices 是将各网元连接到物理介质上的关键部件 负责完成互连参考模型 OSI 第1层中的功能 即为链路层实体之间进行bit传输提供物理连接所需的机械 电气 光电转换和
  • 嵌入式中锁机制杂谈

    在之前的文章中有提到操作系统中锁机制一般依赖于硬件CPU提供的原子数据操作指令 如SWP TEST AND SET等原子原语实现 基于此 才能真正保证锁机制的有效实现 通过上面原子操作 我们比较容易实现所谓的自旋操作 原子性的原地循环判断条
  • np.random.choice用法

    np random choice a size replace p 其作用是按要求生成一个一维数组 a是生成一维数组的来源 可以是int类型 可以是数组 也可以是list size 为从a中抽取的个数 即生成数组的维度 replace 表示
  • 《数据库系统》课程之实验七 通过ODBC/JDBC转移异构数据库中数据

    注 查看全文请关注作者 或点击前往 数据库系统 课程之实验七 通过ODBC JDBC转移异构数据库中数据 数据库系统 课程之实验七 通过ODBC JDBC转移异构数据库中数据 1 实验目的 学会配置ODBC JDBC数据源 熟悉使用ODBC
  • QueryWrapper方法解释

    继承自 AbstractWrapper 自身的内部属性 entity 也用于生成 where 条件 及 LambdaQueryWrapper 可以通过 new QueryWrapper lambda 方法获取 queryWrapper lt
  • PyTorch实战——搭建PyTorch神经网络进行气温预测

    如果觉得我的分享对您的学习有帮助 可以点赞关注哈 谢谢哈 目录 编辑 一 理论部分 二 代码实战 1 导入模块 1 matplotlib inline 2 warnings filterwarnings ignore 2 读入数据 3 展示
  • 三极管电路共集、共基、共射的区别

    共集 共基 共射指的是电路 是三极管电路的连接状态而不是三极管 所谓 共 就是输入 输出回路共有的部分 其判断是在交流等效电路下进行的 共集电极电路 三极管的集电极接地 集电极是输入与输出的公共极 共基极电路 三极管的基极接地 基极是输入与
  • 安装ubuntu系统时给/home分配空间太小,导致训练模型时数据集无法存放,所以给/home增大100GGB的存储空间

    1 从Windows系统中分配出100GB的存储空间 2 制作gparted的U盘启动项 3 插入U盘 进入bios界面 选择U盘启动项 4 进入gparted软件界面进行存储空间的转移重新分配 5 Exit退出 重新进入linux系统 参
  • 微信小程序 WebSocket 端口号配置

    https blog liuguofeng com p 4630 服务端开启 WebSocket 使用 WorkerMan phpSocket io 开启的端口为 2120 访问为 ws wanaioa unetu net 2120 由于微
  • 基于 java Swing 客户端 和 Spring Boot/Spring Cloud & Alibaba 后台管理系统

    基于 java Swing 客户端 和 Spring Boot Spring Cloud Alibaba 后台管理系统 基于 java Swing 客户端 和 Spring Boot Spring Cloud Alibaba 后台管理系统
  • 【Java JDK的使用方法】

    Java JDK的使用方法 第一步 同时按住窗口键和R键 在弹出的运行框中输入cmd打开编译框 第二步 输入cd 空格 地址 可以查看桌面文本文档的属性 找到桌面地址 第三步 notepad 空格 文件名 java 新建java文件 第四步
  • 何为UNP技术?

    为了解决移动视频监控系统中的这种穿NAT型 宇视科技特意提出了UNP UniversalNetwork Passport 万能网络护照 技术 目前 针对监控系统穿越NAT设备 防火墙和安全网闸时 基本上都是使用引流方案 内部服务器 双网口方
  • C++ 调用tensorflow

    安装protobuf 3 6 安装依赖软件 sudo apt get install autoconf automake libtool curl make g unzip 克隆版本为3 6 0的protobuf源码 git clone b
  • 8.翻转子串

    题目描述 假定我们都知道非常高效的算法来检查一个单词是否为其他字符串的子串 请将这个算法编写成一个函数 给定两个字符串s1和s2 请编写代码检查s2是否为s1旋转而成 要求只能调用一次检查子串的函数 给定两个字符串s1 s2 请返回bool

随机推荐

  • 1-如何安装ROS

    如何安装ROS 大家好 我是如何 今天尝试在Ubantu下安装ROS Robot Operating System 测试环境 虚拟机VMware Ubantu20 04 准备步骤 添加ROS软件源 sudo sh c echo deb ht
  • C++之普通成员函数、虚函数以及纯虚函数的区别与用法要点

    C 之普通成员函数 虚函数以及纯虚函数的区别与用法要点 作者 luoweifu 字体 增加 减小 类型 转载 时间 2015 07 21 我要评论 本篇文章主要介绍了C 中的普通成员函数 虚函数以及纯虚函数 非常的详细 有需要的朋友可以参考
  • localstorage在uc无痕模式失效问题;

    做项目的时候发现localstorage在uc 无痕模式下失效 但是其他浏览器不会出现此类问题 补充 我的解决方案是使用cookie代替localstorage 但是有大神给出了解决方案我觉得非常nice 附 https www jians
  • Thrift快速入门和简单示例

    文章目录 Thrift介绍 Thrift的架构 Thrift的特性 开发速度快 接口维护简单 学习成本低 多语言 跨语言支持 稳定 广泛使用 快速入门例子 编译安装 创建Thrift IDL文件 通过编译器编译user thrift文件 生
  • 马踏棋盘问题(C-数据结构)

    题目 在8 8的国际象棋棋盘中 给出马的初始位置 求出马踏遍棋盘每个位置的路线图 棋盘中每个位置只能走一次 思路 国际象棋中 马走的规则和中国象棋相似 为斜两格行走 即向任意方向走两格 再向与前面行走方向垂直的方向走一格 每个位置最多可以向
  • C语言,BMP格式解析,生成不同位深的图片。

    0 前言 目录 0 前言 1 BMP格式详解 1 1图片的构成 1 2BMP格式 1 2 1文件头 1 2 2位图信息头 1 2 3调色板 1 2 4位图数据 2 生成 3 总结 最近工作任务繁重且对我来说小有难度 但是没有困难的事情做起来
  • 《XNA游戏开发》简介

    一 XNA简介 XNA是基于DirectX的游戏开发环境 以C 为开发语言 以 NET Framework 为基础 并加入游戏应用所需之函式库所构成的 XNA Framework 可开发XNA for Windows Phone游戏 Xbo
  • html的<form>表单的基本介绍及使用说明

  • 本地、服务器文件互传命令

    1 从服务器复制文件 文件夹到本地 scp r ZSL 192 168 53 54 data ZSL json D WorkSpace PyCharm myfiel 加上r可以复制整个文件夹 不加r只能复制单个文件 2 从本地复制文件夹到服
  • protocol buffer 简单使用

    protocol buffer占用空间小 传输速率高 并且是跨平台的 每个语言都有一套解释protocol buffer的特殊方式 我就介绍一下C 如何解析protocol buffer 首先我们要自己编译Protogen 地址 如下 ht
  • Synchronized 锁升级(无锁、偏向锁、轻量级锁、重量级锁)

    一概念 是Java中一个关键字 是JVM层面提供的同步锁机制 用于保证多线程访问同一资源的可见性 互斥性 即当一个线程已经获取资源锁时 其他试图获取的线程只能等待或者阻塞在那里 访问静态 synchronized 方法占用的锁是当前类的锁
  • C++标准库学习(三)--队列和string类

    今天学习了C 的queue和string类的基本操作 queue是自带的队列 应用很是方便 要注意 pop函数并不返回pop出的值 include
  • FlowUs 使用攻略:如何快速制作 Web 应用(PWA)

    最近在寻找 Notion 的替代品过程中 我发现了 FlowUs 虽然是后起之秀 但不是唯 Notion 亦步亦趋 FLowUs 有两个很重要的特性打动了我 支持文件夹页面 一直以来 虽然 Notion 等产品十分强大 试图取代 Offic
  • powershell(二)对数据库的增删改查

    数据库配置 Database 数据库名称 数据库实例名 Server localhost SQL2008 用户名 UserName sa 密码 Password 数据库密码 连接数据库 SqlConn New Object System D
  • Databend 设计概述

    Databend 是一个开源的 完全面向云架构的新式数仓 它提供快速的弹性扩展能力 并结合云的弹性 简单性和低成本 使 Data Cloud 构建变得更加容易 Databend 把数据存储在像 AWS S3 Azure Blob 这些云上的
  • Java自定义注解的使用

    注解的定义 注解是一种能被添加到java源代码中的元数据 可以看做是是一种特殊标记 可以在包 类 参数和方法上使用 可以进行一些特殊的处理 访问修饰符必须为public 不写默认为public 元注解 JDK中有一些元注解来修饰注解 主要包
  • 浏览器提示:你的连接不是专用连接的解决方法

    解决方法 1 调整键盘为英文输入状态 2 鼠标点击当前页面任意位置 然后依次按键 thisisunsafe 输入完成后 页面会自动刷新 即可正常访问
  • 基于STM32的SGP30芯片开发例程

    2021 03 10新增 附上SGP30的官方资料和STM32F103的开发例程 链接 https pan baidu com s 1pnUTTcXzY1GqiWg 6QcB5Q 提取码 92m9 复制这段内容后打开百度网盘手机App 操作
  • WordPress网站的robots文件代码怎样写比较好

    本文记载和介绍的是wordpress的robots txt的在哪儿 以及如何修改robots文件来禁止搜索引擎爬取 ajax目录下的文章 以及如何优化WordPress网站的robots文件 wordpress设置robots文件的目录 w
  • Linux编程获取本机IP地址的几种方法

    在进行Linux网络编程时 经常会需要获取本机IP地址 除了常规的读取配置文件外 本文罗列几种个人所知的编程常用方法 仅供参考 如有错误请指出 方法一 使用ioctl 获取本地IP地址 Linux下可以使用ioctl 函数以及结构体 str