思考
思考:网络中的设备多种多样,他们是怎么通信的?
同一设备进程间的通信方式就很多:消息队列、共享内存、管道等。
而对于不同设备的进程之间就需要一套通用的协议来建立连接,也就是下文要说的TCP/IP协议。TCP/IP其实并不是一个协议,而是一个协议族,包括了IP、ICMP、TCP、UDP、FTP、HTTP、ARP
ICMP主要用于告知网络包传送过程中产生的错误以及各种控制信息; ARP则用于在数据接口层根据IP地址查询响应的MAC地址,用于在以太网中传输数据
TCP/IP协议包含了几个层级,每个层级都为数据的稳定传输提供服务
TCP网络模型:应用层 -> 传输层 -> 网络层 -> 网络接口层
应用层
应用层的协议通常分为三类:一是依赖于面向连接的TCP的协议,如虚拟终端协议TELENET、简单电子邮件传输协议SMTP、文件传输协议FTP等;另一类是依赖于面向无连接的UDP的协议,如简单文件传输协议SMTP等;第三类是既依赖于TCP又依赖于UDP的协议,如域名系统DNS等,由此可见应用层的主要协议是HTTP、SMTP、FTP。我们使用的应用软件都是在应用层实现的。
传输层
传输层提供应用层之间端到端的通信服务,这一层主要有TCP和UDP两个协议
TCP和UDP的主要区别在于:
TCP通过流量控制、拥塞控制、超时重传等特性提供可靠数据传输。而UDP不能确保数据包能否抵达接收方,但是它的传播效率更高、实时性更好(HTTP/3就是基于UDP协议实现了类似于TCP的多路数据流和传输可靠性等功能,这套功能称为“QUIC”协议)。当传输层数据包大小超过MSS(TCP最大报文段长度)的时候,就会被分块进行传输,丢包的话也只需要重新传输对应的分块就行了
网络层
网络层的主要协议是IP,负责寻址和路由,将数据从一个设备传输到另一个设备
传输层的数据包在这一层会被添加上IP头组装成IP报文,报文超过MTU(1500字节)会被分片后再发送
IP地址结合子网掩码进行按位与计算出“网络号”和“主机号”,网络号用于表示IP地址是哪个子网,主机号用户表示同一子网下的不同主机,这就是它的寻址能力。
而设备之间不是一条网线直接连着的,而是通过各种网关、路由器、交换机等网络设备连接起来的,因此在每个节点就需要通过路由算法去计算下一步的方向
网络接口层
这一层负责接收IP数据报并通过网络发送,或者从网络上接收物理帧,抽出IP数据报,交给IP层。这一层,数据的单位称为“帧”
网络接口层会在IP数据包前面继续拼接MAC协议,该协议包括了发送方和接收方的MAC地址(通过ARP协议获取)信息。因为以太网中中判断网络包目的地的方式跟IP协议不一样,因此必须采用相匹配的方式才能在以太网中将包发往目的地,而 MAC 头部就是干这个用的,MAC协议负责以太网、WIFI这样的底层网络上发送原始数据
网络包传输
了解了网络的层级结构和各自分工,接下来就来看下实际中网络包从客户端到服务端的传输过程
1、输入URL,浏览器会进行DNS解析,首先会查询浏览器是否有这个域名的缓存,有就返回,没有就去查操作系统是否有缓存,没有继续查hosts文件(这也就是我们本地启动服务能自定义域名的原因了),再没有就查本地DNS服务器(客户端的 TCP/IP 设置中填写的 DNS 服务器地址),如果有缓存就返回,否则会去问根域名服务器,根域名服务器负责告知顶级域名服务器的地址给客户端,转而客户端去询问拿到的顶级域名服务器的地址,顶级域名服务器则会将权威域名服务器地址告知客户端,客户端再去询问权威域名服务器,这个时候权威域名服务器会查询到域名对应的IP地址,返回给客户端,客户端拿到后就进行TCP连接
域名解析的层级:根域名服务器(.) -> 顶级域名服务器(.com) -> 权威域名服务器(a.com)。根域名服务器存在于客户端中,因此安装第三方软件要防止被安装根域名服务地址到系统层
2、TCP三次握手建立连接,目的是保证双方的接收和发送能力是正常的
首先,服务端会主动监听某个端口,处于LISTEN状态
-
第一次握手,客户端会发送一个SYN报文给服务端,并指明客户端的初始化序列号ISN,客户端此时是SYN_SENT状态
-
第二次握手,服务端收到客户端的SYN报文后,会以自己的SYN报文作为应答,并且把ISN+1作为ACK的值,服务器此时是SYN_RCVD状态
-
第三次握手,客户端收到SYN报文后,会发送一个ACK报文,值为服务器的ISN+1,客户端此时状态是ESTABLISHED,服务端收到ACK报文后也处于ESTABLISHED状态,此时,双方就建立起了连接
为什么不是两次握手?
两次握手发送端可以确定自己发送的消息对方能接收,也能确定对方的包自己能接收。但接收方只能确定对方的包自己能接收,不确定对方是否能接收到自己的包。并且两次握手客户端有可能因为网络阻塞等原因会发送多个请求报文,延时到达的请求又会与服务建立连接,浪费掉许多服务器资源
3、建立连接后就开始在网络模型中组装网络包,首先在TCP中如果数据包超过MSS就会分割出块数据,TCP协议有两个端口,一个是浏览器监听的端口(每个tab基本都是一个独立的进程,当然还有多个tab可能共用一个进程的,具体细节可以去了解下浏览器工作原理),另一个是服务器监听的端口(80或443)
4、来到了网络层,这里会拼接上IP头,也是真正负责传输的地方,IP协议里面有源IP地址和目标IP地址,目标IP地址通过DNS解析能获取到,因为客户端可能有多个网卡,所以源IP需要通过目标地址和路由表的子网掩码依次进行与运算,并且和路由表当前条目的Destination对比,匹配则用该IP地址作为源IP地址,否则会走路由表的默认网关继续分发
5、接着来到了数据接口层,会在网络包的IP头部继续拼接上MAC头部,包含了发送方MAC地址和接收目标MAC地址,发送方MAC地址直接读取客户端ROM的值就行,而目标MAC地址则需要ARP协议帮我们查找,首先会先查找ARP缓存,没有就在以太网以广播的形式询问,如果处于同一个子网,那么就能获取到对方的MAC地址了
6、网络包组装好了,就需要将二进制包转换成电信号,并通过网线发送出去,这个时候就来到了网卡负责的模块了,这个时候会在开头加上报头和起始帧分界符 (用于标记包起始位置)和FCS(用于检测包传输过程是否有损坏)
7、接下来就是交换机会接收电信号,并通过交换机的模块转换成数字信号,并通过末尾的FCS校验错误,然后将接收方MAC地址和交换机的MAC地址表比较,MAC地址表每个MAC都对应着一个端口,查询到就将信号发送到相应的端口,否则,交换机会将包转发到除源端口之外的所有端口上,响应后就会响应的地址写入MAC地址表,方便下次查询转发
8、最后,网络包终于离开子网来到了路由器,路由器同样会将电信号转换成数字信号,并且通过尾部的FCS校验包,然后去掉包的MAC头部,通过IP头部信息查询路由表,将目标IP和子网进行与运算,如果与路由表当前比较条目的目标地址匹配就作为候选,接着判断条目的网关列如果为空,说明已经到达终点了,如果网关列是一个IP地址,那这个地址就是要转发的地址,那么就开始转发操作,通过ARP协议查询IP地址对应的MAC地址作为网络包新的接收方MAC地址,而发送方MAC地址则是对应路由输出端口的MAC地址(路由器端口是有MAC协议地址的,而交换机的端口是没有的),接着就是转换成电信号从对应输出端口发送出去,再通过交换机(负责以太网中两个设备之间的包传输)到达下一个路由器
9、最后最后,网络包到达了服务器,会开始对包一层一层剥开,MAC头->IP头->TCP头,根据头信息,随后把客户端需要的数据封装在HTTP响应报文里,然后又是一顿包装,TCP头->IP头->MAC头,然后转发出去,到达客户端后根据响应报文进行渲染(渲染再起文章篇幅介绍)
10、客户端接收到包后就要断开TCP连接了,这就需要四次挥手
- 第一次挥手,客户端发送一个FIN报文和一个序列号,停止发送数据,等待服务端确认,处于FIN_WAIT1状态
- 第二次挥手,服务端收到FIN报文,发送一个值为客户端序列号+1的ACK报文确认,处于CLOSE_WAIT状态,此时不会立马关闭,因为有可能还有数据报文在发送
- 第三次挥手,服务端可以断开链接了,和客户端第一次挥手一样,发送一个FIN报文,指定一个序列号,处于LAST_ACK状态
- 第四次挥手,发送值为服务端序列号+1的ACK报文作为应答,此时客户端也不会立马关闭连接,而是等待2MSL,处于TIME_WAIT,确保服务端收到自己的ACK报文后才会进入CLOSED状态,服务端收到ACK报文后,就关闭连接了
MSL是报文的最大生存时间,超过这个时间的报文会被丢弃,而等待2MSL是因为当客户端发送ACK报文到达服务端最少1MSL,而如果包丢失或者其他原因导致服务端响应客户端也至少1MSL,所以一来一回至少就需要2MSL了
结尾
🎈能力提升需要一点一点积累,了解网络原理能让我们更好的理解技术底层的逻辑~
🎈不积跬步,无以至千里!!
🎈加油!!!
最后最后 ~ 如果觉的文章对你有帮助,也欢迎关注笔者的公众号哈,不定时推送新的技术文章。