先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Web前端全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。






既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果你需要这些资料,可以添加V获取:vip1024c (备注前端)

正文
1.3 可靠性
=======
我们都知道 TCP 是具有可靠性的通信协议,它主要通过以下方式确保可靠性,这里先了解一下可靠性的原理,其中细节部分后文会讲:
-
合理的数据大小:TCP 发送的数据并不是固定的大小,而是会根据实际情况调整报文段的大小。
-
检验和:发送端按照特定算法计算出 TCP 报文段的检验和并存储在 TCP 首部中的对应字段上,接收端在接收时会以同样的方式计算校验和,如果不一致,说明报文段出现错误,会将其丢弃。
-
序号与确认序号:对乱序的数据进行排序后发给应用层,并丢弃重复的数据。
-
超时重传机制:当 TCP 发出一个报文段后,它会启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段,后面会细讲这个机制。
-
连接管理:也就是三次握手和四次挥手,连接的可靠性是整体可靠性的前提,本文第二部分将会详细介绍连接管理的内容。
-
流量控制:TCP 双方都有固定大小的缓冲区,流量控制的原理是利用滑动窗口控制数据发送速度,避免缓冲区溢出导致数据丢失。
-
拥塞控制:TCP 利用慢启动和拥塞避免等算法实现了拥塞控制。
上面为大家介绍了 TCP 最重要的三个特点,在本文第一部分的最后,再来看看 TCP 和 UDP 的对比吧。
1.4 TCP 和 UDP 的区别
=================
UDP | TCP | |
是否连接 | 无连接 | 面向连接 |
是否可靠 | 不可靠,没有确认机制、流量控制和拥塞控制 | 可靠,有确认机制、流量控制和拥塞控制 |
连接对象个数 | 支持一对一,一对多,多对一和多对多交互通信 | 只支持一对一通信 |
传输方式 | 面向报文 | 面向字节流 |
首部开销 | 首部开销小,固定8字节 | 首部开销较大,最小20字节,最大60字节 |
适用场景 | 适用于实时应用(IP电话、视频会议、直播等) | 适用于要求可靠传输的应用,如文件传输等 |
二、TCP 的连接控制
===========
2.1 建立连接
========
2.1.1 三次握手
==========
这个问题简直太经典了,如果你在面试中只被问到了一个关于 TCP 的问题,那大概率就是关于三次握手的问题。TCP 的重要特性之一就是面向连接,连接双方在发送数据之前必须经历握手的阶段,那具体的过程是怎样的呢?先来看图,大家最好可以动手简单画画这个图,当然还有后文四次挥手的图,帮助加深记忆。

