如果说传输层协议,除了 TCP/UDP,我们还可以有其他选择,比如 Google 开发的 QUIC 协议,帮助在传输层支持 HTTP 3.0 传输。但是在网络层,IP 协议几乎一统天下。IP 协议目前主要有两个版本 IPv4 和 IPv6。这一讲我们先介绍 IPv4 协议。根据 Google 统计,使用 IPv6 的Google 用户比例在 30% 左右。IPv4使用范围很大,平时工作中很容易遇到,比如开发场景、网络优化场景、解决线上问题场景等。相信你经常会碰到一些和 IP 协议相关的名词,比如说这一讲关联的面试题目:路由和寻址的区别是什么?因此,学习 IPv4 还是非常有意义的。接下来,就请你带着对上面的问题,开启今天的学习。

什么是 IP 协议?

IP 协议(Internet Protocol)是一个处于垄断地位的网络层协议。

IP 协议并不负责数据的可靠性。传输数据时,数据被切分成一个个数据封包。IP 协议上层的传输层协议会对数据进行一次拆分,IP 协议还会进一步进行拆分。进行两次拆分是为了适配底层的设备。

可靠性保证数据无损地到达目的地。可靠性是 IP 协议上方的 Host-To-Host 协议保证的,比如 TCP 协议通过应答机制、窗口等保证数据的可靠性。 IP 协议自身不能保证可靠性。

比如 IP 协议可能会遇到下面这几个问题:

  • 封包损坏(数据传输过程中被损坏);
  • 丢包(数据发送过程中丢失);
  • 重发(数据被重发,比如中间设备通过 2 个路径传递数据);
  • 乱序(到达目的地时数据和发送数据不一致)。

IP 协议并不会去处理这些问题,因为网络层只专注解决网络层的问题

  • 延迟
  • 吞吐量
  • 丢包率

这里先给出一个结论:这三者是鱼和熊掌不能兼得,我们后续会讨论

IP 协议的工作原理

IP 协议接收 IP 协议上方的 Host-To-Host 协议传来的数据,然后进行拆分,这个能力叫作分片(Fragmentation)。然后 IP 协议为每个片段(Fragment)增加一个 IP 头(Header),组成一个IP 封包(Datagram)。之后,IP 协议调用底层的局域网(数据链路层)传送数据。最后 IP 协议通过寻址和路由能力最终把封包送达目的地。

分片(Fragmentation)

分片就是把数据切分成片。 IP 协议通过它下层的局域网(链路层)协议传输数据,因此需要适配底层传输网络的传输能力。数据太大通常就不适合底层网络传输,这就需要把大的数据切片。

增加协议头(IP Header)

切片完成之后,IP 协议会为每个切片(数据封包 Datagram)增加一个协议头。一个 IPv4 的协议头看上去就是如下图所示的样子:

其中重要有一下几个部分:

  • 原地址和目标地址:IPv4 的地址是 4 组 8 位的数字,总共是 32 位
  • Type Of Service: 服务的类型,是为了响应不同的用户诉求,用来选择延迟、吞吐量和丢包率之间的关系。
  • IHL:Internet Header Length,用来描述 IP 协议头的大小。
  • Total Length:定义报文(封包 Datagram)的长度。
  • Identification:(报文的 ID),发送方分配,代表顺序。
  • Fragment offset:描述要不要分包(拆分),以及如何拆分。
  • Time To Live:描述封包存活的时间。因此每个 IP 封包发送出去后,就开始销毁倒计时。如果倒计时为 0,就会销毁。比如中间的路由器看到一个 TTL 为 0 的封包,就直接丢弃。
  • Protocol :描述上层的协议,比如 TCP = 6,UDP = 17。
  • Options:代表可选项。
  • Checksum:用来检验封包的正确性,如果 Checksum 对不上,就需要选择丢弃这个封包。

“鱼和熊掌”不能兼得——延迟、吞吐量、丢包率

延迟(latency)

延迟指的是 1 bit 的数据从网络的一个终端传送到另一个终端需要的时间。这个时间包括在发送端准备发送的时间、排队发送的时间、发送数据的时间、数据传输的时间等。

吞吐量(Throughput)

吞吐量指单位时间内可以传输的平均数据量。比如用 bit/s 作为单位,就是 bps。吞吐量和延迟没有联系,比如延迟很高的网络,有可能吞吐量很高。可以类比成水管很大流速很慢,对比水管很细流速很快,这两种情况,最终流量可以是相等的。

