为什么我们在 127.0.0.0 中没有可用的 IP 地址?

Moj*_*ian 16 networking tcp tcpip ip

从理论上讲,IP 地址的每个部分都是 0 到 255 之间的数字(总共 256 个可用插槽)。

但是为什么0第四部分中没有使用任何IP地址并且它们在IP地址计算中总是从1开始呢?

例如:

127.0.0.1 <=== logically this should start from 0 as the first usable IP address.
192.168.0.1 <=== for example even default router IP address is set to 1 rather than to be 0
10.10.0.1
.
.
Run Code Online (Sandbox Code Playgroud)

为什么0插槽总是从最后一部分跳过?

use*_*686 34

在 IPv4 中,子网的第一个地址被保留的原因尚不清楚,但很可能是因为很久以前它曾经是“广播”地址。(后来,最后一个地址成为标准广播地址。)

\n

因此,现在从技术上讲,可能可以使用第一个地址,但大多数现有网络堆栈仍然将其视为“保留”(有点像整个前“E 类”240.0.0.0/4 空间意外变得不可用)。

\n

请注意,它具体是子网的第一个地址,而不总是0地址。这些仅在 /24 子网的情况下匹配。但例如,/16 子网将.0.0保留,但不会 .1.0保留.47.0\xe2\x80\x93 这些位于 /16 中间的子网,因此它们是完全有效的主机地址。

\n

(另一方面,较小的 /27 子网不仅可以从以下位置开始.0,还可以从.32.192也将再次保留在 /27 中,即使它们没有保留在 /24 中。)

\n

另请注意,这仅适用于广播子网(例如以太网)。此类地址仍然可以在点对点链接中使用或作为 /32 单独路由。

\n

  • @doneal24:重点是,这似乎是一种早于 RFC 919 和许多其他 RFC 的做法。 IPv6中的寻址和路由仍然是相同的,只是地址分配的方法不同。 (13认同)
  • @doneal24:这是很久以前的事(有记录的痕迹 - 例如 Cisco IOS 有“ip广播零”作为选项)。但现在它仍然可以用作主机地址,同时_也_标识子网,因为这些情况发生在不同的上下文中 – 例如,IPv6 中的“2001:db8::/64”是一个子网地址_并且_同时也是一个有效的主机地址时间。 (11认同)
  • 第一个地址从来都不是广播,而是标识子网。 (8认同)
  • @doneal24为什么识别子网意味着该地址不能也用于主机?无论如何,识别子网实际上意味着什么?这不像数据报被发送到子网(它们可能被发送到广播地址) (5认同)
  • 我认为这种广播兼容性可以追溯到 BSD 4.2:https://datatracker.ietf.org/doc/html/rfc1122#page-66 请参阅页脚注。阅读“应该”等内容后,系统可能不会遵循此 RFC,但此 RFC 也可能存在勘误表。 (4认同)
  • 原始 IP 规范(在任何实现之前)将广播地址视为所有主机位都相同——这可以解释为全零或全一。这是经过改进的(在互操作性测试之后),所有 1 都是广播,所有 0 都是“子网地址”。即,未指定网络管理员的地址。现在,路由器具有常规地址来支持每个子网的多个路由器。 (3认同)

pen*_*359 6

在 IPv4 规范中,任何 IPv4 网络中的最低地址都被保留为网络地址,该地址与广播地址具有不同的用途,而广播地址通常是网络中的最高地址(尽管如果您想找点乐趣,可以进行不同的配置) 。在无类网络和子网掩码出现之前,网络地址的想法更有意义。子网和子网掩码背后的概念是原始规范中不存在的 IPv4 附加概念。

更新:以“.0”结尾的地址没有什么神奇之处,只是它是子网中的最低地址(可能并不总是.0)。

最初,IPv4是有类的,分为5类;A、B、C、D 和 E。A 类网络是最高有效位为 0 的所有 IP,即从 0.0.0.0 到 127.255.255.255 的 IP。高两位为10的IPv4地址为B类地址,对应地址128.0.0.0至191.255.255.255。C 类在其第一个八位字节中以 110xxxxx 开始,或者地址从 192.0.0.0 到 223.255.255.255。D 类的第一个八位字节匹配 1110xxxx,为它们提供 IP 224.0.0.0 到 239.0.0.0。最后,E 类为 1111xxxx 或 IP 240.0.0.0 至 255.255.255.255。E 类地址被视为保留地址,除 255.255.255.255 外,没有明确的用途。D 类是多播地址,用于将数据包一起发送到计算机组。AC 类是普通的单播 IP,其中各个设备在某个网络上获取 IP。

