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

这篇具有很好参考价值的文章主要介绍了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 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 "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 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
[3] https://blog.csdn.net/zhongmushu/article/details/89944990文章来源地址https://www.toymoban.com/news/detail-632182.html

到了这里,关于Linux C 获取主机网卡名及 IP 的几种方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 隐藏服务器源IP的几种方法

    为网络管理员的我们多知道遇到过服务器因为拒绝服务攻击(DDOS攻击)遇到网站瘫痪的情况是很糟心,随着客户信息越来越受到公司企业的重视,网站服务器的安全也越来越受到关注,但无法避免的是会遇到黑客使用DDoS攻击业务。 下面简单介绍一下隐藏ip地址具体的五种方法。

    2024年01月24日
    浏览(30)
  • 手机切换ip地址的几种方法详解

    在某些情况下,我们可能需要切换手机的IP地址来实现一些特定的需求,如解决某些应用程序的限制、绕过IP封禁等。本文将为大家分享几种切换手机IP地址的方法,让您能够轻松应对各种需求。 一、使用动态服务器 使用动态服务器是一种常见的切换手机IP地址的方法。动态服

    2024年02月07日
    浏览(33)
  • 查找树莓派ip地址的几种方法

    从上面的图中可以看到树莓派是通过网线和win10电脑相连的,以此来共享win10电脑网络,但是需要在电脑端设置后才能将网络共享出来, 设置方法参考以下链接: 通过一根网线共享网络给另一个电脑或者群辉上网 注意,第六步不用做,最后以太网 也要先禁用再重启一次。

    2024年01月16日
    浏览(33)
  • Java获取Java文件路径的几种方法

    Java获取Java文件路径的几种方法 在Java开发中,获取Java文件的路径是一项常见的任务。无论是读取文件、写入文件还是对文件进行其他操作,都需要先获得文件的路径。本文将介绍几种获取Java文件路径的方法,并提供相应的代码示例和详细描述。 方法一:使用相对路径 相对

    2024年02月07日
    浏览(41)
  • qt-c++进阶1-window、linux下获取本机所有网卡ip信息、根据网卡名获取ip地址。

    例如:第一章 主要是通过qt-c++实现获取本机电脑的网卡信息或者是IP信息 总结c++获取本机网卡信息的方法 第一章:适用于windows操作系统、linux操作系统 用 QHostAddress 解析获取本机 IPV4地址 ; 用 QNetworkInterface 解析获取所有网关信息( IP地址(IPV4和IPV6) 、 子网掩码 、 广播地

    2024年02月13日
    浏览(34)
  • Android开发:RecyclerView获取item位置的几种方法比较

            当使用 RecyclerView 来展示列表数据时,获取 item 的位置是一个常见的需求。RecyclerView 提供了多种获取 item 位置的方法,包括 getAdapterPosition() 、 getBindingAdapterPosition() 、 getAbsoluteAdapterPosition() 等等。这些方法的实现原理和返回值有所不同,因此在实际使用时需要根据

    2023年04月20日
    浏览(55)
  • 软件测试|探索Python中获取最高数值的几种方法

    前言 在数据分析、统计和编程领域,经常会遇到需要从一组数值中找出最高数值的情况。Python 作为一门功能丰富的编程语言,提供了多种方法来实现这一目标。在本文中,我们将探索几种获取最高数值的方法,帮助大家在不同情况下选择最适合的方法。 使用 max() 内置函数

    2024年02月02日
    浏览(43)
  • js获取文件名或文件后缀名(扩展名)的几种方法

    有时候我们需要通过含有文件名和后缀名的一个字符串中提取出该文件的文件名或文件后缀名(扩展名),可以通过如下几种方式进行截取。 例如文件名为: var fileName=\\\"12345.txt\\\"; 用法参考博文 【js截取字符串subString()方法】 js截取字符串subString()方法_js 如何使用substring()截取字

    2024年04月16日
    浏览(37)
  • Linux锁定用户的几种方法

    方法1:使用usermod命令: 锁定:$ usermod -l 用户名 (锁定用户账号,重新登陆生效) 解锁:$ usermod -u 用户名 查询状态: $ usermod -S 用户名 方法2:使用passwd命令: 锁定:$ passwd -l 用户名 (锁定用户密码,重新登陆生效) 解锁:$ passwd -u 用户名 查询状态: $ passwd -S 用户名 方

    2024年02月05日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包