Skip to content

Commit

Permalink
feat: 数个前端计网八股
Browse files Browse the repository at this point in the history
  • Loading branch information
shipiyouniao committed Sep 18, 2024
1 parent b1dde33 commit 20491f7
Show file tree
Hide file tree
Showing 4 changed files with 201 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## 希尔排序原理

希尔排序(Shell Sort)是一种基于插入排序的排序算法,通过将数组分成若干子序列分别进行插入排序,从而加快排序速度。希尔排序的核心思想是先将整个待排序的记录序列分割成若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。
希尔排序(Shell Sort)是一种基于[插入排序](../3.%20插入排序/index.md)的排序算法,通过将数组分成若干子序列分别进行插入排序,从而加快排序速度。希尔排序的核心思想是先将整个待排序的记录序列分割成若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。

希尔排序的时间复杂度在最坏情况下为 O(n^2),在平均情况下为 O(n log n),空间复杂度为 O(1)。

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
**本模块是公共类课程,适合绝大部分计算机岗位。但服务端岗位只需要简单学习 HTTP,不需要了解 TLS 协议具体内容**
**本模块是公共类课程,适合绝大部分计算机岗位。但部分内容若非`前端开发``移动端开发``客户端(桌面应用、游戏开发)`等“大前端”岗位则了解即可。**

## 讲讲 Http 和 Https 的区别

Expand Down Expand Up @@ -32,13 +32,16 @@ WebSocket 是一种全双工通信协议,它可以在客户端和服务器之

## 讲讲常见的 HTTP 状态码

HTTP 状态码是 HTTP 协议中的一种响应状态码,主要有以下几种状态码:
HTTP 状态码是 HTTP 协议中的一种响应状态码,主要有以下几种状态码:(没必要背,了解即可,面试要是考这些死记硬背的东西就太蠢了)

1. 1xx:信息状态码,表示请求已接收,继续处理。
- 101 Switching Protocols:切换协议,比如 HTTP 升级为 WebSocket 协议。
2. 2xx:成功状态码,表示请求已成功接收、理解、接受。
- 200 OK:请求成功。
- 201 Created:请求已创建。
- 202 Accepted:请求已接受。
- 204 No Content:无内容。(没有 body 内容)
- 206 Partial Content:部分内容。(分块传输)
3. 3xx:重定向状态码,表示需要进一步操作以完成请求。
- 301 Moved Permanently:永久重定向。
- 302 Found:临时重定向。
Expand All @@ -49,9 +52,17 @@ HTTP 状态码是 HTTP 协议中的一种响应状态码,主要有以下几种
- 403 Forbidden:禁止访问。
- 404 Not Found:未找到。
- 405 Method Not Allowed:方法不允许。
- 406 Not Acceptable:资源满足不了请求头中的条件。
- 408 Request Timeout:请求超时。
- 409 Conflict:多个请求发生冲突。
- 413 Payload Too Large:请求体太大。
- 414 URI Too Long:URI 太长。
- 429 Too Many Requests:请求过多。
- 431 Request Header Fields Too Large:请求头字段太大。
5. 5xx:服务器错误状态码,表示服务器无法完成明显有效的请求。
- 500 Internal Server Error:服务器错误。
- 501 Not Implemented:未实现。
- 502 Bad Gateway:网关错误。
- 503 Service Unavailable:服务不可用。

HTTP 状态码主要是为了表示请求的处理结果,根据不同的状态码进行不同的处理。
Expand All @@ -75,4 +86,90 @@ WebSocket 连接断开的详细过程如下:
2. 对方返回关闭连接响应,响应头中包含`Connection: close`字段。
3. 客户端或服务器收到关闭连接响应,连接断开成功。

总的来说,进行了一次握手,不过如果算上 TCP 的四次挥手,其实是五次挥手。
总的来说,进行了一次握手,不过如果算上 TCP 的四次挥手,其实是五次挥手。

## 讲讲 HTTP 报文的结构(非“大前端”岗位了解即可)

HTTP/1.1 报文主要分为请求报文和响应报文,结构如下:

1. 请求报文:
- 请求行:包含请求方法、请求 URL、HTTP 版本。格式为`<method> <URL> <version>`,如`GET /index.html HTTP/1.1`
- 请求头:包含请求头字段和请求头值。格式为`<header>: <value>`,如`Host: www.example.com`,不止一行,多个不同的请求头会用换行符分隔。
- 空行:请求头和请求体之间的空行。
- 请求体:包含请求参数和请求数据。

