本篇是关于计算机网络基础的复习和总结,仅供阅读。
目录
假设客户端有多个网卡,就会有多个 IP 地址,那 IP 头部的源地址应该选择哪个 IP 呢?
TCP/IP网络模型
TCP/IP 网络通常是由上到下分成 4 层,分别是应用层,传输层,网络层和网络接口层。
应用层
关于应用层最容易理解,就是我们普通人平常所接触到的电脑或者手机软件。当两个不同设备的应用需要通信的时候,应用就把应用数据传给下一层,也就是传输层。
传输层
传输层(Transport Layer)是为应用层提供网络支持的。
传输层会有两个协议供选择:分别是TCP和UDP。大部分应用使用的正是 TCP 传输层协议,比如 HTTP 应用层协议。因为TCP协议中的很多特性(流量控制、超时重传、拥塞控制等)保证了数据在传输过程中更可靠的传给对方。
而UDP就比较简单了,他只是简简单单的负责发送数据包,不保证数据包是否能抵达对方。但相对的,传输效率更高,而且UDP其实也可以实现安全可靠的数据传输,大致方法是将TCP的特性在应用层实现。不过要实现一个商用的可靠 UDP 传输协议,也不是一件简单的事情。我其实也不知道到底该怎么做。
当传输的数据特别大的时候,如果直接传输的话就不好控制了,因此规定当传输层的数据包大小超过 MSS(TCP 最大报文段长度,后续也会提到MTU以太网中规定的最大传输单元与此相关),就要将数据包分块,这样即使中途有一个分块丢失或损坏了,只需要重新发送这一个分块,而不用重新发送整个数据包。像这样的每一个分块我们称之为TCP段。
但是,当设备接受数据时,传输层会将这个数据包传给应用,但是一台设备上有多个应用在接收数据,因此需要唯一的标识来找到对应的应用,而这个就是端口。
比如80 端口通常是 Web 服务器用的端口。再比如对于浏览器(客户端)中的每个标签栏都是一个独立的进程,操作系统会为这些进程分配临时的端口号。这些端口号的信息会被携带在传输层的报文中,因此接收方可以识别出该报文是发送给哪个应用。
网络层
最开始学习传输层的时候,我本来也以为传输层就是负责实际的数据传递,其实并不是的,传输层负责的仅仅只是给数据包加了一个TCP头部。负责实际的传输工作的是网络层。
网络层最常使用的是 IP 协议(Internet Protocol),IP 协议会将传输层的报文作为数据部分,再加上 IP 包头组装成 IP 报文,和TCP段类似,如果 IP 报文大小超过 MTU(以太网中一般为 1500 字节)就会再次进行分片,得到一个即将发送到网络的 IP 报文。
此时网络层负责将数据从一个设备传输到另一个设备,世界上那么多设备,又该如何找到对方呢?因此,网络层需要有区分设备的编号。
我们一般用 IP 地址给设备进行编号,只有一个单纯的 IP 地址虽然做到了区分设备,但是寻址起来就特别麻烦,因为全世界那么多台设备,怎么可能一个一个去匹配。
为了解决这个问题,我们先需要了解一个概念,IP地址分成两种意义:一个是网络号,负责标识该 IP 地址是属于哪个「子网」的;一个是主机号,负责标识同一「子网」下的不同主机;
接下来就需要配合子网掩码才能算出 IP 地址 的网络号和主机号:在知道子网掩码的情况下比如 10.100.122.0/24(/24指的就是子网掩码255.255.255.0,要划算成二进制),它的IP地址 10.100.122.0换算成二进制后与子网掩码进行按位与运算,得到的就是网络号;将 255.255.255.0 取反后与IP地址进行进行按位与运算,就可以得到主机号。在寻址的过程中,先匹配到相同的网络号(表示要找到同一个子网),才会去找对应的主机。
除了寻址能力, IP 协议还有另一个重要的能力就是路由。实际场景中,两台设备并不是用一条网线连接起来的,而是通过很多网关、路由器、交换机等众多网络设备连接起来的,那么就会形成很多条网络的路径,因此当数据包到达一个网络节点,就需要通过路由算法决定下一步走哪条路径。路由器寻址工作中,就是要找到目标地址的子网,找到后进而把数据包转发给对应的网络内。
IP 协议的寻址作用是告诉我们去往下一个目的地该朝哪个方向走,路由则是根据「下一个目的地」选择路径。寻址更像在导航,路由更像在操作方向盘。类似于:寻址的目的地是终点,路由则是选择合适的道路走,多个路由,经过多次选择,选出的道路拼起来最终到达终点。
网络接口层
生成了 IP 头部之后,接下来要交给网络接口层在 IP 头部的前面加上 MAC 头部,并封装成数据帧(Data frame)发送到网络上。
因为IP 头部中的接收方 IP 地址表示网络包的目的地,通过这个地址我们就可以判断要将包发到哪里,但在以太网的世界中,这个思路是行不通的。以太网就是一种在「局域网」内,把附近的设备连接起来,使它们之间可以进行通讯的技术。以太网在判断网络包目的地时和 IP 的方式不同,在以太网进行通讯要用到 MAC 地址而不是IP。
MAC 头部是以太网使用的头部,它包含了接收方和发送方的 MAC 地址等信息,我们可以通过 ARP 协议获取对方的 MAC 地址。
网络接口层主要为网络层提供「链路级别」传输的服务,负责在以太网、WiFi 这样的底层网络上发送原始数据包,工作在网卡这个层次,使用 MAC 地址来标识网络上的设备。
总结
网络接口层的传输单位是帧(frame),IP 层的传输单位是包(packet),TCP 层的传输单位是段segment),HTTP 的传输单位则是消息或报文(message)。但这些名词并没有什么本质的区分,可以统称为数据包。
数据传输的具体过程,都经历了什么?
首先针对于浏览器发送给的请求,我们都知道它是根据网址URL发送不同的请求的,所以浏览器的首个工作就是解析URL地址,并将解析得到的请求信息(HTTP)发送给服务器(web)。
最初的模样:HTTP
介绍一下URL的每一个部分
http: + // + web服务器的名字 + / +目录名字 + / +....+ 文件名字
URL开头代表访问数据使用的协议:这里是http协议;比如我们用的bilibili,它的URL开头使用的是https协议 。
// 后面的字符串:标识需要访问服务器的名称。
web服务器名字一般用'.'作为阶层的区分,他和外国人的命名方式类似:右边的范围大,左边的范围小。比如哔哩哔哩的www.bilibili.com,com是顶级域(这里提一下,之后还会细说)
目录名字+....+文件名字:从web服务器的根目录开始往下查找需要查询的数据,这里的根目录和linux中的根目录不是同一个概念,这里的根目录是可以通过配置文件改变的。(如果说这部分并没有出现在URL中,就代表访问根目录下事先设置的默认文件,也就是 /index.html
或者 /default.html。比如我们用的哔哩哔哩首页是
哔哩哔哩 (゜-゜)つロ 干杯~-bilibilihttps://www.bilibili.com/)
所以说URL包含了需要访问的服务器名字和服务器中的数据名字,现在就需要将他包装成http请求信息就行了。对于这个我们有专门的名词来解释他:请求报文和响应报文。顾名思义分别代表的就是请求时和响应时发出的数据。说到这里涉及到的东西又变多了,详细可以看这篇博客
HTTP报文之"请求报文"和"响应报文"详解_请求报文是什么意思-CSDN博客,这里就不多解释了。
那么第一个过程就算结束了:数据由浏览器解析URL得到HTTP请求信息也就是请求报文(相反的如果是响应信息就是响应报文)。
那么这时候新的问题来了:一个小小的数据包,他最终应该去往何处,谁会载她一程,谁会保护她,下一个目的地应该是哪里?别急,最先解决的无非是方向上的问题,这个问题才是最大的,否则南辕北辙得不偿失,所以按照这个思路,就应该有个工具来帮助这个数据包找到真实的目的地。
真实地址查询:通讯录DNS
首先要明确的是这个过程发生在什么位置,之前说到的,浏览器会将请求信息解析成http请求信息,操作系统会委托自身设备中的web服务器,由web服务器发送该请求。而真实的地址查询过程发生在自身的web服务器接受请求信息之前,通过请求信息来确定需要请求访问的真实地址。
为什么说是真实的地址查询呢?因为委托操作系统发送消息时,必须提供通信对象的 IP 地址。因此就需要根据服务器的域名查询服务器域名对应的 IP 地址。而这里的IP地址就是真实地址。
至此,新的问题又出现了,我们该如何确定每一个服务器域名对应的IP地址呢?想一想我们平时所用的电话,电话号码类似IP地址,域名类似联系人的名字,我们通常也不会专门去记联系人的电话号码,而是在手机上通过一个较通讯录的应用保存联系人名字和电话号码的这种一一对应的信息。IP地址也是这样存储的,而存储这些信息的“通讯录”叫DNS服务器。
如此一来只剩下一个问题了怎么根据这个“通讯录”DNS服务器来找到对应域名的IP地址。首先要了解域名的层级关系,先前提到过www.bilibili.com中,.com就是顶级域,现在来解释一下为什么。在这部分中用句点来分隔的,比如 www.server.com
,这里的句点代表了不同层次之间的界限。在域名中,越靠右的位置表示其层级越高。至此你是不是感觉.com是最高的域,其实不是的:实际上域名最后还有一个点,比如 www.server.com.
,这个最后的一个点代表根域名。也就是说.根域是在最顶层,它的下一层就是 .com
顶级域,再下面是 server.com.
类似一个树状结构:
根域的 DNS 服务器信息保存在互联网中所有的 DNS 服务器中。至于怎么保存的我也不知道,但是根据这个信息你就应该猜出来了:任何 DNS 服务器就都可以找到并访问根域 DNS 服务器了。因此,客户端只要能够找到任意一台 DNS 服务器,就可以通过它找到根域 DNS 服务器,然后再一路顺藤摸瓜找到位于下层的某台目标 DNS 服务器。
域名解析的工作流程,意思就是怎么顺藤摸瓜找到目标DNS服务器的获得想要查询的的IP地址呢?
1.客户端首先会发出一个 DNS 请求,问 www.server.com 的 IP 是啥,发送给本地的DNS服务器(这个DNS服务器的地址是在客户端的 TCP/IP 设置中填写的)。
2.本地域名服务器收到客户端的请求后,如果缓存里的表格能找到,也就是该域名对应的IP地址,则它直接返回 IP 地址。如果没有,本地 DNS 会去问它的根域名服务器:这个域名对应的IP地址是什么,而根域并不会告诉他而是给它指明了一条路:
3.根 DNS 收到来自本地 DNS 的请求后,发现后置是 .com,说:“www.server.com 这个域名归 .com 区域管理”,我给你 .com 顶级域名服务器地址,你去找它吧。”
4.本地 DNS 收到顶级域名服务器的地址后,发起请求问顶级域名服务器。
5.顶级域名服务器说:“我给你负责 www.server.com 区域的权威 DNS 服务器的地址你去问它应该能问到”。
6.本地 DNS 于是转向问权威 DNS 服务器server.com 的权威 DNS 服务器,它是域名解析结果的原出处。为什么叫权威,因为我的域名我做主。
7.本地 DNS 再将 IP 地址返回客户端,客户端和目标建立连接。
整个流程至此结束,大多就是在一个个问路的过程。但你是不是觉得太麻烦了,如果每次请求都这样,确实过于繁琐,但你不要忘了还有缓存。浏览器会先看自身有没有对这个域名的缓存,如果有,就直接返回,如果没有,就去问操作系统,操作系统也会去看自己的缓存,如果有,就直接返回,如果没有,再去 hosts 文件看,也没有,才会去问「本地 DNS 服务器」。
远行工具集合:协议栈
数据包,你想要旅游,可以!衣服,帽子,出行工具,护照等等都准备一下,不然我担心你的安全。
在通过 DNS 获取到 IP 后,就可以把 HTTP 的传输工作交给操作系统中的协议栈。协议栈的内部分为几个部分,分别承担不同的工作。上下关系是有一定的规则的,上面的部分会向下面的部分委托工作,下面的部分收到委托的工作并执行。
说这么多,你绝对没听懂,可以这样理解:这个数据包在获得IP地址后就飘了,马上就要出发了,但是他只知道最终的目的地在哪,并不知道下一站应该去哪里,遇上了"强盗"怎么办,而且他还没有交通工具。
我们作为数据包的好兄弟当然担心它,就给他提了一系列要求(协议),这些按照特定顺序组织的网络协议的集合构成了最终的协议栈来确保它的安全,数据包一看原来远行还要这么多东西准备就听好兄弟的话老老实实的行动去了。说是建议其实更是强制性要求,你没做完这些准备之前是不会让你走的。以下大概图
应用程序(浏览器)通过调用 Socket 库,来委托协议栈工作。协议栈的上半部分有两块,分别是负责收发数据的 TCP 和 UDP 协议,这两个传输协议会接受应用层的委托执行收发数据的操作。协议栈的下面一半是用 IP 协议控制网络包收发操作,在互联网上传数据时,数据会被切分成一块块的网络包,而将网络包发送给对方的操作就是由 IP 负责的。
此外 IP 中还包括 ICMP
协议(
用于告知网络包传送过程中产生的错误以及各种控制信息。)
和 ARP
协议( 用于根据 IP 地址查询相应的以太网 MAC 地址。)。
IP 下面的网卡驱动程序负责控制网卡硬件,而最下面的网卡则负责完成实际的收发操作,也就是对网线中
数据包一看还需要准备这么多东西,按照顺序的话那就是先去找TCP,得到TCP的帮助。
可靠的传输:衣服TCP
HTTP 是基于 TCP 协议传输的,所以在这我们先了解下 TCP 协议。在之前的TCP/IP模型中已经了解过此过程会给数据包添加一个TCP包头,这个包头的格式有一些需要关注的点
TCP报文
首先,源端口号和目标端口号是不可少的,如果没有这两个端口号,数据就不知道应该发给哪个应用。
接下来有包的序号,这个是为了解决包乱序的问题。因为防止超过MSS,会分成多个TCP段,这些段有对应的序号,防止乱序
还有应该有的是确认号,目的是确认发出去对方是否有收到。如果没有收到就应该重新发送,直到送达,这个是为了解决丢包的问题。
状态位。例如 SYN
是发起一个连接,ACK
是回复,RST
是重新连接,FIN
是结束连接等。TCP 是面向连接的,因而双方要维护连接的状态,这些带状态位的包的发送,会引起双方的状态变更。后续讲到3次握手和4次挥手,跟这个状态位有很大联系。
还有一个重要的就是窗口大小。TCP 要做流量控制,通信双方各声明一个窗口(缓存大小),标识自己当前能够的处理能力,双方互相知晓自己能处理的范围大小。
TCP还会做拥塞控制,对于真正的通路堵车不堵车,它无能为力,唯一能做的就是控制自己的速度。
就跟上面说的那些一样TCP比UDP多了流量控制、拥塞控制等特性来确保数据的可靠传输。
关于三次握手和四次挥手
在 HTTP 传输数据之前,首先需要 TCP 建立连接,TCP 连接的建立,通常称为三次握手。
在一开始客户端和服务端要建立连接的时候,双方都处于close状态,客户端先向服务端发送一个连接请求数据:能否与你建立连接,这个包被称为SYN包,如果服务端同意连接的话就会回复一个SYN+ACK包并处于就会处于SYN-RCVD状态,客户端收到后状态就会变为SYN-SEND并回复一个ACK包之后变为ESTABLISHED(数据传输状态)状态,服务端接也会变成ESTABLISHED状态。
你好奇的三次握手中的三指的就是发送了三次包,那为什么是发送3次包三次握手而不是两次握手呢?
可以这样想:如果是两次握手,客户端第一次向服务端发送SYN1包因为某些原因并未到达服务端,于是又重新发送了一个SYN2,这次服务端收到后就回复了SYN+ACK包并建立连接
而此时的SYN1突然又恢复正常了,也送达到了服务端,服务端会以为这又是一个新的连接,因为是两次握手,于是就直接处于数据等待状态,此时服务端的视角是有两个连接,而客户端以为是一个连接。
而如果是三次握手的情况下,服务端收不到最后客户端发送的ACK包就不会建立连接,并认为连接建立不成功。
所以三次握手本质上来说就是为了解决网路信道的不可靠问题,为了能够在不可靠的信道上建立可靠的连接。
目的是保证双方都有发送和接收的能力。
如果 HTTP 请求消息比较长,超过了 MSS
的长度,这时 TCP 就需要把 HTTP的数据拆解成一块块的数据发送,而不是一次性发送所有数据。
解释一下MSS(除去 IP 和 TCP 头部之后,一个网络包所能容纳的 TCP 数据的最大长度。)和MTU(一个网络包的最大长度,以太网中一般为 1500
字节。)数据会被以 MSS
的长度为单位进行拆分,拆分出来的每一块数据都会被放进单独的网络包中。就是在每个被拆分的数据加上 TCP 头信息,然后交给 IP 模块来发送数据。
这时我们前面所讲的TCP包头中的包的序号就起到了很大的作用,关于结局包的丢失和乱序:因为在数据包过大时分成的多个网络包中有规律的序号,这些序号可以防止包的乱序,至于如何防止的,大概过程是因为回复确认中的ACK包会包含本次包的序号和长度,接收到ACK包的一段会根据这些找到下一个发送的数据包并发送,循环。当然如果说传输过程中造成了包的丢失,也可以根据这个ACK包来判断哪一部分包的丢失让发送段重新发送数据。
对于四次挥手,处于连接状态的客户端和服务端都可以发起关闭连接请求,假设此时客户端主动发送请求,会向服务端发送FIN包表示要关闭连接自己进入终止等待1状态(FIN-WAIT-1),服务端接收到FIN包后就会发送ACK包,并进入关闭等待状态(CLOSE-WAIT),客户端接收到ACK包后,就会进入终止等待1状态(FIN-WAIT-2).此时服务端还可以发送未发送的数据,客户端还可以接受数据。
待服务端发送完数据之后,服务端会发送一包FIN包并进入最后确认状态(LAST-ACK),客户端收到后会发送ACK包并进入超时等待状态(TIME-WAIT),经过超时时间后关闭连接,而服务端接收到ACK包后就会直接关闭连接。
为什么说要等待超时时间后才关闭连接,是为了保证服务端一定会收到ACK包。因为一旦最后一次ACK包在传输中出现了意外并没有被服务端接收到,如果没有超时等待状态,此时的客户端是已经关闭连接的,可怜的服务端还没有接收到发送的ACK包会一直傻傻的等待不能关闭连接,一直停留在最后确认状态。如果有这个超时等待状态,因为服务端没有收到ACK包,他会重新发送一个FIN包,客户端会响应这个FIN包重发ACK包并刷新超时时间。
这样一说你会不会觉得四次挥手和三次握手一样,也是为了在不可靠的网络连接中进行可靠的连接断开确认
TCP 协议里面会有两个端口,一个是浏览器监听的端口(通常是随机生成的),一个是 Web 服务器监听的端口(HTTP 默认端口号是 80
, HTTPS 默认端口号是 443
)。我知道你不理解,因为我也是,下面来解释一下:源端口和目标端口号都是16位,但是目标端口号用于指定接收数据的目的进程。当一个新的TCP连接建立时,客户端会选择一个随机的未使用的端口号作为源端口号,并请求服务器选择一个特定的端口号作为目标端口号,然后这两个端口号会被绑定到彼此之间,形成一对一的连接。通俗理解就是:自己的东西自己随便定,所以源端口采用随机端口号,而目标端口号需要另一个拥有者协商确认,使得TCP连接建立的时候,两个端口号会被绑定到彼此之间形成一对一的连接。
远程定位:外套IP
TCP 模块在执行连接、收发、断开等各阶段操作时,都需要委托 IP 模块将数据封装成网络包发送给通信对象。亦可以看作TCP/IP协议栈中的IP模块处理,将其分割成适合网络传输的数据包。
IP模块更像是一个数据包的承载者,它并不直接创建或修改TCP报文结构。而TCP会在其内部处理数据的封装和解封装工作。
IP报文
在 IP 协议里面需要有源地址 IP 和 目标地址 IP:
- 源地址IP,即是客户端输出的 IP 地址;
- 目标地址,即通过 DNS 域名解析得到的 Web 服务器 IP。
协议号:因为 HTTP 是经过 TCP 传输的,所以在 IP 包头的协议号,要填写为 06
(十六进制),表示协议为 TCP。
假设客户端有多个网卡,就会有多个 IP 地址,那 IP 头部的源地址应该选择哪个 IP 呢?
当存在多个网卡时,在填写源地址 IP 时,就需要判断到底应该填写哪个地址。这个判断相当于在多块网卡中判断应该使用哪个一块网卡来发送包。这个时候就需要根据路由表规则,来判断哪一个网卡作为源地址 IP。假设下面一张路由表
举例我们的目标地址是192.168.10.200,就需要先把他换算成二进制,再对每一个网卡的子网掩码进行与运算。将得到的结果与该网卡的Destination尽心匹配,如果一样就选择该网卡,如果不一样就继续计算,直到找到匹配的网卡或者没有匹配的网卡,选择默认网关(第三条),此时就会将数据包发送给路由器,这里的Gateway就是该路由器的IP地址,后续的发送都交给这个路由器来做。
至此,IP代表远程定位,通过DNS找到对应的目的地,TCP里面记录的也有想要到达的目的地中的某一栋房子(端口)。接下来基本上就是怎么去的问题了。
两点传输:帽子MAC
形象点理解就是又给数据包在外面套了一层东西,也就是帽子MAC头部。再来回顾一下,现在有衣服:TCP头部,外套:IP头部,现在又来个帽子:MAC头部。
还记得我上个部分说的基本上就是怎么去的问题了,因为这个MAC头部又多了一层装备,之后才是如何去的问题。
我们都知道在以太网进行通讯要用到 MAC 地址而不是IP。因此为了满足在以太网中的通讯,就需要带上MAC头部,MAC 头部是以太网使用的头部,它包含了接收方和发送方的 MAC 地址等信息。用于两点之间的传输。
一般在 TCP/IP 通信里,MAC 包头的协议类型只使用:
0800
: IP 协议0806
: ARP 协议
如何获取MAC地址
发送方的 MAC 地址获取就比较简单了,MAC 地址是在网卡生产时写入到 ROM 里的,只要将这个值读取出来写入到 MAC 头部就可以了。你可以理解为出生自带的相对唯一标识。
接收方的 MAC 地址就有点复杂了,一旦拥有了对方的 MAC 的地址,以太网就会帮我们把包发送过去。这个过程首先需要借助路由表找到对应的IP地址(正常情况下是一个路由器的IP地址),接着需要 ARP
协议广播帮我们找到路由器的 MAC 地址。就像这样
ARP 协议会在以太网中以广播的形式,对以太网所有的设备进行询问,然后就会有人回答,如果对方和自己处于同一个子网中,那么通过上面的操作就可以得到对方的 MAC 地址。然后,我们将这个 MAC 地址写入 MAC 头部,MAC 头部就完成了。
现在我要讲清楚的一点很重要,你日常在网上刷视频并是通过IP地址找到的,但是在公司通过一个局域网进行交流就指的是MAC地址。
ARP缓存
有一点需要注意:并不是说每次都需要广播这样麻烦的操作,后续操作系统会把本次查询结果放到一块叫做 ARP 缓存的内存空间留着以后用,也就是说,在发包时:
先查询 ARP 缓存,如果其中已经保存了对方的 MAC 地址,就不需要发送 ARP 查询,直接使用 ARP 缓存中的地址。
而当 ARP 缓存中不存在对方 MAC 地址时,则发送 ARP 广播查询。
其实将这个MAC当做帽子可以,将他当做传输时的方式也可以,因为数据包在包装过后就会根据MAC地址进行点到点的传输。
出口:网卡
网络包只是存放在内存中的一串二进制数字信息,没有办法直接发送给对方。因此,我们需要将数字信息转换为电信号,才能在网线上传输,也就是说,这才是真正的数据发送过程。负责执行这一操作的是网卡,要控制网卡还需要靠网卡驱动程序。
网卡驱动获取网络包之后,会将其复制到网卡内的缓存区中,接着会在其开头加上报头和起始帧分界符,在末尾加上用于检测错误的帧校验序列。
- 起始帧分界符是一个用来表示包起始位置的标记
- 末尾的
FCS
(帧校验序列)用来检查包传输过程是否有损坏
最后网卡会将包转为电信号,通过网线发送出去,这个部分比较容易理解,就是在添加了起始帧分解符和FCS的基础上把这个全是数字的网络包转换成了电信号。
骑行工具1(近距离‘远行’):交换机
交换机的设计是将网络包原样转发到目的地。交换机工作在 MAC 层,也称为二层网络设备。
首先,电信号到达网线接口,交换机里的模块进行接收,接下来交换机里的模块将电信号转换为数字信号。然后通过包末尾的 FCS
校验错误,如果没问题则放到缓冲区。这部分操作基本和计算机的网卡相同,但交换机的工作方式和网卡不同。
因为计算机的网卡本身具有 MAC 地址,并通过核对收到的包的接收方 MAC 地址判断是不是发给自己的,如果不是发给自己的则丢弃;相对地,交换机的端口不核对接收方 MAC 地址,而是直接接收所有的包并存放到缓冲区中。因此,和网卡不同,交换机的端口不具有 MAC 地址。
将包存入缓冲区后,接下来需要查询一下这个包的接收方 MAC 地址是否已经在 MAC 地址表中有记录了。
MAC地址表
交换机的 MAC 地址表主要包含两个信息:一个是设备的 MAC 地址,另一个是该设备连接在交换机的哪个端口上。
正常流程
举一个简单的例子。现在有两台设备MAC地址分别为A和B,我们先假设MAC地址表中有完整的数据信息:MAC地址为A的设备对应端口1,MAC地址为B的设备对应端口2,A向B发送消息经过交换机,交换机通过MAC地址表:因为接受方的MAC地址是B所以就会通过交换电路将包发送到相应的端口了。
MAC地址表是如何添加记录的
那如果MAC地址表中并没有记录信息呢?那么只有这种可能,此次请求的接收方设备并未通过交换机发送过任何请求(或者说这条记录可能被删除了),拿上次的例子举例,假设MAC地址表中并未记录此条信息“MAC地址为A的设备对应端口1”,那么该例子在经过交换机的时候,就会将他的MAC地址信息和对应的端口记录下来。
当 MAC 地址表找不到指定的 MAC 地址会怎么样?
了解完MAC地址表是如何添加记录的之后,我们要解决这个更难的问题。这种情况下,交换机无法判断应该把包转发到哪个端口,只能将包转发到除了源端口之外的所有端口上,无论该设备连接在哪个端口上都能收到这个包。
这样做不会产生什么问题,因为以太网的设计本来就是将包发送到整个网络的,然后只有相应的接收者才接收包,而其他设备则会忽略这个包。
你是不是会觉得可能造成网络堵塞,其实不会的,因为一旦有设备响应“这个网络包是我的东西”,交换机就会将他的MAC地址和对应的端口记录到MAC地址表中。
此外,如果接收方 MAC 地址是一个广播地址,那么交换机会将包发送到除源端口之外的所有端口。(MAC 地址中的 FF:FF:FF:FF:FF:FF
;IP 地址中的 255.255.255.255)
骑行工具2(远距离‘远行’):路由器
你们可能会疑惑路由器和交换机的区别,还记得上边提到过得信息吗:交换机是在MAC层进行工作的,也就是在一个局域网,是二层网络设备,而路由器指的则是三层网络设备,他能穿的更远而不是简单的只在一个局域网中传播。
如果将整个过程比作远行旅游,你可能会在国内旅游也可能会在国外旅游
如果你是在国内旅游,仅仅只需要骑行工具1就能办到;而如果你是要国外旅游,那么你要先用到骑行工具1到达边境大门,在通过骑行工具2出国旅游。骑1可能就是汽车之类的,骑2可能就是飞机、轮船之类的。当然你也可以在国内旅游的时候用到骑行工具2,因为你需要。
这就类似于:虽然在局域网传输过程中可以只使用交换机来实现设备之间的通信,但是如果需要连接到外部网络或实现不同网络之间的通信,则需要使用路由器来进行路由和数据包转发。
路由器和交换机的区别
不抽象的比喻来说:路由器也是通过查表判断包转发的目标。不过在具体的操作过程上,路由器和交换机是有区别的。
因为路由器是基于 IP 设计的,俗称三层网络设备,路由器的各个端口都具有 MAC 地址和 IP 地址;而交换机是基于以太网设计的,俗称二层网络设备,交换机的端口不具有 MAC 地址。
基本原理
路由器的端口具有 MAC 地址,因此它就能够成为以太网的发送方和接收方;(交换机就不行他只能转发。)同时还具有 IP 地址,从这个意义上来说,它和计算机的网卡是一样的。当转发包时,首先路由器端口会接收发给自己的以太网包,然后路由表查询转发目标,再由相应的端口作为发送方将以太网包发送出去。
首先,电信号到达网线接口部分,路由器中的模块会将电信号转成数字信号,然后通过包末尾的 FCS
进行错误校验。如果没问题则检查 MAC 头部中的接收方 MAC 地址,看看是不是发给自己的包,如果是就放到接收缓冲区中,否则就丢弃这个包。总的来说,路由器的端口都具有 MAC 地址,只接收与自身地址匹配的包,遇到不匹配的包则直接丢弃。
查询路由表确定输出端口
完成包接收操作之后,路由器就会去掉包开头的 MAC 头部,因为这个MAC头部已经没用了,此次骑行的小目的地已经到了(点到点的传输)。为了到达终点目的地,他会重新设置一个新的MAC头部作为下一次小目的地。
当然你可以不按我的理解,正常:MAC 头部的作用就是将包送达路由器,其中的接收方 MAC 地址就是路由器端口的 MAC 地址。因此,当包到达路由器之后,MAC 头部的任务就完成了,于是 MAC 头部就会被丢弃。
接下来,路由器会根据 MAC 头部后方的 IP
头部中的内容进行包的转发操作。转发操作分为几个阶段,首先是查询路由表判断转发目标。
举个例子。
假设地址为 10.10.1.101
的计算机要向地址为 192.168.1.100
的服务器发送一个包,这个包先到达图中的路由器。第一步,就是根据包的接收方 IP 地址查询路由表中的目标地址栏,以找到相匹配的记录。
路由匹配和前面讲的一样,每个条目的子网掩码和 192.168.1.100
IP 做 & 与运算后,得到的结果与对应条目的目标地址进行匹配,如果匹配就会作为候选转发目标,如果不匹配就继续与下个条目进行路由匹配。如第二条目的子网掩码 255.255.255.0
与 192.168.1.100
IP 做 & 与运算后,得到结果是 192.168.1.0
,这与第二条目的目标地址 192.168.1.0
匹配,该第二条目记录就会被作为转发目标。
实在找不到匹配路由时,就会选择默认路由,路由表中子网掩码为0.0.0.0
的记录表示「默认路由」
发送操作
接下来就会进入包的发送操作。首先,我们需要根据路由表的网关列判断对方的地址。
如果网关是一个 IP 地址,则这个IP 地址就是我们要转发到的目标地址,还未抵达终点,还需继续需要路由器转发。再循环这一步操作。
如果网关为空,则 IP 头部中的接收方 IP 地址就是要转发到的目标地址,也是就终于找到IP 包头里的目标地址了,说明已抵达终点。
知道对方的 IP 地址之后,接下来需要通过 ARP
协议根据 IP 地址查询 MAC 地址,并将查询的结果作为接收方 MAC 地址。路由器也有 ARP 缓存,因此首先会在 ARP 缓存中查询,如果找不到则发送 ARP 查询请求。更新MAC头部中的接收方MAC地址
接下来是更新发送方 MAC 地址字段:这里填写输出端口的 MAC 地址(就是路由器的MAC地址)。还有一个以太类型字段,填写 0800
(十六进制)表示 IP 协议。
网络包完成后,接下来会将其转换成电信号并通过端口发送出去。这一步的工作过程和计算机也是相同的。发送出去的网络包会通过交换机到达下一个路由器。由于接收方 MAC 地址就是下一个路由器的地址,所以交换机会根据这一地址将包传输到下一个路由器。接下来,下一个路由器会将包转发给再下一个路由器,经过层层转发之后,网络包就到达了最终的目的地。
在网络包传输的过程中,源 IP 和目标 IP 始终是不会变的,一直变化的是 MAC 地址,因为需要 MAC 地址在以太网内进行两个设备之间的包传输。
这像不像你旅游时需要时不时的借助汽车(骑行工具1)来到达某个地点的飞机场或者港口,在通过飞机等(骑2)继续远行。
小知识
你有疑问吗?为什么必须要经过交换机才能实现路由器到路由器的转发?可以不用交换机吗?
答案当然是可以的,在一些特定的网络配置中,数据包可以直接从一个路由器传输到另一个路由器,而不通过交换机。这种情况通常发生在特殊的网络拓扑结构下,比如点对点连接或者虚拟专用网络(VPN)等情况下。这些情况都是实现路由器到路由器的数据传输。
那为什么在一般的网络环境中,数据包通常会通过交换机进行转发呢?我其实也不知道这么多,全靠搜集:
-
局域网内部通信:交换机主要用于在局域网内部进行数据包的转发和交换。在局域网中,设备通常需要快速、高效地进行通信,而交换机能够根据 MAC 地址表直接将数据包转发到目标设备,避免了广播风暴和提高了网络性能。
-
数据链路层转发:交换机操作在数据链路层,能够根据目的 MAC 地址进行精确的转发,从而实现设备之间的直接通信。这样可以确保数据包只发送到目标设备,而不会被广播到整个网络中。
-
广播和多播处理:交换机可以有效地处理广播和多播数据包,只将这些数据包转发到需要接收的设备,而不会洪泛整个网络。
-
提高网络性能:通过交换机进行数据包转发可以减少网络拥塞,提高网络性能和响应速度。交换机具有缓存和转发数据包的能力,可以有效管理数据流量。
-
降低碰撞:使用交换机可以减少碰撞,提高数据传输的稳定性和可靠性。交换机能够根据需要将数据包缓存并逐个发送,避免了数据包在网络中碰撞的情况。
总的来说在一般的网络环境中使用交换机进行数据包转发能够提高网络性能、降低碰撞、有效处理广播和多播数据包等,从而保证局域网内部的通信高效、稳定。
而造就他这么多优点的重要原因就是它是基于MAC地址进行数据包转发的。
脱衣扒皮:服务器 与 客户端
关于最后一跳
通常情况下,当信息从客户端传输到服务端时,最后一跳可能是经过交换机到达服务端。这取决于网络的拓扑结构和布置方式。
最后一跳经过路由器到达服务端是可能的,特别是在跨越不同网络或子网的情况下。
类似的扒皮/穿衣(这里假设最后一跳是交换机)
数据包到达服务端后会先扒开数据包的 MAC 头部,查看是否和服务器自己的 MAC 地址符合,符合就将包收起来。接着继续扒开数据包的 IP 头,发现 IP 地址符合,根据 IP 头中协议项,知道自己上层是 TCP 协议。于是,扒开 TCP 的头,里面有序列号,需要看一看这个序列包是不是我想要的,如果是就放入缓存中然后返回一个 ACK,如果不是就丢弃。
TCP头部里面还有目标端口号, 某个(HTTP 的)服务器正在监听这个端口号。服务器自然就知道是 HTTP 进程想要这个包,于是就将包发给 HTTP 进程。服务器的 HTTP 进程看到,原来这个请求是要访问一个页面,于是就把这个网页封装在HTTP 响应报文里。
HTTP 响应报文也需要穿上 TCP、IP、MAC 头部,不过这次是源地址是服务器 IP 地址,目的地址是客户端 IP 地址。
穿好头部衣服后,从网卡出去,交由交换机转发到出城/国的路由器,路由器就把响应数据包发到了下一个路由器,就这样循环跳到了客户端的路由器(骑行工具2),路由器扒开 IP 头部发现目的地是在国内,于是又把包发给了城内的交换机(骑行工具1),再由交换机转发到客户端。
客户端收到了服务器的响应数据包后,开始扒皮,把收到的数据包的皮扒剩 HTTP 响应报文后,交给浏览器去渲染页面,数据就这样显示出来了!
客户端要离开了,向服务器发起了 TCP 四次挥手,至此双方的连接就断开了。
小结
一个数据包的传输,如同蜿蜒迂回的旅程,穿越千山万水。学习完这部分内容之后,我就特别惊叹这是人能想出来的方法?这创造力?这伟人?
我还是继续当一条奋斗的咸鱼吧............
标签:IP,基础,地址,TCP,计算机网络,MAC,数据包,路由器 From: https://blog.csdn.net/yiyiyu66/article/details/141598447