丢包率(Packet loss)

丢表率指发送出去的封包没有到达目的地的比例。 在最大流速确定的网络中,丢表率会直接影响吞吐量。

我们的网络有时候需要低延迟,比如玩一款 RTS 游戏或者 Moba 游戏,这种时候延迟非常重要。另外如果把延迟看作一个平均指标,丢包也会影响延迟——一个包丢了,需要重发。而有的应用需要高吞吐量,延迟不是很重要,比如说网盘下载文件。大部分应用期望丢包不能太严重,比如语音电话,少量丢包还能听清,大量丢包就麻烦了,根本听不清对方说什么。严格希望不丢包的应用比较少,只有极特殊的网络控制管理场景,才需要在互联网层要求不丢包。

之所以说这三者鱼和熊掌不可兼得是因为如果同时追求延迟、吞吐量、丢包率,那么对网络设备的要求就会非常高,说白了就会非常贵。因此 IP 协议头中的 Type of Service 字段里,有以下 4 种主要的类型可以选择:

  • 低延迟
  • 高吞吐量
  • 低丢包率
  • 低成本

寻址(Addressing)

地址想要表达的是一个东西在哪里。寻址要做的就是:给一个地址,然后找到这个东西。IPv4 协议的寻址过程是逐级寻址。 #### IPv4 地址

IPv4 地址是 4 个 8 位(Octet)排列而成,总共可以编址 43 亿个地址。

比如 103.16.3.1 就是一个合法的 Ipv4 地址。4 组数字用.分开,是为了让人可读,实际上在内存和传输过程中,就是直接用 32 位。你可以观察一下103.16.3.1的二进制,如下图所示:

寻址过程

寻址就是如何根据 IP 地址找到设备。因为 IPv4 的世界中,网络是一个树状模型。顶层有多个平行的网络,每个网络有自己的网络号。然后顶层网络下方又有多个子网,子网下方还有子网,最后才是设备。

IP 协议的寻址过程需要逐级找到网络,最后定位设备。下面我们具体分析下这个过程:

① 找到顶层网络

比如103.16.3.1最顶层的网络号可以和255.0.0.0(子网掩码)做位与运算得到,如下所示:

1
103.16.3.1 & 255.0.0.0 = 103.0.0.0

因此103.0.0.0就是103.16.3.1所在的顶层网络。255.0.0.0.称作子网掩码。子网掩码的作用就是帮助根据 IP 地址找到对应子网。子网掩码是很多个1接着很多个0,和 IP 地址一起使用。

② 找到下一层网络

接下来要找到下一级网络,就需要用 IP 地址和下一级的子网掩码做位与运算。 比如:

1
103.16.3.1 & 255.255.0.0 = 103.16.0.0

其中103.16.0.0就是下一级的网络号。

③ 找到再下一级网络

接下来使用255.255.255.0子网掩码找到下一级网络是103.16.3.0。

④定位设备

设备就在子网103.16.3.0中,最终找到的设备号是1。当然子网掩码也不一定都是255,比如这个子网掩码255.240.0.0也是可以的。但通常我们把 IPv4 的网络分成这样 4 层。

路由(Routing)

在寻址过程中,数据总是存于某个局域网中。如果目的地在局域网中,就可以直接定位到设备了。如果目的地不在局域网中,这个时候,就需再去往其他网络。由于网络和网络间是网关在连接,因此如果目的地 IP 不在局域网中,就需要为 IP 封包选择通往下一个网络的路径,其实就是选择其中一个网关。你可能会问:网关有多个吗?如果一个网络和多个网络接壤,那自然需要多个网关了。

假如,我们要为 IP 地址 14.215.177.38 寻址,当前路由器所在的网络的编号是16.0.0.0。那么我们就需要知道去往 14.0.0.0 网络的 Gateway IP 地址。如果你在当前网络中用route查看路由表,可能可以看到一条下面这样的记录。

1
2
3
4
Destination:14.0.0.0
Gateway:16.12.1.100
Mask:255.0.0.0
Iface:16.12.1.1

这条记录就说明如果你要去往 14.0.0.0 网络,IP 地址 14.215.177.38 先要和 255.0.0.0 进行位运算,然后再查表,看到 14.0.0.0,得知去往 Gateway 的网卡(IFace)是 16.12.1.1。当封包去向下一个节点后,会进入新的路由节点,然后会继续上述路由过程,直到最终定位到设备。