2. 响应报文:
- 状态行:包含 HTTP 版本、状态码、状态消息。格式为`<version> <status code> <status message>`,如`HTTP/1.1 200 OK`
- 响应头:包含响应头字段和响应头值。格式为`<header>: <value>`,如`Content-Type: text/html`,不止一行,多个不同的响应头会用换行符分隔。
- 空行:响应头和响应体之间的空行。
- 响应体:包含响应数据和响应结果。

报文头总体结构遵守以下规则:

1. 字段名不区分大小写
2. 字段名不允许出现空格和下划线
3. 字段名后面紧跟一个冒号

此外,每一行后都以遵守`ABNF`规则的`CRLF`(回车换行)结尾。

## 讲讲 URI 的结构(非“大前端”岗位了解即可)

URI(Uniform Resource Identifier)是统一资源标识符,用于标识互联网上的资源,主要包括 URL 和 URN 两种形式。

URI 的结构:`scheme://authority/path?query#fragment`,具体如下:
- `scheme`:协议名称,如`http``https`
- `authority`:资源的所有者或者管理者,结构为`[user:password@]host[:port]`
- `path`:资源的路径,如`/index.html`
- `query`:查询参数,如`?id=1`
- `fragment`:片段标识符,如`#section1`

但要注意,直接在 URI 当中包含用户名和密码是不安全的,请尽可能避免这种情况,即便在内网环境下也要注意。

URI 的编码是 ASCII 字符集的超集,所有非 ASCII 字符和界定符都转为`%`加上两位十六进制数,如空格转为`%20`

## 如何在 HTTP/1.1 解决队头阻塞问题(非“大前端”岗位了解即可)

队头阻塞是指在 HTTP/1.1 中,传输是一问一答的,每个任务都放在队列中,只有前一个任务完成后,才能进行下一个任务,一旦前一个任务耗时过长,会导致后续任务等待时间过长,影响性能。

如果要在 HTTP/1.1 中解决队头阻塞问题,可以采用以下几种方法:

1. **并发连接**:通过并发连接,可以同时发送多个请求,提高并发性能。Chrome 浏览器默认支持 6 个并发连接。
2. **域名分片**:通过域名分片,可以将资源分散到不同的域名下,提高并发性能。如`www.example.com``static.example.com`,不同二级域名都指向同一个服务器。

## 讲讲 HTTP/2 的改进点(非“大前端”岗位了解即可)

HTTP/2 是 HTTP/1.1 的升级版本,主要改进点如下:

1. **头部压缩**:HTTP/2 使用 HPACK 算法对头部进行压缩,减少头部大小,提高传输效率。客户端和服务端各自维护一个哈希索引表,用于存储头部字段和值,对于出现过的头部字段和值,只需要发送索引值(如`1``2`)即可,减少重复传输。此外,整数和字符串被进行了 Huffman 编码,减少了传输大小。
2. **多路复用**:HTTP/2 使用多路复用技术,可以在一个连接上同时传输多个请求和响应,避免队头阻塞问题,提高传输效率。多路复用是通过二进制分帧(Binary Framing)实现的,将请求和响应拆分为多个帧,每个帧通过流 ID 标识,不同流的帧可以混合在一起传输,没有先后顺序(同一个流的帧保持顺序),解决了排队等待的问题。
3. **服务器推送**:HTTP/2 支持服务器推送技术,服务器可以在客户端请求之前主动推送 HTML 引用的其他资源,提高性能。服务器推送是通过 PUSH_PROMISE 帧实现的,服务器在收到客户端请求后,可以主动推送资源,客户端可以选择接收或拒绝。

## 讲讲什么是 TLS/SSL 协议(非“大前端”岗位了解即可)

SSL(Secure Sockets Layer)是安全套接字层协议,在 OSI 模型中位于会话层,用于保护网络通信的安全性。SSL 发展到第三个大版本后,改名为 TLS(Transport Layer Security),TLS 1.0 实际上就是 SSL 3.1 版本。

不管是 HTTPS、WSS 还是 FTPS,只要后面多跟了一个 S,就表示是原有协议附上了 SSL/TLS 加密。

## TLS 1.2 是如何握手的(非“大前端”岗位了解即可)

TLS 1.2 一般使用 `ECDHE` (Elliptic Curve Diffie-Hellman Ephemeral)算法进行密钥交换,这个算法是一种基于椭圆曲线的密钥交换算法,可以实现前向保密性,保护通信的安全性。

