• Ipv6设置与字节序转换


    一、Ipv6与Ipv4的区别

    IPv4是数字地址,用点分隔。IPv6是一个字母数字地址,用冒号分隔。
    在这里插入图片描述

    1. IPv4地址

    在这里插入图片描述

    • 通常,IPv4地址以点分十进制表示。每个部分代表一组构成8位地址方案的8位地址。

    • IPv4地址组合的数量是有限的。总体而言,可以算出40亿(256^4)个唯一地址。在IPv4地址才开始时,这个数字似乎永远不会过期。但是,现在情况有所不同了。2011年,全球互联网编号分配机构(IANA)分发了IPv4地址空间的最后一块。2015年,IANA正式宣布美国已用完IPv4地址。直到今天,IPv4地址仍然承载着最多(超过90%)的互联网流量。到目前为止,即使目前存在IPv4地址耗尽的问题,也有一些方法可以继续使用IPv4地址。例如,当仅需要一个唯一的IP地址来代表一组设备时,网络地址转换(NAT)是一种方法。除此之外,IP地址可以重复使用。当然,我们已经有了彻底耗尽的解决方案-IPv6地址

    2. IPv6地址

    在这里插入图片描述

    • IPv6地址使用以冒号分隔的十六进制数字。它分为八个16位块,构成一个128位地址方案。
    • 对于多个地址块为0的情况,可以用"::“号进行简化,化简原则有这几点:
      1)全0块"0000”,可以简写为"0";
      2)多个全0块,可以简写为"::“;
      3)一个IPv6地址中最多只能出现1个”::“,出现多个全0块时,”::“要简写最长的那一段,如果没有最长的,选距离左边最近的;
      4)”::"可以出现在地址字符串的开头或结尾;

    二、Enable IPv6

    # enable eth0
    echo 0 > /proc/sys/net/ipv6/conf/eth0/disable_ipv6
    
    • 1
    • 2

    一台主机启动后,每一块网卡都会自动生成一个fe80开头的链路本地地址。

    三、 配置方法

    设置IPv4会覆盖原来的ip地址,但ipv6设置是新增一个,所以如需保持一个ip地址,则需在新增后删除旧的ip。

    1. ifconfig命令

    可直接通过系统调用ifconfig命令新增或删除IPv6,如:

    ifconfig eth0 inet6 add(del) fe80::6a3e:34ff:fe7a:e9be/64
    
    • 1

    2. socket方法

    查看ifconfig源码,可发现是通过socket设置ip地址的,可参考其方法直接设置ip。需配置in6_ifreq结构体:

    // From linux/ipv6.h
    struct in6_ifreq {
       	struct in6_addr ifr6_addr;
       	__u32 ifr6_prefixlen;
       	unsigned int ifr6_ifindex;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    (1). ifr6_ifindex索引

    • if_nametoindex转换
      指定网络接口名称字符串(如”eth0”)作为参数;若该接口存在,则返回相应的索引,否则返回0。
    	ifr6.ifr6_ifindex = if_nametoindex(“eth0”);
    
    • 1
    • socket获取索引
    	strncpy(ifr.ifr_name, “eth0”, IFNAMSIZ);
    	if (ioctl(fd, SIOGIFINDEX, &ifr) < 0) {
    		perror("SIOGIFINDEX");
    		return;
       	}
       	ifr6.ifr6_ifindex = ifr.ifr_ifindex;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    (2). ifr6_addr

    	// inet_pton:将IP地址从字符串格式转换成网络地址格式,支持Ipv4和Ipv6。
    	inet_pton(AF_INET6, “fe80::6a3e:34ff:fe7a:e9be”, &ifreq6.ifr6_addr);
    
    • 1
    • 2

    (3). 新增与删除ip

    	ioctl(fd6, SIOCSIFADDR, &ifreq6);	// ADD
    	ioctl(fd6, SIOCDIFADDR, &ifreq6);	// DEL
    
    • 1
    • 2

    四、 网络字节序和主机字节序

    1. 概念

    tcp/ip规定网络字节序都是大端字节序,但主机字节序可能是大端也可能是小端,因此考虑到与协议的一致以及与同类其它平台产品的互通,发数据包时,将主机字节序转换为网络字节序,收数据包处将网络字节序再转换为主机字节序。

    • 如地址127.0.0.1 IP是ASCII表示法,把每一部分转化为8位的二进制数:
      01111111.00000000.00000000.00000001 = 2130706433(主机字节序,小端)
    • 将上面的四部分二进制数从右往左按部分重新排列:
      00000001.00000000.00000000.01111111 = 16777343(网络字节序,大端)

    2. 转换

    (1)主机<=>网络(ipv4)
    • 主机=>网络:htonl (uint32_t)、htons(uint16_t)
      例:htonl(2130706433) => 16777343
    • 网络=>主机:ntohl (uint32_t)、ntohs(uint16_t)
      例:ntohl(16777343) => 2130706433
    (2)IP字符串=>字节流(ipv4)
    • 返回网络字节序:inet_addr(“127.0.0.1”) // 16777343
    • 返回主机字节序:inet_network(“127.0.0.1”) // 2130706433

    问题:输入不合法时会返回INADDR_NONE(usually -1),而-1是合法的地址(255.255.255.255)。可以使用inet_aton、inet_pton或者getaddrinfo等函数来代替,这些函数提供了一种更清晰的方式来指示错误返回。

    (3)IP字符串<=>网络字节流
    • 字符串IP=>网络字节流:inet_aton、inet_pton
    • 网络字节流=>字符串IP:inet_ntoa、inet_ntop

    注意:inet_ntoa返回值是静态分配的,后面的调用会覆盖上一次的调用。
    Inet_aton不支持ipv6,而inet_pton支持,他们参数列表不同,返回值也不同;Inet_pton处理ipv4只支持点分十进制格式,inet_aton支持其他格式。

  • 相关阅读:
    【JavaEE】博客系统【前后端分离版本】
    KDD 2022 | 深度图神经网络中的特征过相关:一个新的视角
    echarts 轴文字内容太长导致显示不全解决方案
    JDK21最终版协程实现之虚拟线程
    分治算法求解:逆序对,Max Sum,棋盘覆盖,a-Good String——中山大学软件工程学院算法第四次实验课 必做+选做题
    使用Hot Chocolate和.NET 6构建GraphQL应用(9) —— 实现Mutate更新数据
    JVM相关知识点
    审计智能合约的成本是多少?如何审计智能合约?
    绕任意轴旋转矩阵推导
    283. 多边形,《算法竞赛进阶指南》,
  • 原文地址:https://blog.csdn.net/mrhjlong/article/details/126490588