为了进一步说明下面给出linux路由配置示例:

路由器 R1 路由表

Destination: 目的地址,可以是主机地址、网络地址,常用的是网络地址;

Gateway: 网关地址,所有未知地址都会找网关,有网关统一转发,只有边缘网络才会配置网关,并且直连网络不需要配置网关 ;

Genmask:目的地址的子网掩码;

Iface: 接口,去往目的地址的网络路径的出口(也就是从那个出口可以去往目的地址)

网络ID 子网掩码 接口 网关
10.0.0.0 255.0.0.0 1 -
172.16.0.0 255.255.0.0 2 -
192.168.0.0 255.255.255.0 2 172.16.0.2
192.168.100.0 255.255.255.0 2 172.16.0.2
0.0.0.0 0.0.0.0 2 172.16.0.2

路由器 R2 路由表

连接互联网的路由信息省略;
只有边界路由才有 默认路由 0.0.0.0/0.0.0.0 gateway_ip;
R2 不是边界路由,所以没有默认路由;
只有 R1 R3 才有默认路由,可以进行路由合并;

网络ID 子网掩码 接口 网关
10.0.0.0 255.0.0.0 3 172.16.0.1
172.16.0.0 255.255.0.0 3 -
192.168.0.0 255.255.255.0 4 -
192.168.100.0 255.255.255.0 4 192.168.0.2

路由器 R3 路由表

网络ID 子网掩码 接口 网关
10.0.0.0 255.0.0.0 5 192.168.0.1
172.16.0.0 255.255.0.0 5 192.168.0.1
192.168.0.0 255.255.255.0 5 -
192.168.100.0 255.255.255.0 6 -
0.0.0.0 0.0.0.0 5 192.168.0.1

小结

这一讲介绍了 IP 协议和 IP 协议的工作原理。首先 IP 协议会进行分片,将上游数据拆成一个个的封包(Datagram),然后为封包增加 IP 头部。封包发送出去后,就开始了寻址过程。寻址就是找到 IP 地址对应的设备。在局域网内,如果找不到设备,就需要路由。路由就是找到数据应该往哪里发送。最后通过层层路由定位到具体的设备。

现在你可以尝试来回答本讲关联的面试题目:路由和寻址的区别是什么?

【解析】寻址(Addressing)就是通过地址找设备。和现实生活中的寻址是一样的,比如根据地址找到一个公寓。在 IPv4 协议中,寻址找到的是一个设备所在的位置。路由(Routing)本质是路径的选择。就好像知道地址,但是到了每个十字路口,还需要选择具体的路径。

所以,要做路由,就必须能够理解地址,也就是需要借助寻址的能力。要通过寻址找到最终的设备,又要借助路由在每个节点选择数据传输的线路。因此,路由和寻址,是相辅相成的关系。

思考:127.0.0.1, localhost, 0.0.0.0 有什么不同?

127.0.0.1是本地回环地址(loopback),发送到 loopback 的数据会被转发到本地应用。127.0.0.1是通过网卡传输,依赖网卡,并受到网络防火墙和网卡相关的限制。

localhost 指代的是本地计算机,用于访问绑定在 loopback 上的服务。localhost 是一个主机名,不仅仅可以指向 IPv4 的本地回环地址,也可以指向 IPv6 的本地回环地址 [::1]。localhost是不经网卡传输!这点很重要,它不受网络防火墙和网卡相关的的限制。一般设置程序时本地服务用localhost是最好的,localhost不会解析成IP,也不会占用网卡、网络资源。

0.0.0.0是一个特殊目的 IP 地址,称作不可路由 IP 地址,它的用途会被特殊规定。通常情况下,当我们把一个服务绑定到0.0.0.0,相当于把服务绑定到任意的 IP 地址。比如一台服务器上有多个网卡,不同网卡连接不同的网络,如果服务绑定到 0.0.0.0 就可以保证服务在多个 IP 地址上都可以用。

下面给出一张对比表:

localhost 127.0.0.1 本机IP
网络 不联网 不联网 联网
传输 不使用网卡,不受防火墙和网卡的限制 网卡传输,受防火墙和网卡的限制 网卡传输,受防火墙和网卡的限制
访问 本机访问 本机访问 本机访问

参考如下:

https://www.cnblogs.com/shichangming/p/10195389.html

https://kaiwu.lagou.com/course/courseInfo.htm?courseId=837#/detail/pc?id=7271