话虽如此,定义每个网络大小的是它的类别。A 类网络被定义为将前 8 位或第一个八位字节作为地址的网络部分,其余 24 位是单个 IPv4 网络上地址的特定于主机的部分。B 类将其分割为 16 位和 16 位或各 2 个八位位组。C类网络使用前24位作为网络部分,最后8位作为主机部分。用现代术语来说,A 类网络具有 /8 子网,B 类网络具有 /16 子网,C 类网络具有 /24 子网。IPv4 地址的网络部分和主机部分之间的分离对于路由数据包非常重要,并且是任何设备决定是否可以将其直接发送到本地网络上的系统还是必须将其发送到路由器以转发到其他地方的方式。在 IPv4 网络堆栈和协议实现子网划分之前,这种区别是从 IP 本身硬编码的。

您可以在 RIPv1 路由协议等协议中看到这一点的残余。它只通告 IP,而不通告子网掩码,因此主机地址和网络地址之间的区别是关键。如果 RIPv1 地址通告的地址为 192.0.0.0,则该地址是 B 类网络中的最低地址,因此它是整个网络的网络地址。它将告诉其他设备从 192.0.0.0 到 192.0.255.255 的所有系统都可以通过该路由使用(因为 B 类使用前两个八位位组作为网络,在本例中为 192.0)。但是,如果它通告 192.0.0.1,则这不是该网络中的最低地址,因此它是主机地址。这意味着 RIPv1 正在为单个特定主机而不是整个网络通告路由。也许它是一个拨号调制解调器,或者有其他原因需要获得唯一的路由,但该广告仅适用于该一台主机。

现在子网很常见,而且 RIPv2 等较新的协议将子网掩码与 IP 一起发送,网络地址的整个概念有点多余,但由于历史原因,我们仍坚持使用它。主机特定路由可以使用子网掩码 255.255.255.255 进行通告,但我们仍然必须保持与假设网络地址存在于网络范围底部的软件的兼容性。

更新:为了进一步澄清,这里有一些例子。如果您要将 10.xxx IP 地址范围分割为 /26 子网,则每个子网总共有 64 个地址(其中 62 个可用于主机),因为 32 位 IP 中仅剩下 6 位可供主机部分使用。前五个子网网络地址为 10.0.0.0、10.0.0.64、10.0.0.128、10.0.0.192 和 10.0.1.0。默认广播地址是子网中的最高地址,分别对应于 10.0.0.63、10.0.0.127、10.0.0.191 和 10.0.1.63。如果改为使用 /23 子网,则每个网络将有 512 个地址(510 个可用)。前五个子网是 10.0.0.0、10.0.2.0、10.0.4.0 和 10.0.6.0。对应的广播地址为10.0.1.255、10.0.3.255、10.5.255和10.7.255。请注意,在后一个示例中,10.0.1.0、10.0.3.0 等不是网络地址。它们完全可以用作主机的常规 IP,因为它们位于子网范围的中间。只有第一个和最后一个地址是特殊的。10.0.0.255 也可以类似地用作常规主机。


lar*_*sks 4

但为什么第四部分的IP地址中没有使用0,而IP地址的计算总是从1开始呢?

关于你的问题的标题,至少在Linux下,127.0.0.0是一个非常有用的地址(就像127.*映射到环回接口的任何其他地址一样)。

例如,我可以在以下位置启动网络服务器127.0.0.0:8080

docker run -d --rm --hostname node1 --name node1 -p 127.0.0.0:8080:8080 alpine \
  sh -c "apk add --update darkhttpd; mkdir /srv; hostname > /srv/index.html; darkhttpd /srv --port 8080"
Run Code Online (Sandbox Code Playgroud)

然后启动另一个绑定到127.0.0.1:8080

docker run -d --rm --hostname node2 --name node2 -p 127.0.0.1:8080:8080 alpine \
  sh -c "apk add --update darkhttpd; mkdir /srv; hostname > /srv/index.html; darkhttpd /srv --port 8080"
Run Code Online (Sandbox Code Playgroud)

现在我可以通过各自的地址访问这些服务器:

$ curl 127.0.0.0:8080
node1
$ curl 127.0.0.1:8080
node2
Run Code Online (Sandbox Code Playgroud)