在查看<netinet/in.h>中sockaddr_in6代码时,发现有一个成员sin6_scope_id,表示IPv6 scope-id。而在sockaddr_in中是没有该成员的。
那么,这个成员是干什么的呢?
要讨论这个问题,先看一下IPv6的基础知识:IPv6地址分类及表示法。
IPv6地址分类及表示方法
-
一个IPv6地址字符表示
ABCD:EF01:2345:6789:ABCD:EF01:2345:6789
一共128bit,上面用16进制字符串表示,地址划分为8个块,每个块16bit,块与块之间用“:”隔开。
-
带有子网前缀的IPv6地址表示
ABCD:EF01:2345:6789:ABCD:EF01:2345:6789/64
这里/64表示前64bit都是子网络号
-
带有端口号的IPv6地址表示
[ABCD:EF01:2345:6789:ABCD:EF01:2345:6789]:8080
-
化简
对于多个地址块为0的情况,可以用"::"号进行简化
化简原则有这几点:
1)全0块"0000",可以简写为"0";
2)多个全0块,可以简写为"::";
3)一个IPv6地址中最多只能出现1个"::",出现多个全0块时,"::"要简写最长的那一段,如果没有最长的,选距离左边最近的;
4)"::"可以出现在地址字符串的开头或结尾;
具体示例:
化简前
|
化简后
|
备注
|
ABCD:0000:2345:0000:ABCD:0000:2345:0000
|
ABCD:0:2345:0:ABCD:0:2345:0
|
全0块"0000",简写为"0"
|
ABCD:EF01:0:0:0:0:0:6789 |
ABCD:EF01::6789
|
多个全0块,简写为"::"
|
ABCD:0:0:0:ABCD:0:0:6789
|
ABCD::ABCD:0:0:6789
|
多个可以简写的全0块,但只能简写最长的那个或者左边那个(如果同时2个最长)
|
0:0:0:0:0:0:0:1
|
::1
|
开头多个全0块
|
2001:0:0:0:0:0:0:0
|
2001::
|
末尾多个全0块
|
IPv6地址类型
IPv6整体上分三类:单播地址,任播地址,组播地址。
-
单播地址:一个单播地址对应一个接口,发往单播地址的数据包会被对应的接口接收;
-
任播地址:一个任播地址对应一组接口,发往任播地址的数据包会被这组接口的其中一个接收,被哪个接口接收由具体的路由协议确定;
-
组播地址:一个组播地址对应一组接口,发往组播地址的数据包会被这组的所有接口接收;
特殊地址
具体地址分配如下,任播存在于单播地址之中,没有专门的区分:
地址类型
|
二进制前缀
|
IPv6表示
|
未指定
|
00...0(全0)
|
::/128
|
环回地址
|
00...1(最后1位是1)
|
::1/128
|
组播地址
|
11111111
|
FF00::/8
|
本地链路单播地址
|
1111111010
|
FE80::/10
|
全球单播地址
|
剩余的所有
|
|
-
未指定地址:主要用于系统启动之初,尚未分配IP时,对外请求IP地址时,作为源地址使用,它不能用于数据包的目的地址之中。
-
环回地址:用于自己向自己发送数据包时使用,在日常网络排错中可用测试网络层协议状态。
-
本地链路单播地址(Link-Local addressing):前缀FE80::/10,作用是在没有路由(网关)存在的网络中,主机通过MAC地址自动配置生成IPv6地址,仅能在本地网络中使用。::FE80::/10 这些链路本地地址指明,这些地址只在区域连线中合法,有的类似于IPv4中的169.254.0.0/16。
IPv6地址空间由IANA组织分配,官网:https://www.iana.org/
IPv6 Scope ID
回到IPv6 scope的问题。
全世界的IPv6本地链路地址(Link-Local addressing)都有相同网络(FE80::/10),那么如何区分特定网络呢?
这就需要用到Scope ID(作用域ID),也称为Zone ID(区域ID),以免与多播scope flags混淆。Scope ID仅用于本地链接,使用百分号追加在地址后面。其内容特定于操作系统,例如Windows使用数字fe80::2%3,Linux使用网卡名fe80::2%eth0。在URI中使用时,百分号需要编码,如fe80::2%eth1 应显示为http://[fe80::a%25en1]。
PS:只有位于同一Scope ID下的两端,并且物理上直联,才能使用IPv6进行网络通信。
参考