记录一下常用的IPv4和IPv6地址格式
IPv4
IPv4地址是32位的,通常表示为“192.168.1.12”这样点分成4段的形式。
一个IP地址可以分为两部分,网络ID和主机ID。如何区分哪些位是网络ID,哪些位是主机ID,就需要子网掩码。
子网掩码
子网掩码使用来区分网段的,不同网段之间是不能直接通信的。
子网掩码的计算:
ip地址与子网掩码
广播地址
主机位全为1就是该子网的广播地址。例如:
192,168.1.255/24,就是 192.168.1.0网段的广播地址。
子网广播地址是可以被路由转发的,但是如"255.255.255.255"这个受限广播地址是不会被路由转发的。
参考:101-指向子网的广播
本地回环地址
127.0.0.1,数据不会经过网卡,用于本地测试
任意地址
任意地址,就是在socket编程的时候使用的 INADDR_ANY。
INADDR_ANY 实际上值得是 0.0.0.0,它的意思是不指定具体的网卡。
IPv6
IPv6地址是128位的,用:分为8个16进制的段。
ABCD:EF01:2345:6789:ABCD:EF01:2345:6789
子网掩码
与IPv4的子网掩码类似
多播地址
IPv6没有广播,只有多播。
前缀为FF00::/8的都是组播地址。
比如:FF02::1,它会发给本地链路内的所有节点,我认为他是个只能在本网段不能经过路由转发的广播。
在windows中,可以用netsh interface ipv6 show joins命令,查看机器是哪些多播组的成员
本地回环地址
::1/128,用于本地测试
任意地址
任意地址,就是在socket编程的时候使用的 in6addr_any。
in6addr_any实际上值得是 0:0:0:0:0:0:0:0(即::),它的意思是不指定具体的网卡。
关于in6addr_any,发现了一篇文章,有机会验证一下:
IPv6 socket侦听in6addr_any的问题
全球单播地址和链路本地地址
IPv6的地址常用的有global 、link。
在linux中ifconfig会明确告诉,IPv6地址属于那种,例如:
inet6 addr: 2001:f80:888::159/64 Scope:Global
inet6 addr: fe80::1fc3:1699:fe33:b227/64 Scope:Link
link地址(本地链路地址),前缀是FE80::/10 ,用于本地链路的直连通信,不能进行路由转发。
global地址,(全球唯一地址),前缀是2000::/3,用于向外通信。
->参考连接
链路本地地址和 Scope id(网卡索引)
在C++ 的socket编程中,sockaddr_in6有一个成员sin6_scope_id。
struct sockaddr_in6 {
short sin6_family;
u_short sin6_port;
u_long sin6_flowinfo;
struct in6_addr sin6_addr;
__C89_NAMELESS union {
u_long sin6_scope_id;
SCOPE_ID sin6_scope_struct;
};
};
sin6_scope_id(ULONG类型)实际上是本地网卡的索引号码。
它默认是0,相当于没有指定网卡,此时使用链路本地地址是无法进行通信的。
必须指定一个scope_id才行。
也就是下面索引这一列中的号码。
或者我们用ipconfig
命令,查看到的网卡地址中,本地连接IPv6地址后面跟了个“%20”这里就是他的网卡索引是20。
我把怎么获取Scope_id记录在本专栏的:
《[IPv6] Linux 和 Windows中如何获取sockaddr_in6的sin6_scope_id》
为什么在使用链路本地地址的时候必须要指定scope_id,而全球单播地址不需要呢?
这是因为全世界的本地链路地址都是FE80::网段的,路由没法根据网段做出区分。所以需要指定连接使用的scope id,路由才会找到目标。
参考:闲谈IPv6-IPv6地址的scope到底是什么?
参考文章
闲谈IPv6-IPv6地址的scope到底是什么?
ping通ipv6地址
IPv6 socket侦听in6addr_any的问题
ip地址与子网掩码
101-指向子网的广播
IPv6地址、单播、多播/组播介绍
第四十七讲:IPv6基础知识
IPv6 技术精要–第7章 IPv6多播地址