三次握手过程
如图所示,双方之间的三个蓝色箭头就表示了三次握手过程中所发生的数据交换:
-
第一次握手:客户端向服务器发送报文段1,其中的 SYN 标志位 (前文已经介绍过各种标志位的作用)的值为 1,表示这是一个用于请求发起连接的报文段,其中的序号字段 (Sequence Number,图中简写为seq)被设置为初始序号x (Initial Sequence Number,ISN),TCP 连接双方均可随机选择初始序号。发送完报文段1之后,客户端进入 SYN-SENT 状态,等待服务器的确认。
-
第二次握手:服务器在收到客户端的连接请求后,向客户端发送报文段2作为应答,其中 ACK 标志位设置为 1,表示对客户端做出应答,其确认序号字段 (Acknowledgment Number,图中简写为小写 ack) 生效,该字段值为 x + 1,也就是从客户端收到的报文段的序号加一,代表服务器期望下次收到客户端的数据的序号。此外,报文段2的 SYN 标志位也设置为1,代表这同时也是一个用于发起连接的报文段,序号 seq 设置为服务器初始序号y。发送完报文段2后,服务器进入 SYN-RECEIVED 状态。
-
第三次握手:客户端在收到报文段2后,向服务器发送报文段3,其 ACK 标志位为1,代表对服务器做出应答,确认序号字段 ack 为 y + 1,序号字段 seq 为 x + 1。此报文段发送完毕后,双方都进入 ESTABLISHED 状态,表示连接已建立。
常见面试题 1:TCP 建立连接为什么要三次握手而不是两次?
答:网上大多数资料对这个问题的回答只有简单的一句:防止已过期的连接请求报文突然又传送到服务器,因而产生错误,这既不够全面也不够具体。下面给出比较详细而全面的回答:
-
防止已过期的连接请求报文突然又传送到服务器,因而产生错误在双方两次握手即可建立连接的情况下,假设客户端发送 A 报文段请求建立连接,由于网络原因造成 A 暂时无法到达服务器,服务器接收不到请求报文段就不会返回确认报文段,客户端在长时间得不到应答的情况下重新发送请求报文段 B,这次 B 顺利到达服务器,服务器随即返回确认报文并进入 ESTABLISHED 状态,客户端在收到 确认报文后已进入 ESTABLISHED 状态,双方建立连接并传输数据,之后正常断开连接。此时姗姗来迟的 A 报文段才到达服务器,服务器随即返回确认报文并进入 ESTABLISHED 状态,但是已经进入 CLOSED 状态的客户端无法再接受确认报文段,更无法进入 ESTABLISHED 状态,这将导致服务器长时间单方面等待,造成资源浪费。
-
三次握手才能让双方均确认自己和对方的发送和接收能力都正常第一次握手:客户端只是发送处请求报文段,什么都无法确认,而服务器可以确认自己的接收能力和对方的发送能力正常;第二次握手:客户端可以确认自己发送能力和接收能力正常,对方发送能力和接收能力正常;第三次握手:服务器可以确认自己发送能力和接收能力正常,对方发送能力和接收能力正常;可见三次握手才能让双方都确认自己和对方的发送和接收能力全部正常,这样就可以愉快地进行通信了。
-
告知对方自己的初始序号值,并确认收到对方的初始序号值TCP 实现了可靠的数据传输,原因之一就是 TCP 报文段中维护了序号字段和确认序号字段,也就是图中的 seq 和 ack,通过这两个字段双方都可以知道在自己发出的数据中,哪些是已经被对方确认接收的。这两个字段的值会在初始序号值得基础递增,如果是两次握手,只有发起方的初始序号可以得到确认,而另一方的初始序号则得不到确认。
常见面试题2:TCP 建立连接为什么要三次握手而不是四次?
答:相比上个问题而言,这个问题就简单多了。因为三次握手已经可以确认双方的发送接收能力正常,双方都知道彼此已经准备好,而且也可以完成对双方初始序号值得确认,也就无需再第四次握手了。
常见面试题3:有一种网络攻击是利用了 TCP 建立连接机制的漏洞,你了解吗?这个问题怎么解决?
答:在三次握手过程中,服务器在收到了客户端的 SYN 报文段后,会分配并初始化连接变量和缓存,并向客户端发送 SYN + ACK 报文段,这相当于是打开了一个“半开连接 (half-open connection)”,会消耗服务器资源。如果客户端正常返回了 ACK 报文段,那么双方可以正常建立连接,否则,服务器在等待一分钟后会终止这个“半开连接”并回收资源。这样的机制为 SYN洪泛攻击 (SYN flood attack)提供了机会,这是一种经典的 DoS攻击 (Denial of Service,拒绝服务攻击),所谓的拒绝服务攻击就是通过进行攻击,使受害主机或网络不能提供良好的服务,从而间接达到攻击的目的。在 SYN 洪泛攻击中,攻击者发送大量的 SYN 报文段到服务器请求建立连接,但是却不进行第三次握手,这会导致服务器打开大量的半开连接,消耗大量的资源,最终无法进行正常的服务。
解决方法:SYN Cookies,现在大多数主流操作系统都有这种防御系统。SYN Cookies 是对 TCP 服务器端的三次握手做一些修改,专门用来防范 SYN 洪泛攻击的一种手段。它的原理是,在服务器接收到 SYN 报文段并返回 SYN + ACK 报文段时,不再打开一个半开连接,也不分配资源,而是根据这个 SYN 报文段的重要信息 (包括源和目的 IP 地址,端口号可一个秘密数),利用特定散列函数计算出一个 cookie 值。这个 cookie 作为将要返回的SYN + ACK 报文段的初始序列号(ISN)。当客户端返回一个 ACK 报文段时,服务器根据首部字段信息计算 cookie,与返回的确认序号(初始序列号 + 1)进行对比,如果相同,则是一个正常连接,然后分配资源并建立连接,否则拒绝建立连接。
2.2.2 同时打开
==========
这是 TCP 建立连接的特殊情况,有时会出现两台机器同时执行主动打开的情况,不过概率非常小,这种情况大家仅作了解即可。在这种情况下就无所谓发送方和接收方了,双放都可以称为客户端和服务器,同时打开的过程如下:

同时打开的过程
如图所示,双方在同一时刻发送 SYN 报文段,并进入 SYN-SENT 状态,在收到 SYN 后,状态变为 SYN-RECEIVED,同时它们都在发送一个 SYN + ACK 的报文段,状态都变为 ESTABLISHED,连接成功建立。在此过程中双方一共交换了4个报文段,比三次握手多一个。
2.2 关闭连接
========
2.2.1 四次挥手
==========
建立一个连接需要三次握手,而终止一个连接要经过 4次握手。这由 TCP 的半关闭( half-close) 造成的。既然一个 TCP 连接是全双工 (即数据在两个方向上能同时传递), 因此每个方向必须单独地进行关闭。这原则就是当一方完成它的数据发送任务后就能发送一个 FIN 来终止这个方向连接。当一端收到一个 FIN,它必须通知应用层另一端已经终止了数据传送。理论上客户端和服务器都可以发起主动关闭,但是更多的情况下是客户端主动发起。

四次挥手过程
四次挥手详细过程如下:
-
客户端发送关闭连接的报文段,FIN 标志位1,请求关闭连接,并停止发送数据。序号字段 seq = x (等于之前发送的所有数据的最后一个字节的序号加一),然后客户端会进入 FIN-WAIT-1 状态,等待来自服务器的确认报文。
-
服务器收到 FIN 报文后,发回确认报文,ACK = 1, ack = x + 1,并带上自己的序号 seq = y,然后服务器就进入 CLOSE-WAIT 状态。服务器还会通知上层的应用程序对方已经释放连接,此时 TCP 处于半关闭状态,也就是说客户端已经没有数据要发送了,但是服务器还可以发送数据,客户端也还能够接收。
-
客户端收到服务器的 ACK 报文段后随即进入 FIN-WAIT-2 状态,此时还能收到来自服务器的数据,直到收到 FIN 报文段。
-
服务器发送完所有数据后,会向客户端发送 FIN 报文段,各字段值如图所示,随后服务器进入 LAST-ACK 状态,等待来自客户端的确认报文段。
-
客户端收到来自服务器的 FIN 报文段后,向服务器发送 ACK 报文,随后进入 TIME-WAIT 状态,等待 2MSL(2 * Maximum Segment Lifetime,两倍的报文段最大存活时间) ,这是任何报文段在被丢弃前能在网络中存在的最长时间,常用值有30秒、1分钟和2分钟。如无特殊情况,客户端会进入 CLOSED 状态。
-
服务器在接收到客户端的 ACK 报文后会随即进入 CLOSED 状态,由于没有等待时间,一般而言,服务器比客户端更早进入 CLOSED 状态。
常见面试题1:为什么 TCP 关闭连接为什么要四次而不是三次?
答:服务器在收到客户端的 FIN 报文段后,可能还有一些数据要传输,所以不能马上关闭连接,但是会做出应答,返回 ACK 报文段,接下来可能会继续发送数据,在数据发送完后,服务器会向客户单发送 FIN 报文,表示数据已经发送完毕,请求关闭连接,然后客户端再做出应答,因此一共需要四次挥手。
常见面试题2:客户端为什么需要在 TIME-WAIT 状态等待 2MSL 时间才能进入 CLOSED 状态?
答:按照常理,在网络正常的情况下,四个报文段发送完后,双方就可以关闭连接进入 CLOSED 状态了,但是网络并不总是可靠的,如果客户端发送的 ACK 报文段丢失,服务器在接收不到 ACK 的情况下会一直重复 FIN 报文段,这显然不是我们想要的。因此客户端为了确保服务器收到了 ACK,会设置一个定时器,并在 TIME-WAIT 状态等待 2MSL 的时间,如果在此期间又收到了来自服务器的 FIN 报文段,那么客户端会重新设置计时器并再次等待 2MSL 的时间,如果在这段时间内没有收到来自服务器的 FIN 报文,那就说明服务器已经成功收到了 ACK 报文,此时客户端就可以进入 CLOSED 状态了。
2.2.2 同时关闭
==========
之前在介绍 TCP 建立连接的时候会有一种特殊情况,那就是同时打开,与之对应地, TCP 关闭时也会有一种特殊情况,那就是同时关闭,这种情况仅作了解即可,流程图如下:

同时关闭过程
这种情况下,双方应用层同时发出关闭命令,这将导致双方各发送一个 FIN,两端均从 ESTABLISHED 变为 FIN_WAIT_1,两个 FIN 经过网络传送后分别到达另一端。收到 FIN 后,状态由 FIN_WAIT_1 变迁到 CLOSING,并发送最后的 ACK,当收到最后的 ACK 时,为确保对方也收到 ACK,状态变化为 TIME_WAIT,并等待 2MSL 时间,如果一切正常,随后会进入 CLOSED 状态。
三、TCP 的流量控制与滑动窗口
================
3.1 什么是流量控制?
============
TCP 连接双方的主机都为该连接设置了发送缓存和接收缓存,这些缓存起到了蓄水池的作用,我们肯定不能把上层应用程序发来的数据一股脑儿发送到网络中,而是利用发送缓存将其缓存起来,然后再按一定的速率通过网络发送给对方,而接收缓存的作用是把对方传来的数据先缓存起来,等到己方应用程序有空的时候再来取走数据。示意图如下:

TCP 缓存示意图
在此过程中,如果接收方应用程序读取数据的速度小于发送方的数据发送速度,将导致接收方的接收缓存溢出,造成数据丢失,这显然不是我们想看到的。因此 TCP 为应用程序提供了流量控制服务 (flow-control service),以消除发送方使接收方的接收缓存溢出的可能性。简单来说流量控制的目的就是协调发送方的数据发送速度,使其与接收方的数据处理速度相匹配,避免数据丢失,那么如何实现流量控制呢?
3.2 早期的流量控制模式——停止-等待模式 (stop-wait)
==================================
顾名思义就是发送方在发送一个数据包后就停止发送,等待对方响应 ACK,然后才能继续发送数据。这种模式的具体实现为 Positive Acknowledgment With Retransmission (PAR),意为带重传的肯定确认协议,其实现方式如下图所示:

PAR 示意图
这种实现很简单,发送方在发送数据包 (图中的msg)时会设置一个计时器,然后等待接收方的 ACK,接收方在收到数据后会返回 ACK 作为应答,发送方在收到 ACK 后会发送下一个数据包。如果由于网络原因造成数据包或者 ACK 丢失时,计时器会超时,然后发送方会重新发送未被确认的数据包。可以看到,这种模式虽然可以确保数据传输的可靠性,但是有个致命的缺点,那就是效率太低?如果是你,你会怎么对这个方案进行优化呢?
既然每次发送只一个数据包效率太低,那就多发送几个,然后给这些数据包编上号,接收端必须对每一个包进行确认,这样设备 A 一次多发送几个片段,而不必等候 ACK,同时接收端也要告知它能够收多少,这样发送端发起来也有个限制,当然还需要保证顺序性,不要乱序,对于乱序的状况,我们可以允许等待一定情况下的乱序,比如说先缓存提前到的数据,然后去等待需要的数据,如果一定时间没来就丢掉乱序的数据,来保证顺序性,这样的话,数据传输效率就可以大大提高。不过 TCP 也没有采用这种方案,而是在此基础上实现更加复杂的滑动窗口。
3.3 滑动窗口
========
首先给大家推荐一个视频,讲得很不错
https://www.bilibili.com/vide…
我们可以把发送方的发送缓存中的字节分为以下四类,每个编号对应一个字节:

发送缓存中的字节分类
-
第一类:已发送且已确认,这些数据已经发送成功并已经被确认的数据,比如图中的前31个bytes,这些数据其实的位置是在窗口之外了,下一步将被移出发送缓存。窗口内顺序最低的字节被确认之后,窗口左边界会向右移动,称为窗口合拢。
-
第二类:已发送但未收到确认,这部分数据已经被发送出去,但是还没有收到接收端的 ACK,认为并没有完成发送,这部分数据属于窗口内的数据。
-
第三类:未发送但是接收方已经准备好接收,这部分是尽快发送的数据,这部分数据已经被加载到缓存中,也在发送窗口中,正在等待发送,其实这个窗口是完全有接收方告知的,接收方告知当前可以接受这些数据,所以发送方需要尽快的发送。
-
第四类:未发送且接收方未准备好接收,这些数据属于未发送,同时接收端也不允许发送的,因为这些数据已经超出了发送端所接收的范围。
3.3.1 发送窗口和接收窗口
===============

