假设我们要将数据从主机A推送到主机B,根据我们之前的理解,是可以通过网络层进行路由的,这就是网络层在做决策,所以在网络层就要先决策该报文是要转发给和我处于同一网段的其它主机,还是交到下一跳,决策了之后再把报文向下交付,最后把报文交到路由器中。
IP 解决的问题是将数据从主机A跨网络送到主机B的问题,那么在送到主机B之前,就要先解决主机A如何将报文送到与主机A直接相连的路由器当中!所以数据链路层解决的是,直接相连的主机之间进行数据交付的问题。
我们回顾一下之前在 网络基础 讲的 Mac 地址,就是在同一个局域网中区分特定的主机。
那么在数据链路层中也有对应的报头,称为 Mac 帧 报头,Mac 帧 也就是数据链路层的一个协议,下图为 Mac 帧 报文:
其中数据部分就是上层交给数据链路层的 IP 报文,也就是有效载荷。
其中 Mac 帧 是通过定长报文做到解包和封装的;而通过类型这个字段进行分用交付给上层的不同协议,上层不同的协议对应不同的类型,如下图:
其中局域网的通信原理,也就是以太网通信原理,我们在 网络基础 中也谈过了,所以这里不再详细介绍。
那么在一个局域网中,如果一台主机正在发消息,周围也有主机正在发数据,此时就会发生数据碰撞问题,一旦发生数据碰撞,所有人的消息也就全部都失效了。所以一旦发生数据碰撞,碰撞双方的主机可以检测到,所以参与发送数据的主机,都要执行它所对应的碰撞避免算法以避免数据碰撞,然后再进行重发数据。
那么我们回到第一个问题,数据链路层解决的是,直接相连的主机之间进行数据交付的问题。当主机A讲数据推送到主机B,本质就是主机A查自己的路由表发现该数据是要发送到其它网络的,所以就根据 default 转发到路由器A中。
我们知道,在主机A中的网络层就已经做了决策要将数据转发到路由器A了,而主机A和路由器A是直接相连的,也就是符合局域网的通信原理。所以在主机A中封装Mac 帧时,源 Mac 地址 就是主机A的 Mac 地址,目的 Mac 地址 就是路由器A的 Mac 地址。当路由器A收到了该报文,是需要根据类型向上交付的,在路由器中也是要分层的,但是只分到网络层,所以是需要将 Mac 帧 的报头和有效载荷进行分离交付给上层。而有效载荷的开头处就是 IP 报头!而 IP 报头中涵盖了源 IP 地址和目的 IP 地址,而在路由器A中也有自己的路由表,所以它也会根据 IP 报头中的目的 IP 地址查自己的路由表,查的过程本质又是一次决策的过程。当它查的时候发现是要发送给下一个路由器B,此时决策完后就要修改源 IP 地址,然后重新封装 Mac 帧 交付给当前路由器的数据链路层,此时它的源 Mac 地址 就变成了路由器A的 Mac 地址,目的 Mac 地址 就变成了路由器B的Mac 地址,然后再让数据链路层发送给路由器B,也就是重复上面的工作了,知道数据一直到目的 IP 地址!
所以上面的工作过程说明 Mac 帧 只在局域网中有效!因为 Mac 帧 在发送之后,下一跳主机会去掉 Mac 帧 报头并重新封装 Mac 帧 报头!
当一个局域网中主机越来越多,发生数据碰撞的概率越来越大,那该局域网不就会瘫痪用不了了吗?其实不是的,随着局域网主机增多,就诞生了一种新的网络设备:交换机。
交换机是将一个局域网分成若干部分,假设没有交换机的时候,任何主机发数据都有可能会发生碰撞。而假如有了交换机,如果该交换机的左侧部分局域网发生了数据碰撞,交换机也能识别到,它就不会把左侧的碰撞报文转发到右侧,这样只会影响到左侧了。当然,如果是正常报文,交换机会正常转发到右侧部分的局域网中。所以交换机有一个概念叫做划分碰撞域,也就是减少局域网碰撞,不能彻底解决数据碰撞。
虽然网络发送的速度非常快,如果我们发送的报文太长的话,因为如果数据量大的话,也就注定了要在局域网中发送更多的数据,也就是和网络通信的时间就变长了,所以在发送期间和其它报文发生碰撞的概率就变高了,所以我们建议尽量发送小的数据包。所以 Mac 帧 中的有效载荷,也就是数据部分一般要求不要太大,范围是 46 ~ 1500,所以这就是为什么我们在 IP 协议 段格式中讲的,数据链路层一次不能发送太大的报文的原因!
由于数据链路层 MTU 的限制,对于较大的 IP 数据包要进行分片,但是我们上面也讲过分片是不好的。那么怎么解决呢?我们继续往下。
由于 Mac 帧 的有效载荷最大也只能是 1500 字节,所以就倒逼着网络层一次不能超过这个数,也就是倒逼网络层进行分片,但是分片是不好的,所以需要减少分片。但是网络层不能决定报文的大小,因为数据是从传输层交付到网络层的,所以减少分片的根源在于传输层。
那么如果数据链路层要求网络层一次发送的数据不能超过 1500 字节的话,那么在网络层中减去 IP 协议的报头,假设是 20 字节,那就剩下 1480 字节。此时网络层就可以要求传输层一次尽量发送不超过 1480 个字节的数据。那么在传输层假设是 TCP 协议,减去 TCP 的报头,假设也是 20 字节,所以只剩下 1460 字节,那么这时候 TCP 就知道了每次发送数据都不能超过 1460 个字节,这样就可以做到减少网络层的分片了!
那么我们把这个 1460 字节称为 MSS. 这也就是为什么我们在学 TCP 滑动窗口的时候,在滑动窗口内还要把数据分为一段一段再发送,不能把滑动窗口的数据一次性发送的原因,因为由 MSS 在约束!所以双方会在发送 SYN 建立三次握手的时候会在 TCP 头部写入自己能支持的 MSS 值!
一旦 UDP 携带的数据超过 1472(1500 - 20(IP首部) - 8(UDP首部)),那么只能在网络层分成多个 IP 数据报,也就是分片。这多个 IP 数据报有任意一个丢失,都会引起接收端网络层组装失败。那么这就意味着,如果 UDP 数据报在网络层被分片,整个数据被丢失的概率就大大增加了。
所谓的数据发送到目标网络,本质就是通过无数个连续的子网实现的。假设主机A有一个数据包通过无数的子网送到了主机B的入口路由器处,这个路由器经过该数据包的目标 IP 地址可以知道它就是要进入这个路由器所在的子网的。所以现在的问题是,路由器需要经过内网转发将数据转发到主机B,此时就需要进行局域网通信,那么就需要封装 Mac 帧,所以就需要知道主机B的 Mac 地址,此时路由器不一定知道主机B的 Mac 地址!所以此时就需要有一种技术,在局域网中,将目标主机的 IP 地址转化为目标主机的 Mac 地址,我们把它称为 ARP 协议,这是一种局域网协议。
虽然我们在这里介绍 ARP 协议,但是需要强调,ARP 不是一个单纯的数据链路层的协议,而是一个介于数据链路层和网络层之间的协议。
如上图,当主机A(入口路由器)收到一个数据包,会在该局域网中广播一条消息,就是发送 ARP 协议请求,当主机B得知该报文的 IP 地址是自己时,就会通过 ARP 响应返回自己的 Mac 地址给主机A,这样主机A就能知道目标 IP 地址的 Mac 地址了。主要是通过目标 IP 地址得到对应主机的 Mac 地址,也就是 ARP 协议建立了主机 IP 地址和 MAC 地址的映射关系。
如上就是 ARP 协议的报头格式,我们可以看到前 14 位是 Mac 报头,当然最后还有一位校验位没画出来,中间的就是 ARP 协议。其实 ARP 协议是属于 Mac 上层,但是归属到数据链路层。下面我们了解一下它的各个字段:
arp -a
查看每台主机的 ARP 缓存表
首先我们需要知道,如果主机收到多次同样的 ARP 应答,会以最新的为准。如果有一台主机A,在它的 ARP 缓存中存在路由器R的 IP 地址和 Mac 地址的缓存,但是此时有一台主机M,给主机A发送大量的路由器R和主机M的Mac地址的映射ARP响应,如下图:
此时主机A就认为 ipR:MacR 发送了变化,所以更改了该缓存的映射关系,此时如果主机A想要进行通信,都要经过主机M,如果主机M直接把主机A的报文丢弃,丢会导致主机A断网!
其中,我们把这种给主机发送大量的ARP应答的称为 ARP 欺骗。而主机A和路由器R并不知道主机M的存在,所以主机M成为了所谓的“中间人”!这种就是基于 ARP 的称为“中间人”的方式!
DNS 是一整套从域名映射到 IP 的系统。
TCP/IP 中使用 IP 地址和端口号来确定网络上的一台主机的一个程序。但是 IP 地址不方便记忆。于是人们发明了一种叫主机名的东西,是一个字符串,并且使用 hosts 文件来描述主机名和 IP 地址的关系。
最初,通过互连网信息中心(SRI-NIC)来管理这个 hosts 文件的。如果一个新计算机要接入网络,或者某个计算机 IP 变更,都需要到信息中心申请变更 hosts 文件。其他计算机也需要定期下载更新新版本的 hosts 文件才能正确上网。
这样就太麻烦了,于是产生了DNS系统。
至今,我们的计算机上仍然保留了 hosts 文件。在域名解析的过程中仍然会优先查找 hosts 文件的内容。
cat /etc/hosts
主域名是用来识别主机名称和主机所属的组织机构的一种分层结构的名称。
域名使用 . 连接
例如:www.baidu.com
ICMP 协议是一个网络层协议。一个新搭建好的网络,往往需要先进行一个简单的测试,来验证网络是否畅通;但是 IP 协议并不提供可靠传输。如果丢包了,IP 协议并不能通知传输层是否丢包以及丢包的原因。
ICMP 的功能:ICMP 正是提供这种功能的协议;ICMP 主要功能包括:
之前我们在 IP 协议 中讨论了,IPv4 协议中,IP 地址数量不充足的问题。而 NAT 技术当前解决 IP 地址不够用的主要手段,是路由器的一个重要功能。
但是我们在 IP 协议中并没有谈到数据包到了公网中如何回到内网中呢?我们下面探讨一下。
如果局域网内,有多个主机都访问同一个外网服务器,那么对于服务器返回的数据中,目的 IP 都是相同的,那么 NAT 路由器如何判定将这个数据包转发给哪个局域网的主机呢?这时候就需要 NAPT 来解决这个问题了,使用 IP+port 来建立这个关联关系。
实际上,我们在内网中发起外网的服务器请求时,需要经过 NAT 路由器的转化表,将内网的源 IP 地址+ port 和目的 IP 地址+ port 建立映射关系,映射路由器的 WAN口IP 地址+目标服务器的port,所以在服务器给内网应答数据的时候,就可以通过查询 NAT 路由器的转化表可以回到内网中!
路由器往往都具备 NAT 设备的功能,通过 NAT 设备进行中转,完成子网设备和其他子网设备的通信过程。代理服务器看起来和 NAT 设备有一点像。客户端向代理服务器发送请求,代理服务器将请求转发给真正要请求的服务器,服务器返回结果后,代理服务器又把结果回传给客户端。这就像我们在学校里的校园网,学校自建的服务器就相当于一个代理服务器,当我们想要上网,都是要先进行登录校园网,实际上我们是在学校的内网中获取 IP 地址!
代理服务器又分为正向代理和反向代理。正向代理用于请求的转发,而像上面学校的服务器就是一种正向代理;反向代理往往作为一个缓存,一般用于负载均衡。
那么 NAT 和代理服务器的区别有哪些呢?