过程主要分为以下几个步骤:

1. **客户端发送 ClientHello**:客户端向服务器发送 ClientHello 消息,包含支持的 TLS 版本、加密套件列表、随机数(client_random)等信息。

所谓加密套件,就是加密算法和哈希算法的组合,如`TLS_RSA_WITH_AES_128_CBC_SHA256`。意思是在 TLS 协议下,使用 RSA 算法进行密钥交换,128 位的 AES 算法进行对称加密,通过 CBC 分组模式,SHA256 哈希算法进行消息摘要。

2. **服务器发送 ServerHello**:服务器向客户端发送 ServerHello 消息,包含选择的 TLS 版本、加密套件、服务器证书、随机数(server_random)、参数(server_params)等信息。

3. **客户端验证服务器证书和签名**:客户端验证服务器证书的有效性,包括证书是否过期、证书是否被吊销、证书是否与域名匹配等。如果验证通过,传递 `client_params` 给服务器。此时可以提前抢跑,发送 HTTP 请求,节省一个 RTT,这个过程叫做`TLS False Start`

4. **双端生成密钥**:接下来,通过传入两个 `params` 参数,使用 `ECDHE` 算法生成 `pre_random`。最后通过三个随机数生成 `secret`,之后的通信都是通过这个 `secret` 进行加密解密。

值得一提的是,在之前的 TLS 加密协议中,主要以 RSA 算法为主。

RSA 算法是一种非对称加密算法,可以实现加密和解密,数字签名和验证,主要特点是公钥加密、私钥解密,公钥验证、私钥签名。

但由于 RSA 算法速度慢,且有安全隐患,在存在漏洞的情况下,如果被攻击者计算出了私钥,那么整个通信过程就会被破解。相比之下,即便攻击者计算出了 ECDHE 算法中的私钥,也只能破解当前通信,不会影响到其他通信。

因此,在 TLS 1.3 中,已经将 RSA 算法移除。
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
**本模块是公共类课程,适合绝大部分计算机岗位。**
**本模块是公共类课程,适合绝大部分计算机岗位。但部分内容若非`前端开发``移动端开发``客户端(桌面应用、游戏开发)`等“大前端”岗位则了解即可。**

## 讲讲 TCP 和 UDP 的区别