发送窗口
发送窗口:图中的黑色框就是发送方的发送窗口,其大小由两个因素决定:1、接收方的提供的窗口大小 (TCP 报文段首部中的 window 字段),发送方在三次握手阶段首次得到这个值,之后的通信过程中接收方会根据自己的可用缓存对这个值进行动态调整;2、发送方会根据网络情况维护一个拥塞窗口变量 (后文介绍)。发送窗口的大小取这两个值的最小值。对于发送方来说,发送窗口分为两部分,分别是已经发送的部分(已经发送了,但是没有收到ACK)和可用窗口,接收端允许发送但是没有发送的那部分称为可用窗口。
接收窗口:对于接收端也是有一个接收窗口的,类似发送端,接收端的数据有3个分类,因为接收端并不需要等待ACK所以它没有类似的接收并确认了的分类,情况如下
-
Received and ACK Not Send to Process:这部分数据属于接收了数据但是还没有被上层的应用程序接收;
-
Received Not ACK: 已经接收,但是还没有回复 ACK;
-
Not Received:有空位,还没有被接收的数据。
3.3.2 滑动窗口是如何滑动的?
=================

滑动窗口的滑动过程
累积确认概念:TCP 并不是每一个报文段都会回复一个 ACK ,可能会对两个报文段发送一个ACK,也可能会对多个报文段发送 1 个 ACK,这称为累积确认。比如说发送方有 1/2/3 3 个报文段,先发送了2,3 两个报文段,但是接收方期望收到1报文段,这个时候 2/3 报文段就只能放在缓存中等待报文1的空洞被填上,如果报文段1一直不来,报文2/3也将被丢弃,如果报文1来了,那么会发送一个 ACK 对第3个报文段进行确认,就代表对这三个报文段全部进行了确认。
下面举例说明一下窗口滑动的过程:
-
在握手过程中,接收方通告的窗口大小为20字节,所以发送方将发送窗口大小设置为20字节。
-
从图中的"上一个发送窗口的位置"(灰色虚线框)说起, 32-51号字节恰好处于发送窗口中,恰好20个字节,假设 TCP 将其分为 4 个报文段进行发送,每个报文段 5 个字节数据,分别记为 seg1 32-36, seg2 37-41, seg3 42-46, seg4 47-51。
-
TCP 将有序发送 seg1、seg2、seg3和seg4四个报文段,如果这四个报文段都顺利到达接收方 (图中并不是这样),接收方将发回一个累积确认的 ACK 报文段,其中 ack = 52,代表希望收到下一个报文段的起始字节编号,报文段中也会继续通告窗口大小,如果还是20字节,那么发送方的窗口将整体向右移动20字节,如果通告的窗口值变小,比如变成15,那么发送窗口左边界移动20字节,右边界移动15字节。
-
如果在发送过程中 seg2 报文段丢失,而其他三个报文段正常到达接收方,那么接收方会现接受这三个报文段,然后返回 ACK 报文段,ack = 37,表示希望收到的下一个报文段的起始字节号为37,也就是seg2报文段。如果通告窗口值未发生变化,发送方在收到 ACK 后会将窗口整体右移5个字节,也就变成了图中的位置。
-
由于 seg2 还未收到 ACK,当重传计时器超时后,发送方会重新发送 seg2,此时52-56号字节又落到了发送窗口中,TCP 将其封装成 报文段进行发送,如果接收方全部顺利收到,会返回一个累积确认的 ACK,ack = 57,表示希望收到的喜爱个报文段的起始字节号为57。
接下来就是重复上述过程,直到 TCP 字节流的所有数据发送完毕。在这个过程中,接收方会根据自己接收缓存的剩余空间动态调整窗口值,对发送方进行流量控制。文字描述可能不够直观,大家可以参考上文推荐的视频。另外推荐一个动图演示的网站 动画地址 ,可以观看滑动窗口的动态效果,如下图 (此演示未考虑丢包的情况):

滑动窗口动画效果
四、TCP 的拥塞控制
===========
最后
其实前端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。
这里再分享一个复习的路线:(以下体系的复习资料是我从各路大佬收集整理好的)
《前端开发四大模块核心知识笔记》

最后,说个题外话,我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。
我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在IT学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
_convert/b6ecb2c71421efff2a0cd1db5a9d4251.png)
最后,说个题外话,我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。
我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在IT学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
[外链图片转存中…(img-Usx3emSK-1713553258226)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
14万+

被折叠的 条评论
为什么被折叠?



