有时候设备网卡上有多个IPv6,其中只有一个是可用的,另外一个是内网地址,无法使用,如果程序需要绑定一个V6地址的时候,需要获取网卡上的V6地址,并且要求是可用的。

通过ifconfig可用看到,eth0网卡上有2个IP地址,其中只有第一个V6地址的ScopeGlobal

eth0      Link encap:Ethernet  HWaddr 52:54:00:1D:79:D1
inet addr:192.168.121.120 Bcast:192.168.121.255 Mask:255.255.255.0
inet6 addr: 2001:250:250:250:250:250:250:222/64 Scope:Global
inet6 addr: fe80::5054:ff:fe1d:79d1/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:5999959 errors:0 dropped:0 overruns:0 frame:0
TX packets:104610 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:317521212 (302.8 MiB) TX bytes:8564391 (8.1 MiB)

那么如何用C获取IPv6地址,并且过滤其中Scope为Global的地址:

#define _GNU_SOURCE    # required for NI_NUMERICHOST
#include <arpa/inet.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <netdb.h> int main ()
{
struct ifaddrs *ifap, *ifa;
struct sockaddr_in6 *sa;
struct sockaddr_in *sa4;
char addr[INET6_ADDRSTRLEN];
char addr4[INET_ADDRSTRLEN]; getifaddrs (&ifap);
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
if (!ifa->ifa_addr) {
continue;
}
if (ifa->ifa_addr->sa_family==AF_INET6) {
sa = (struct sockaddr_in6 *) ifa->ifa_addr;
getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6), addr,
sizeof(addr), NULL, 0, NI_NUMERICHOST);
printf("Interface: %5s\tAddress: %s, scope: ", ifa->ifa_name, addr); // struct sockaddr_in6 sa;
if (IN6_IS_ADDR_LINKLOCAL(&sa->sin6_addr)) {
printf ("link-local ");
}
if (IN6_IS_ADDR_SITELOCAL(&sa->sin6_addr)) {
printf ("site-local ");
}
if (IN6_IS_ADDR_V4MAPPED(&sa->sin6_addr)) {
printf ("v4mapped ");
}
if (IN6_IS_ADDR_V4COMPAT(&sa->sin6_addr)) {
printf ("v4compat ");
}
if (IN6_IS_ADDR_LOOPBACK(&sa->sin6_addr)) {
printf ("host ");
}
if (IN6_IS_ADDR_UNSPECIFIED(&sa->sin6_addr)) {
printf ("unspecified ");
}
if (IN6_IS_ADDR_MC_GLOBAL(&sa->sin6_addr)){
printf ("global ");
}
printf("\n");
} else if(ifa->ifa_addr->sa_family == AF_INET){
sa4 = (struct sockaddr_in *)ifa->ifa_addr;
getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in), addr4,
sizeof(addr4), NULL, 0, NI_NUMERICHOST);
/*inet_ntop(AF_INET, sa4, addr4, INET_ADDRSTRLEN);*/
printf("Interface: %5s\tAddress: %s\n", ifa->ifa_name, addr4);
}
} freeifaddrs(ifap);
return 0;
}

编译下:

gcc -o ipa ipa.c

运行输出:

# ./ipa
Interface: lo Address: 127.0.0.1
Interface: eth0 Address: 192.168.121.120
Interface: eth1 Address: 10.24.0.114
Interface: lo Address: ::1, scope: host
Interface: eth0 Address: 2001:250:250:250:250:250:250:222, scope:
Interface: eth0 Address: fe80::5054:ff:fe1d:79d1%eth0, scope: link-local
Interface: eth1 Address: fe80::5054:ff:fedb:bdd7%eth1, scope: link-local

啊,可见IN6_IS_ADDR_MC_GLOBAL无法判断global的地址,我们只能用排除法了,将IN6_IS_ADDR_MC_GLOBAL判断修改为如下代码:

      // if (IN6_IS_ADDR_MC_GLOBAL(&sa->sin6_addr)){
// printf ("global ");
// }
if (!(IN6_IS_ADDR_LINKLOCAL(&sa->sin6_addr)) && !(IN6_IS_ADDR_SITELOCAL(&sa->sin6_addr)) &&
!(IN6_IS_ADDR_V4MAPPED(&sa->sin6_addr)) && !(IN6_IS_ADDR_LOOPBACK(&sa->sin6_addr)) &&
!(IN6_IS_ADDR_UNSPECIFIED(&sa->sin6_addr))
) {
printf ("global ");
}

重新编译输出:

# ./ipa
Interface: lo Address: 127.0.0.1
Interface: eth0 Address: 192.168.121.120
Interface: eth1 Address: 10.24.0.114
Interface: lo Address: ::1, scope: host
Interface: eth0 Address: 2001:250:250:250:250:250:250:222, scope: global
Interface: eth0 Address: fe80::5054:ff:fe1d:79d1%eth0, scope: link-local
Interface: eth1 Address: fe80::5054:ff:fedb:bdd7%eth1, scope: link-local

