计算机网络是面试中的重点,尤其是一些高频题目,比如TCP、UDP协议以及TCP的三次握手四次挥手还有关于TCP的一系列知识,这篇文章就是自己总结的传输层的重点知识,适合面试前复习巩固。
传输层
一、总览整个传输层的重点
图太大了,只能压缩,就会有些模糊。不过图只是给一个总览,接下来我们会一一介绍这些知识滴。
二、传输层基本知识
1. 多路复用和多路分用
多路分用:在接收端将传输层的报文段交给正确的套接字工作就是多路分用
多路复用:在发送端将不同的套接字中收集到的数据块封装上首部信息后发送出去就叫多路复用
多路复用和多路分用是传输层要做的最基础的事情,通过多路复用和分用就可以将网络层的信息交到对应的应用层,也可以将应用层协议发送到网络层。
TCP和UDP协议都实现了多路复用和分用。
2.多路分用工作
主机接受到网络层传送来的IP数据报后,在首部中解析到源端口号、目的端口号等信息,然后将数据报交给应用层对应的Socket
其中UDP无连接服务是使用目的IP、目的端口号来标识。这样来自不同IP地址不同端口的数据包都会导入到同一个Socket
而TCP是使用源IP、目的IP、源端口、目的端口来标识。只有四个都相同时,才会导向同一个Socket,Web服务器为每一个客户端开不同的Socket
三、UDP协议
1. UDP基本特点
- 基于IP协议提供了:
复用和分用、最简单的错误校验 - "Best effort"服务:
尽力而为,UDP段不保证数据传输的可靠性,数据包可能会丢失或未按序到达 - 无连接
不需要进行握手、每个UDP段的处理独立于其它段,也不会维护连接的状态
2.UDP为什么存在?
- 无需建立连接 —— 减少延迟
- 实现简单 —— 无需维护连接状态
- 头部开销少—— TCP 20字节,UDP 8字节
- 没有拥塞控制 —— 应用层可更好的控制发送时间和速率
3.UDP的应用
- 用于流媒体应用 —— 容忍丢失、速率敏感
- 用于DNS协议 —— 使用UDP传输速度更快
- 用于RIP路由选择表的更新 —— 路由表更新迭代快
4.UDP首部格式
UDP首部包含:
- 源端口号:表示数据是从哪个进程来
- 目的端口号:表示数据是从要到哪个进程去
- 16位UDP长度:表示整个数据报(UDP首部+UDP数据)的最大长度
- 校验和:如果校验和出错, 就会直接丢弃
四、TCP协议
1.TCP概述
- 点对点:一个发送方,一个接收方
- 可靠的、按序的字节流
- 流水线机制:TCP有拥塞控制和流量控制
- 发送方接收方缓存
- 全双工:同一个连接中能够传输双向数据流
- 面向连接:
(1)通信双方在发送数据之前必须建立连接
(2)连接状态只在连接的两端中维护,在沿途的节点中并不维护 - TCP连接包括:两台主机上的缓存、连接状态变量、socket等
2. TCP报文段的结构
- 源/目的端口号: 表示数据是从哪个进程来, 到哪个进程去
- 32位序号:表示这个报文段数据的第一个开始字节的编号
- 32位确认号: 表示希望下一次收到的字节的序列号
- 4位TCP报头长度: 表示该TCP头部有多少个32位bit(有多少个4字节)
- 6位标志位:
URG: 紧急指针是否有效
ACK: 确认号是否有效
PSH: 提示接收端应用程序立刻从TCP缓冲区把数据读走
RST: 对方要求重新建立连接; 我们把携带RST标识的称为复位报文段
SYN: 请求建立连接; 我们把携带SYN标识的称为同步报文段
FIN: 通知对方, 本端要关闭了, 我们称携带FIN标识的为结束报文段 - 16位窗口大小: 接收窗口的大小,用在流量管理中
- 16位校验和: 如果校验和出错, 就会直接丢弃.
- 16位紧急指针: 标识哪部分数据是紧急数据;
这里的序列号是指每一个被分开的数据报中的第一个字节的标号而不是整个数据报的编号
确认序号表示的是希望接收的下一个字节的序列号,也表示在这个序列号之前的所以字节都以及被成功接收。
5.连接控制
(1)三次握手
三次握手流程:
- 首先客户端未开始发起连接时处于 CLOSE 状态,服务器处于LISTEN 状态。客户端发器链接时,首先发送一个不含有数据的特殊报文段,被称为SYN报文段。这个报文段中,首部标志位SYN置1表示请求建立连接,并且在首部的序列号中生成自己的传输数据的起始序列号:client_isn,一并发送到服务端。发送后,客户端状态变为 SYN_SENT
- 当服务器收到客户端的建立连接的请求时,就开始为此次连接创建缓存和变量。同时,服务端要向客户端发送请求连接以及确认应答的报文段,称之为SYNACK报文段。在这个报文段中,首部标志位SYN置1表示请求连接,并且服务端生成自己的发送数据起始序列号:sever_isn,同时要对客户端发来的SYN报文段进行确认,也就是将自己的ACK确认号设置为client_isn + 1,一并发回客户端。发送后,服务端状态变为SYN_RCVD
- 客户端收到SYNACK报文段后,也开始为此次连接创建缓存和变量。同时客户端要向服务端发送一个确认的ACK包。在这次的数据首部中,SYN就可以置0,ACK确认号就为sever_isn+1,序列号为client_isn + 1。同时第三次握手时可以携带数据。发送出后,客户端状态变为ESTABLISHED ,表示已经建立连接,服务端收到ACK包后,状态也变为ESTABLISHED 。至此,三次握手结束,两端正式建立连接。
(2)四次挥手
四次挥手流程:
- 客户端发起连接结束,发送一个FIN报文段,这个报文段首部的FIN标志位置1表示要断开连接。发送后,客户端状态变为FIN_WAIT1 状态
- 服务端接收到这个报文段后,得知客户端想断开连接,首先发送一个ACK报文段表示收到这个请求,发送后服务端状态变为CLOSE_WAIT状态,此时服务端不会立马断开连接,而是等待将所有未传输完的报文都传输给客户端后,再准备断开连接。客户端接收到这个ACK报文段后,状态变为FIN_WAIT2
- 当服务端准备好断开连接时,会主动发送一个FIN报文段给客户端,表示已经可以断开连接了。发送这个报文段后,服务端的状态就变为LAST_ACK
- 客户端收到这个FIN报文段后,就会回发一个ACK包给服务端,表示已经收到了,此时服务端收到后就关闭了连接,而客户端进入TIME_WAIT,这个阶段客户端会等待一段时间后才关闭连接,以确保服务端确实收到了ACK包,否则如果ACK丢失就会进行重传。至此四次挥手结束,客户端服务端正式断开连接。
常见问题:
📌为什么要进行三次握手,两次可以吗?四次呢?
答:两次握手不可以,四次握手没必要
三次握手可以使客户端和服务端都得到 自身和对方的发送接收数据报的能力使正常的:
- 第一次握手后,服务端得知客户端的发送能力和自己的接收能力是正常的
- 第二次握手后,客户端得知自己的发送能力接收能力以及服务端的发送能力接收能力是正常的
- 第三次握手后,服务端得知客户端的接收能力和自己发送能力是正常的
通过这三次的握手,使连接两端都确定了发送接收能力的正常。显然两次还不够,三次刚刚好,四次也没有必要了。
另外一个原因就是,防止创建一些过期或者重复的连接。比如之前客户端发送了第一次握手的SYN包,但由于网络问题延时了,客户端会重发一个包建立连接,成功建立连接后,之前的延时包到达了,此时服务端就会准备建立连接,如果只有两次握手,那这个连接就被成功建立,而显然连接建立后客户端不会有进一步的操作了,这就会不断创建空的连接。而使用三次握手,由于缺少第三次握手,服务端没有等到最后的ACK包,导致连接没有成功建立,也就避免上面的问题。
📌为什么要进行四次挥手?
在这之前,要明白——发送FIN不是表示立马断开连接,而是本端没有继续要发送的数据了
这样再来看,客户端发送FIN后,表示没有需要发送的数据了,但它仍然使可以接收数据的。服务端接收到FIN也不会立即关闭,因为这只表示对端没有数据要发了,而服务端的数据还没发完。所以服务端先回应一个ACK后将自己所有的数据都发完后再次进行发送FIN表示服务端也没有数据要发送了,但这个FIN必须要让客户端接收到,否则客户端就会进行“傻等”。因此还需要客户端发送最后一次的确认ACK包。所以,四次挥手一次都不可缺少!
📌为什么要有TIME_WAIT 状态?
TIME_WAIT 状态就是最后一次握手中,客户端发送ACK后会等待一段时间保证对端成功接收到确认包。
如果没有,试想一下当ACK并没有到达服务端,服务端判断超时后就会重复的发送FIN包。如果有一个相同地址的连接再次建立,就会莫名收到一个FIN结束连接的报文段,这就会造成很大的影响,所以必须要有这个状态确保在本连接断开前,所有相关的报文都已经从网络上消失,所以一定要使得服务器收到了最后的ACK报文段。
4. 可靠传输的保证
我们已经知道了,TCP协议是一个可靠的传输协议。相比于UDP协议,它在应用层做了更多的工作,那么TCP是怎样保证可靠传输的呢?
(1)数据流编号
TCP协议是面向字节流传输的,它可以将上层传来的所有数据流进行编号,然后对数据进行分包按序发送。而UDP只能直接发送所有的数据并不会进行分包分组发送。
(2) 确认重传机制
首先想到需要解决的问题就是丢包和延时到达的问题,如果数据报在传输中丢失,那对于TCP协议就一定要在传输层做出反应,这个反应就是确认重传。
怎么知道丢包了呢?这就使用到了上面介绍了的TCP的首部结构中的有两个数据分别是序列号和确认号。
在建立连接时,接收端和发送端都指定了自己开始发送字节流的序列号,每次接收端收到数据报后就会将收到的序列号+1作为确认号ACK发送给发送端。这样发送端接收到,就知道对端已经收到了自己的这个序列号的数据报。
所以,如果发生了丢包和延时,发送端就会收不到对端的ACK包,如果到达一定的时间,发送端就会重新再次发送未被确认的包,直到收到该序列号的ACK包后才继续发送接下来的数据。因此TCP协议使用序列号和确认号,实现了发送端和接收端的“交流”保证了数据报可以安全的到达对端。
(3) 流量控制
我们都知道,TCP的发送端和接收端都有缓存。对于发送端而言,可以控制自己的发送速度,对于接收端而言只能无条件接受,但如果接收端的缓存区满了而发送端还是不停的发送数据,就会造成数据报的丢失。所以TCP实现了流量控制,以便于发送端能感知接收端的剩余缓存大小,来合适的调整发送速率。
这里用到了TCP首部的数据:接收窗口。这个窗口就用来表示接收端剩余可接收数据报的大小。每次接收端向发送端发送数据报时就会在首部的接收窗口位置加上自己缓冲区的剩余大小。这样发送端收到后就根据这个大小来控制发送。
如果接收窗口为0表示已经没有缓冲区了,需要让发送端停止发送一段时间。此时为了能实时获取接收窗口的修改,发送端会每隔一段时间发送一个很小的数据包来试探,接收端就会再次发送自己的接收窗口大小,如果不为零,发送端恢复发送。
(4)拥塞控制
很多人会将流量控制和拥塞控制搞混,其实,流量控制是对于接收端的接受能力而言,而拥塞控制是对于整个网络而言,当整个网络相对拥塞时,TCP协议也会做出反应,适当降低自己的发送数据包的数量。拥塞控制也有个相关数值就是拥塞窗口表示每次能发送的数据报的数量。发送端每次发送的数据包数量为接受窗口和拥塞窗口的最小值。
整个拥塞控制有三个阶段,分别是慢启动、拥塞避免、快速恢复
阶段一:慢启动
在建立连接时,拥塞窗口的初始值为1,也就是第一次只发送一个数据报,当收到这次发送的数据报应答后,拥塞窗口的大小变为之前的两倍就是2。相应的,如果成功接收到第二次的这两个数据报,那拥塞窗口就调整为4,以此类推。
那什么时候会停下慢启动呢?
- 超时没收到ACK,表示丢包。此时将拥塞窗口值减为1,再次进行慢启动过程。这里又有一个变量:慢启动阈值,这个慢启动阈值被设置为上次达到拥塞后的拥塞窗口的一半。
- 当拥塞窗口当前的值达到或超过了慢启动阈值,也就是达到了上次拥塞时拥塞窗口值得一半,此时在进行翻倍就有些“鲁莽”,所以此时结束慢启动,并进入拥塞避免模式。
- 收到3个冗余的ACK,表示网络已经有些拥堵,但也不至于直接减为1,此时执行快速重传并进入快速恢复模式。
快速重传是在收到3个冗余ACK后的反应,此时TCP认为在这冗余的ACK后的数据均已经丢失,于是就会在下一次超时之前就将丢失的报文段快速重传到接收端。
阶段二:拥塞避免
在拥塞避免这个阶段,表示当前已经达到了慢启动阈值,此时不进行继续翻倍,而是线性增长,一次只+1,这样可以保证更加的稳妥。
何时结束拥塞避免呢?
- 出现超时丢包时:与前面一样,慢启动阈值更新为拥塞窗口的一半且拥塞窗口减为1,重新进入慢启动。
- 出现3个冗余ACK:慢启动阈值更新为拥塞窗口的一半且拥塞窗口值减半,进入快速恢复状态
阶段三:快速恢复
在快速恢复状态中,对于收到的每一个冗余的ACK,拥塞窗口+1,最终当丢失的报文段的ACK到达后,TCP降低拥塞窗口值并进入拥塞避免状态。当然如果出现超时丢包后,拥塞窗口还是减为1进入慢启动。
以上就是我认为传输层需要掌握的重点知识的总结,也适合面试前的突击复习,多多总结能让整个知识体系更加清晰。如果有任何问题欢迎指正,也欢迎小伙伴们点赞关注一起进步。