Expand Down Expand Up @@ -32,15 +32,15 @@ TCP 报文通常由长 20 字节的报文头(不计选项和填充字段的话
TCP 三次握手和四次挥手是 TCP 协议中的连接和断开过程,主要过程如下:

1. 三次握手:
1. 第一次握手:客户端发送 SYN 包,序列号 seq=x,进入 SYN-SENT 状态。
2. 第二次握手:服务器收到 SYN 包,发送 SYN+ACK 包,确认号 ack=x+1,序列号 seq=y,进入 SYN-RECEIVED 状态。
3. 第三次握手:客户端收到 SYN+ACK 包,发送 ACK 包,确认号 ack=y+1,进入 ESTABLISHED 状态。服务端收到 ACK 包,进入 ESTABLISHED 状态。
1. 第一次握手:客户端发送 `SYN` 包,序列号 `seq=x`,进入 `SYN-SENT` 状态。
2. 第二次握手:服务器收到 `SYN` 包,发送 `SYN+ACK` 包,确认号 `ack=x+1`,序列号 `seq=y`,进入 `SYN-RECEIVED` 状态。
3. 第三次握手:客户端收到 `SYN+ACK` 包,发送 `ACK` 包,确认号 `ack=y+1`,进入 `ESTABLISHED` 状态。服务端收到 `ACK` 包,进入 `ESTABLISHED` 状态。

2. 四次挥手:
1. 第一次挥手:客户端发送 FIN 包,序列号 seq=u,进入 FIN-WAIT-1 状态。
2. 第二次挥手:服务器收到 FIN 包,发送 ACK 包,确认号 ack=u+1,序列号 seq=v,进入 CLOSE-WAIT 状态。客户端收到 ACK 包,进入 FIN-WAIT-2 状态。
3. 第三次挥手:服务器发送 FIN 包,序列号 seq=w,进入 LAST-ACK 状态。
4. 第四次挥手:客户端收到 FIN 包,发送 ACK 包,确认号 ack=w+1,进入 TIME-WAIT 状态。间隔 2MSL 后,客户端进入 CLOSED 状态,服务器收到 ACK 包,进入 CLOSED 状态。
1. 第一次挥手:客户端发送 `FIN` 包,序列号 `seq=u`,进入 `FIN-WAIT-1` 状态。
2. 第二次挥手:服务器收到 `FIN` 包,发送 `ACK` 包,确认号 `ack=u+1`,序列号 `seq=v`,进入 `CLOSE-WAIT` 状态。客户端收到 `ACK` 包,进入 `FIN-WAIT-2` 状态。
3. 第三次挥手:服务器发送 `FIN` 包,序列号 `seq=w`,进入 `LAST-ACK` 状态。
4. 第四次挥手:客户端收到 `FIN` 包,发送 `ACK` 包,确认号 `ack=w+1`,进入 `TIME-WAIT` 状态。间隔 `2MSL` 后,客户端进入 `CLOSED` 状态,服务器收到 `ACK` 包,进入 `CLOSED` 状态。

TCP 三次握手和四次挥手是为了建立和断开 TCP 连接,保证数据的可靠传输。

Expand Down Expand Up @@ -77,3 +77,33 @@ TCP 的滑动窗口协议是为了实现流量控制,保证发送端和接收
3. 快重传(Fast Retransmit):发送端收到 3 个重复的 ACK 包,说明某个数据包丢失,立即重传丢失的数据包,而不是等待超时重传。此时慢启动阈值设置为拥塞窗口的一半,拥塞窗口大小设置为新的慢启动阈值加上 3 个 MSS(因为已经收到三个重复的 ACK 包),重新进入慢启动阶段。

TCP 的拥塞控制机制是为了防止网络拥塞,保证数据的可靠传输,提高网络的性能和可靠性。

## 说说半连接队列和 SYN Flood 攻击的关系(非“大前端”岗位了解即可)

### 半连接队列

在 TCP 三次握手前,服务器状态从 `CLOSED` 变为 `LISTEN`,此时服务器会创建一个半连接队列(SYN Queue)和一个全连接队列(Accept Queue)。

当客户端发送 `SYN` 包时,服务器回复 `SYN+ACK` 包,此时状态变成 `SYN-RECEIVED`,此时连接就被放入半连接队列中。

当客户端发送 `ACK` 包时,服务器状态变为 `ESTABLISHED`,此时连接就被放入全连接队列中。

### SYN Flood 攻击

SYN Flood 攻击是一种 DoS/DDoS 攻击,攻击者向服务器发送大量伪造的 `SYN` 包,服务器向不存在的 IP 回复 `SYN+ACK` 包,但攻击者不回复 `ACK` 包,导致服务器的半连接队列被填满,资源耗尽后无法处理正常的连接请求。

解决方案有三种:

1. **SYN Cookies**:在服务器资源紧张时,使用 SYN Cookies 技术。服务器收到 `SYN` 包后,不立即分配资源,而是根据客户端的 `SYN` 包计算一个 Cookie,放入 `SYN` 包的序列号中,然后回复 `SYN+ACK` 包。客户端收到 `SYN+ACK` 包后,回复 `ACK` 包时带上 Cookie,服务器根据 Cookie 计算出序列号,验证合法性后才建立连接。这样可以防止半连接队列被填满。
2. **增加半连接队列大小**:增大半连接队列的大小,提高服务器处理能力。
3. **缩短超时时间,减少重试次数**:缩短半连接状态的超时时间,减少重试次数,尽快释放资源。

## 讲讲 TCP 是如何优化连接建立过程的(非“大前端”岗位了解即可)

TCP 优化连接建立过程主要运用了 TFO(TCP Fast Open)技末。

在首轮握手当中,服务器将计算得来的 `SYN Cookie` 放入 `SYN+ACK` 包中 TCP 报文的 `Fast Open` 字段,客户端收到 Cookie 之后将其缓存下来,后续握手流程照常执行。

但在第二次与服务器建立连接时,客户端发送 `SYN` 包的同时,就可以将缓存的 Cookie、SYN 和 HTTP 请求一并发送给服务器,在验证合法性之后,服务器正常返回 `SYN+ACK` 包,此时服务器可以直接发起 HTTP 响应,即便第三次握手可能还没有开始执行。

其重点是,请求在第一次握手时就已经发送,不需要等待第三次握手完成,而响应也可以在第三次握手之前就已经发送,二者互不干扰,从而大大减少了连接建立的时间。
Loading

0 comments on commit 20491f7

Please sign in to comment.