Linux C 获取本机IPV4和IPV6地址列表的更多相关文章

  1. Linux中获取本机的最新IPv6地址_更新ddns的脚本

    Linux中获取本机的最新IPv6地址_更新ddns的脚本 转载注明来源: 本文链接 来自osnosn的博客,写于 2019-11-07. 运营商提供ipv6地址. 路由器后有台linux机器,通过e ...

  2. ubuntu(Linux) c++ 获取本机IPv4和ipv6、查询本机IPv4,IPv6

    1.关于 演示环境: Linux xxxxxxx 5.4.0-47-generic #51-Ubuntu SMP Fri Sep 4 19:50:52 UTC 2020 x86_64 x86_64 x ...

  3. linux编程获取本机网络相关参数

    getifaddrs()和struct ifaddrs的使用,获取本机IP 博客分类: Linux C编程   ifaddrs结构体定义如下: struct ifaddrs { struct ifad ...

  4. Linux 获取本机IP、MAC地址用法大全

    getifaddrs()和struct ifaddrs的使用,获取本机IP ifaddrs结构体定义如下: struct ifaddrs { struct ifaddrs *ifa_next; /* ...

  5. Linux下获取本机IP地址的代码

    Linux下获取本机IP地址的代码,返回值即为互联网标准点分格式的字符串. #define ETH_NAME "eth0" //获得本机IP地址 char* GetLocalAdd ...

  6. 获取本机IP、mac地址、计算机名

    python获取本机IP.mac地址.计算机名 在python中获取ip地址和在php中有很大不同,我们先来看一下python 获得本机MAC地址: >>> import uuid ...

  7. js获取本机的网络IP地址

    JavaScript是一门脚本语言,是不能操作文件,读取本地信息的,所以想要获取IP,还需要借助后端技术.方法如下: //获取本机的网络ip地址 function jsonpCallback(res) ...

  8. c#中如何获取本机用户名、MAC地址、IP地址、硬盘ID、CPU序列号、系统名称、物理内存

    我们在利用C#开发桌面程序(Winform)程序的时候, 经常需要获取一些跟系统相关的信息, 以下这些代码获取能有些用处. c#中如何获取本机用户名.MAC地址.IP地址.硬盘ID.CPU序列号.系统 ...

  9. (转)协议森林04 地址耗尽危机 (IPv4与IPv6地址)

    协议森林04 地址耗尽危机 (IPv4与IPv6地址) 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! IP地址是IP协议的重要组 ...

  10. [Linux]Linux下开启snmp支持IPV4和IPV6

    SNMP简介 简单网络管理协议(SNMP),由一组网络管理的标准组成,包含一个应用层协议(application layer protocol).数据库模型(database schema)和一组资源 ...

随机推荐

  1. Typecho 如何开启外链转内链

    把博客中的外部链接转换为网站内链,据说有利于搜索引擎收录.该插件主要由 benzBrake 大佬 编写,同时支持转换文章和评论中的链接. 上传插件 下载 Master Branch Code 后上传到 ...

  2. 百万架构师第四十六课:并发编程的原理(一)|JavaGuide

    百万架构师系列文章阅读体验感更佳 原文链接:https://javaguide.net 并发编程的原理 课程目标 JMM 内存模型 JMM 如何解决原子性.可见性.有序性的问题 Synchronize ...

  3. C#使用Interlocked实现线程同步

    通过System.Threading命名空间的Interlocked类控制计数器,从而实现进程 的同步.Iterlocked类的部分方法如下表: 示例,同时开启两个线程,一个写入数据,一个读出数据 代 ...

  4. VNCTF2025_Crypto

    VNCTF2025_Crypto Simple prediction task.py from random import shuffle from Crypto.Util.number import ...

  5. 地球OL攻略 —— 某应届生求职总结

    某应届生的苦逼求职总结 1.自我介绍,阐述一下自己过去的情况 2.目前的就业情况以及从事的就业方向 3.你在面试的时候遇到什么困难?是怎么帮忙解决的 4.当初为什么会选择选择这一行? 5.分享一下学习 ...

  6. 前缀函数和 KMP "跳步骤"模式匹配

    在一篇由字符构成的长文中查找另一个短字符串出现的位置,这可以算是编程领域最最常见的问题(比如按下 Ctrl + F 就可以打开你浏览器的查找功能).这个问题叫做字符串的模式匹配,我们把被查找的关键词叫 ...

  7. MongoDB入门介绍与案例分析

    一.MongoDB 数据库定位 首先我们来看一下 MongoDB 是什么样的数据库.数据库分两大类: OLTP(Online Transaction Processing)联机事务处理. OLAP(O ...

  8. 妙用PHP函数处理数组

    PHP的数组是一种很强大的数据类型,与此同时PHP内置了一系列与数组相关的函数可以轻松地实现日常开发功能. 1. 取数组指定键名列 对于某些关联数组,有时候我们只想取指定键名的那部分,比如数组为 [' ...

  9. Linux 防火墙及开放端口管理

    查看防火墙是否开启systemctl status firewalld 若没有开启则是开启状态systemctl start firewalld  关闭则start改为stop 查看所有开启的端口fi ...

  10. 实现领域驱动设计 - 使用ABP框架 - 领域服务

    领域服务 领域服务实现领域逻辑 依赖于服务和存储库. 需要处理多个聚合,因为该逻辑不适合任何聚合. 领域服务与领域对象一起工作.它们的方法可以获取并返回实体.值对象.原始类型--但是,它们不获取/返回 ...