来源自小林Coding博客,阅读后部分精简笔记
目录
8.2、为什么断网了还能 ping 通 12.0.0.1 ?
8.3、127.0.0.1 和 localhost 以及 0.0.0.0 有区别吗?
IP 在 TCP/IP 参考模型中处于第三层,也就是网络层。
网络层的主要作用是:实现主机与主机之间的通信,也叫点对点(end to end)通信。
有的同学可能分不清 IP(网络层)和 MAC(数据链路层)之间的区别和关系
其实很容易区分,IP 的作用是主机之间通信用的,而 MAC 地址的作用则是实现【直连】的两个设备之间通信,而 IP 则负责在【没有直连】的网络之间进行通信传输。
IP 地址的分类:
最大主机个数,就是要看主机号的位数,如 C 类地址的主机号占 8 位,那么 C 类地址的最大主机个数:
为什么减 2 呢?
因为在 IP 地址中,有两个 IP 是特殊的,分别是主机号全为 1 和全为 0 地址:
广播地址用于什么?
用在同一链路中相互连接的主机之间发送数据包。广播地址分为本地广播和直接广播:
在本网络内广播的叫做本地广播,在不同网络之间的广播叫做直接广播。
IP 分类的缺陷:
同一网络下没有地址层次,缺少地址的灵活性
A,B,C 类网络有个尴尬的处境就是不能很好的与现实网络匹配
这两个缺点都可以在 CIDR 无分类解决
IP 地址与路由控制
IP 地址的网络地址这一部分是用于进行路由控制,路由控制表中记录着网络地址与下一步应该发送至路由器的地址。在主机和路由器上会有各自的路由器控制表。在发送 IP 包时,首先要确定 IP 包首部中的目标地址,再从路由器控制表中找到与该地址具有相同网络地址的记录,根据该纪录将 IP 包发送给相应的下一个路由器,如果路由器表中存在多条相同网络地址的记录,就选择相同位数最多的网络地址,也就是最长匹配。
注意:环回地址是不会流向网络,环回地址是在同一台计算机上的程序之间进行网络通信时所使用的一个默认地址。计算机使用一个特殊的 IP 地址 127.0.0.1 作为环回地址。与该地址具有相同意义的是一个叫做 localhost 的主机名。使用这个 IP 或主机名时,数据包不会流向网络。
IP 分片与重组
每种数据链路的最大传输单元 MTU 都是不相同的,如 FDDI 数据链路 MTU 4352、以太网的 MTU 是 1500 字节等。
每种数据链路的 MTU 之所以不同,是因为每个不同类型的数据链路的使用目的不同。使用目的不同,可承载的 MTU 也就不同。其中我们最常见数据链路是以太网,它的 MTU 是1500 字节。当 IP 数据包大小大于 MTU 时,IP 数据包就会被分片。经过分片之后的 IP 数据报在被重组的时候,只能由目标主机进行,路由器是不会进行重组的。在分片传输中,一旦某个分片丢失,则会造成整个 IP 数据报作废,所以 TCP 引入了 MSS 也就是在 TCP 层进行分片不由 IP 分片,那么对于 UDP 我们尽量不要发送一个大于 MTU 的数据报文。
我们在上网的时候,通常使用的方式是域名,而不是 IP 地址,因为域名方便人们记忆,那么实现这一技术的就是 DNS 域名解析,DNS 可以将域名网址自动转换为具体的 IP 地址。
DNS 中的域名都是用句号隔开的,比如 www.server.com ,这里的句点代表了不同层次之间的界限,在域名中,越靠右的位置表示其层级越高,所有的域名层级关系都类似于一棵树状结构。而 DNS 域名解析的过程蛮有意思的,整个过程就像和我们日常生活中找人问路的过程类似,只指路不带路。
在传输一个 IP 数据报的时候,确定了源 IP 地址和目标 IP 地址后,就会通过主机【路由表】确定 IP 数据包下一跳。然而,网络层的下一层是数据链路层,所以我们还要知道【下一跳】的 MAC 地址。由于主机的路由表中可以找到下一跳的 IP 地址,所以可以通过 ARP 协议,求得下一跳的地址。
ARP 又是如何知道对方的 MAC 地址的呢?
简单的说,ARP 是借助 ARP 请求和 ARP 响应两种类型的包确定 MAC 地址的。
操作系统通常会把第一次通过 ARP 获取的 MAC 地址缓存起来,以便下次直接从缓存中找到对应 IP 地址的 MAC 地址。不过,MAC 地址的缓存是由一定期限的,超过这个期限,缓存的内容将被清除。
RARP 协议是什么你知道不?
RARP 协议与 ARP 协议正好相反,是已知 MAC 地址求 IP 地址。例如将打印机服务器等小型嵌入式设备接入到网络中就经常会用到。通常要架设一台 RARP 服务器,在这个服务器上注册设备的 MAC 地址和 IP 地址,然后再将这个设备接入网络,接着:
最后设备就根据从 RARP 服务器所收到的应答消息设置自己的 IP 地址
DHCP 在生活中很常见,电脑通常都是通过 DHCP 动态获取 IP 地址,大大省去了配 IP 信息繁琐的过程。
DHCP 交互中,全程都是用 UDP 广播通信
IPv4 的地址是非常紧缺的,在前面我们也提到可以通过无分类地址来减缓 IPv4 地址耗尽的速度,但是互联网的用户增速是非常惊人的,所以 IPv4 地址依然有被耗尽的危险。
于是提出了一种网络转换 NAT 的方法,缓解了 IPv4 地址耗尽的问题。
两个私有 IP 地址都转换 IP 地址为共有地址,但是是以不同端口号为区分。于是生成了一个 NAPT 路由器表的转换表,就可以正确地转换地址跟端口的组合,令客户端 A、B 同时能与服务端之间进行通信。
缺点:
解决办法:使用 IPv6 地址,NAT 穿透技术
NAT 穿透技术:能够让网络应用程序主动发现自己位于 NAT 设备后,并且会主动获得 NAT 设备的共有 IP ,并为自己建立端口映射条目,注意这些都是 NAT 设备后的应用程序自动完成的。也就是说,在 NAT 穿透技术中,NAT 设备后的应用程序处于主动地位,它已经明确知道 NAT 设备要修改它外发的数据包,于是主动配合 NAT 设备的操作,主动地建立好映射,这样就不会像以前由 NAT 设备来建立映射了。说人话就是,客户端主动从 NAT 设备中获取公有 IP ,然后自己建立端口映射条目,然后用这个条目对外通信,就不需要 NAT 设备来进行转换了。
ICMP 全称是 Internet Control Message Protocol ,也就是互联网控制报文协议
主要功能包括:确认 IP 包是否成功送达目标地址、报告发送过程中 IP 包被丢弃的原因和改善网络设置等。
在 IP 通信中如果某个 IP 包因为某种原因未能到达目标地址,那么这个原因将由 ICMP 负责通知。
ICMP 大致可以分为两类:
IGMP 是因特网组管理协议,工作在主机(组播成员)和最后一跳路由之间:
ping 命令执行的时候,源主机首先会构建一个 ICMP 回送请求消息数据包。
接下来我们重点看 ping 的发送和接收过程
同个子网下的主机 A 和主机 B ,主机 A 执行 ping 主机 B 后我们看看中间发送了什么?
ping 命令执行的时候,源主机首先会构建一个 ICMP 回送请求消息数据包。
ICMP 数据包内包含多个字段,最终的是两个:
每发出一个请求数据包,序号会自动加 1,为了能够计算往返时间 RTT ,他会在报文的数据部分插入发送时间
然后由 ICMP 协议将这个数据包连同这个地址 192.168.1.2 一起交给 IP 层。IP 层将以 192.168.1.2 作为目的地址,本机 IP 地址作为源地址,协议字段设置为 1,表示是 ICMP 协议,再加上一些其他控制信息,构建一个 IP 数据包。
接下来加入 MAC 头。如果在本地 ARP 映射表中查找出 IP 地址 192.168.1.2 所对应的 MAC 地址,则可以直接使用,如果没有,则需要发送 ARP 协议查询 MAC 地址,获得 MAC 地址后,由于数据链路层构建一个数据帧,目的地址是 IP 层传过来的 MAC 地址,源地址则是本机的 MAC 地址,还要附加上一些控制信息,依据以太网的介质访问规则,将他们传送出去。
主机 B 收到这个数据帧后,先检查它的目的 MAC 地址,并和本机的 MAC 地址对比,如符合,则接收,否则就丢弃。接收后检查该数据帧,将 IP 数据包从帧中提取出来,交给本机的 IP 层。同样 IP 层检查后,将有用的信息提取后交给 ICMP 协议。主机 B 会构建一个 ICMP 回送响应消息数据包,回送响应数据包的类型字段为 0,序号为接收到的请求数据包的序号,然后再发送出去给 主机 A。
在规定时间内,源主机如果没有接到 ICMP 的应答包,则说明主机不可达,如果接收到了 ICMP 回送响应消息,则说明目标主机可达。此时源主机会检查,用当前时刻减去该数据包最初从源主机发送出的时刻,就是 ICMP 数据包的时间延迟。
traceroute 作用一:故意设置特殊的 TTL ,来追踪去往目的地时沿途的经过的路由器
这是如何工作的呢?
它的原理就是利用 IP 报的生存期限从 1 开始按照顺序递增的同时发送 UDP 包,强制接收 ICMP 超时消息的一种方法。比如将 TTL 设置为 1,则遇到第一个路由器,就牺牲了,接着返回 ICMP 差错报文网络类型,类型是时间超时。接下来将 TTL 设置为 2,第一个路由器过了,遇到第二个路由器也牺牲了,同时也返回了 ICMP 差错报文数据包,如此往复,直到到达目的主机。这样的过程,traceroute 就可以拿到了所有的路由器 IP 。
发送方如何知道发出去的 UDP 包是否到达了目的主机呢?
traceroute 在发送 UDP 包时,会填入一个不可能的端口号,作为 UDP 目标端口号,然后由于每个下一个探针,他都会增加一个,这些端口号都是通常认为不会使用,不过,没有人会知道当某些程序监听此端口会发生什么。当目的主机,收到 UDP 包后,会返回 ICMP 差错报文消息,但这个差错报文消息的类型是【端口不可达】,所以当差错报文类型是端口不可达时,说明发送方发出的 UDP 包到达了目的主机。
作用二:故意设置不分片,从而确定路径的 MTU。
这样做是为了什么?目的是为了路径 MTU 发现。
工作原理如下:首先在发送端主机发送 IP 数据报时,将 IP 包首部的分片禁止标志位设置为 1,根据这个标志位,途中的路由器不会对大数据包进行分片,而是将包丢弃。随后,通过一个 ICMP 的不可到达消息将数据链路上 MTU 的值一起发送给主机,不可到达的消息的类型为【需要进行分片但设置了不分片位】,发送主机端每次收到 ICMP 差错报文时就减少包的大小,以此来定位一个合适的 MTU 值,以便能达到目标主机。
断网了能 ping 通 127.0.0.1 。
首先这是个 IPv4 地址,IPv4 地址有 32 位,一个字节有 8 位,共 4 个字节。
其中 127 开头的都属于回环地址,也是 IPv4 的特殊地址,没什么道理,就是人为规定的。而 127.0.0.1 是众多回环地址的一个。之所以不是 127.0.0.2 ,而是 127.0.0.1 ,是因为源码里就是这个定义的,也没什么道理。
在有网的情况下,ping 最后是通过网卡将数据发送出去的。在断网的情况下可以看一下工作原理:
从应用层到传输层再到网络层。这段路径跟 ping 外网的时候是几乎是一样的。到了网络层,系统会根据目的 IP,在路由表中获取对应的路由信息,而这其中就包含选择哪个网卡把消息发送出去。当发现目标 IP 是外网的话,会从”真网卡“ 发送出去,当发现目标 IP 是回环地址时,就会选择本地网卡。本地网卡实际上就是个”假网卡“,它不像”真网卡“一样有个 ring buffer 什么的,”假网卡“会把数据推到一个叫做 input_pkt_queue 的链表中。这个链表是所有网卡共享的,上面挂着发给本机的各种消息。消息被发送到这个链表后,会再触发一个软中断。专门处理软中断的工具人是”ksoftrqd“这是个内核线程,它在收到软中断后就会立马去链表里把消息取出,然后顺着数据链路层,网络层等层层网上传递最后到应用程序。
ping 回环地址和通过 TCP 等各种协议发送数据到回环地址都是走这条路径。整条路径从发到收,都没有经过”真网卡“。之所以叫 127.0.0.1 叫本地回环地址,可以理解为,消息发出到这个本地上的话,就不会发出网络,在本机打个转就又回来了。所以断网能 ping 通 127.0.0.1
ping 回环地址和 ping 主机地址没有区别,都是在本机网络协议栈中兜一圈,就发回来了。
是有区别的:
首先 localhost 就不叫 IP ,它是一个域名,就跟 ”baidu.com“,是一个形式的东西,只不过默认会把它解析成 127.0.0.1 ,当然这可以在 /etc/hosts? 文件下修改。
所以默认情况下,使用 localhost 跟使用 127.0.0.1 是没有区别的。其次就是 0.0.0.0 ,执行 ping 0.0.0.0 是会失败的,因为它在 IPv4 中是无效地址的目标地址,但是它还是很有用的,我们再启动服务器的时候,一般会 listen 一个IP 和一个端口,等待客户端的连接,如果此时 listen 的是本机的 0.0.0.0 那么它代表的是本机的所有 IPv4 地址(当然,客户端 connect 时,不能使用 0.0.0.0 ,必须要指明连接哪个服务器 IP )