## 目录
1. [HTTPS建立连接的过程](#一https建立连接的过程)
2. [HTTP缓存策略详解](#二http的缓存策略是怎么样的)
3. [TCP三次握手和四次挥手](#三tcp三次握手和四次挥手是怎么样的)
4. [TCP可靠性保证机制](#四tcp怎么保证可靠性的)
5. [TCP拥塞控制实现](#五tcp拥塞控制怎么实现)
6. [Close_wait问题处理](#六close_wait太多怎么处理)
7. [HTTP/2新特性](#http2-有哪些新特性)
8. [HTTP报文结构](#http报文结构是怎么样的)
9. [常见状态码解析](#http状态码502503504各自代表着什么)

---

## 一、HTTPS建立连接的过程

### 证书申请阶段(前置准备)
在正式建立连接前,服务器需要向证书机构(CA)申请SSL证书:
- 服务器将自己的公钥发给CA机构
- CA机构用自己的私钥对服务器的公钥进行加密,生成SSL证书
- 服务器存储SSL证书,供后续安全连接使用

### 连接建立详细流程

**第1步:TCP三次握手**
客户端与服务器先建立TCP连接(这是HTTPS的基础)

**第2步:服务器发送SSL证书**
服务器将SSL证书发送给客户端,证书包含:
- 证书的发布机构(CA)
- 证书的有效期
- 服务器的公钥
- 证书所有者
- 数字签名

**第3步:客户端验证证书(以浏览器为例)**
1. 浏览器检查证书所有者、有效期等基本信息
2. 查找操作系统中内置的受信任CA证书,比对颁发者
3. 如果找不到,浏览器报错(证书不可信)
4. 如果找到,用CA的公钥解密证书中的签名
5. 用相同hash算法计算证书hash值,与解密后的签名对比
6. 一致则证明证书合法,读取公钥用于后续加密

### 为什么需要CA?

假设没有CA,可能发生中间人攻击:
```
正常流程:服务器公钥 → 客户端
被攻击:服务器公钥被hack截获 → hack将自己的公钥发给客户端 → 客户端用hack公钥加密数据 → hack解密获取数据 → hack用服务器公钥加密转发
```

有了CA后,客户端内置的CA根证书能识别出hack的证书不合法,有效防止中间人攻击。

---

## 二、HTTP的缓存策略是怎么样的?

HTTP缓存主要分为**强缓存**和**对比缓存**两种,优先级:**强缓存 > 对比缓存**

### 强缓存
浏览器直接从本地缓存读取数据,不再向服务器发送请求

**实现字段:**
- **Expires**:缓存到期时间(绝对时间,服务器时间+缓存有效期)
  - 缺点:客户端修改本地时间会导致缓存失效;本地时间与服务器时间不一致也会失效
  
- **Cache-Control**:缓存最大有效时间(相对时间)
  - 优点:即使本地时间与服务器不一致,也不会导致缓存失效
  - 常用取值:
    - `max-age`:最大有效时间(秒)
    - `no-cache`:没有缓存
    - `s-maxage`:同max-age,仅用于共享缓存(如CDN)
    - `public`:多用户共享缓存(默认)
    - `private`:不能多用户共享

### 对比缓存
先向服务器发送请求,带上缓存标识,由服务器判断是否使用缓存

**Last-Modified/If-Modified-Since**
- 响应头返回`Last-Modified`(资源最后修改时间)
- 请求头带上`If-Modified-Since`(上次获取的修改时间)
- 服务器判断资源是否更新:
  - 有更新:返回新资源(状态码200)
  - 无更新:返回304,浏览器使用缓存

**缺点:**
1. 只能精确到秒级,1秒内多次修改无法准确标识
2. 内容未变但修改时间改变,导致缓存失效

**Etag/If-None-Match**
- 响应头返回`Etag`(资源版本号)
- 请求头带上`If-None-Match`(上次的版本号)
- 服务器对比版本号决定返回200还是304

### 缓存优先级
强缓存(Cache-Control) > 强缓存(Expires) > 对比缓存(Etag) > 对比缓存(Last-Modified)

---

## 三、TCP三次握手和四次挥手是怎么样的?

### 三次握手(建立连接)

```
客户端         服务端
  |----SYN---->|
  |<--SYN+ACK--|
  |----ACK---->|
```

**详细流程:**
1. **客户端发SYN**:生成随机数J作为序号,发送SYN包(seq=J),进入`SYN_SENT`状态
2. **服务端回应SYN+ACK**:进入`SYN_RECV`状态,发送SYN包(ACK=1,ack=J+1,seq=K)
3. **客户端发ACK**:检查ACK=1且ack=J+1,发送ACK包(ACK=1,ack=K+1)
4. 双方进入`ESTABLISHED`状态,连接建立成功

### 四次挥手(断开连接)

```
客户端         服务端
  |----FIN---->|  客户端→服务端断开
  |<---ACK-----|  服务端确认
  |<---FIN-----|  服务端→客户端断开
  |----ACK---->|  客户端确认
```

**详细流程:**
1. **客户端发FIN**:发送FIN包(seq=J),进入`FIN_WAIT_1`,表示客户端无数据发送
2. **服务端回ACK**:发送ACK包(ack=J+1),进入`CLOSE_WAIT`,客户端收到后进入`FIN_WAIT_2`
3. **服务端发FIN**:服务端无数据后,发送FIN包,进入`LAST_ACK`
4. **客户端回ACK**:发送ACK包,进入`TIME_WAIT`,超时后自动关闭;服务端收到ACK后进入`CLOSE`

**TIME_WAIT的意义**:如果ACK包丢失,服务端会重发FIN,客户端可以在TIME_WAIT状态下重发ACK。

---

## 四、TCP怎么保证可靠性的?

TCP通过多种机制共同保障可靠性:

### 1. 校验和
将数据切分成16位二进制串,求和得到校验和。接收方用相同算法计算,对比校验和是否一致,防止数据损坏。

### 2. 序列号/确认应答 + 超时重传
- 每个数据包都有序号
- 接收方收到数据返回ACK确认
- 超过超时时间未收到ACK,触发超时重传
- 超时时间动态变化:初始值>正常往返时间,重传失败则指数增加
- Linux中以500ms为单位,重传超时依次为500ms、2500ms、4500ms...
- 重传次数累计到阈值后,关闭连接

### 3. 最大消息长度(MSS)
建立连接时双方约定MSS作为发送单位,理想情况下刚好不被网络层分块。

### 4. 滑动窗口控制
发送方不需要等待每个包的确认,只要包在滑动窗口内就可以发送。每收到一个确认应答,窗口向后移动一位。

### 5. 流量控制
接收方根据缓冲区情况,动态调整滑动窗口大小,通知发送方调整发送速率,防止接收方缓冲区溢出。

---

## 五、TCP拥塞控制怎么实现?

拥塞控制由四个算法组成:**慢启动、拥塞避免、拥塞发生时算法、快速恢复**

### 1. 慢启动
- 连接刚建立时,拥塞窗口cwnd初始为1
- 每收到一个ACK确认,cwnd+1
- 每个往返时延RTT,窗口大小翻倍(指数增长)
- 目的:试探网络承受能力

### 2. 拥塞避免
- 当cwnd达到慢启动阈值ssthresh时,停止指数增长
- 进入线性增长:每个RTT,cwnd+1
- 目的:避免超过网络承载能力导致拥塞

### 3. 拥塞发生时算法
**判定拥塞的依据(丢包):**
- **超时重传**:超过RTO未收到ACK
- **三个重复ACK**:收到3个以上相同的ACK(如连续收到3个ACK=2,说明包3丢失)

**处理方式:**
- 将ssthresh设置为当前窗口大小的一半
- 判定拥塞后触发快速恢复

**补充:快重传**
收到失序报文时,接收方立即返回已收到的最新序号ACK(如收到包4但没收到包3,仍返回ACK=2)。连续3个重复ACK触发发送方快速重传丢失的包。

### 4. 快速恢复算法
- **TCP Tahoe(早期算法)**:cwnd重置为1,重新慢启动
- **TCP Reno(现在常用)**:cwnd设置为新的ssthresh,进入拥塞避免(线性增长)

---

## 六、close_wait太多怎么处理?

### close_wait产生原因
四次挥手中,服务端返回ACK应答后,如果还有数据要发给客户端,会进入close_wait状态。如果被动关闭方没有及时发出FIN包,就会一直停留在close_wait状态。

### 解决方案
可以调整TCP空闲连接存活时间:
```
tcp_keepalive_time = 7200  # 默认2小时,可调小
```

### time_wait太多的问题及处理

**产生原因**:高并发短连接场景下,主动关闭方进入TIME_WAIT状态,端口资源(0-65535)有限,持续高并发会导致端口耗尽。

**解决方案**(修改系统配置):
```
net.ipv4.tcp_syncookies = 1      # 开启SYN Cookies,防范SYN攻击
net.ipv4.tcp_tw_reuse = 1         # 允许TIME-WAIT sockets重新用于新连接
net.ipv4.tcp_tw_recycle = 1       # 开启TIME-WAIT sockets快速回收
net.ipv4.tcp_fin_timeout = 30     # 修改默认TIMEOUT时间
```

---

## HTTP/2 有哪些新特性?

### 1. 二进制传输
- 采用二进制格式传输数据,而非HTTP/1.x的纯文本
- 协议解析更高效
- 将请求和响应数据分割为更小的帧,二进制编码
- 同域名下所有通信在单个连接上完成,承载任意数量双向数据流

### 2. Header压缩(HPACK算法)
- 客户端和服务器建立"字典",用索引号表示重复字符串
- 采用哈夫曼编码压缩整数和字符串,压缩率达50%-90%
- 首部表在连接存续期内始终存在,渐进更新
- 新请求只需发送差异数据,减少冗余

### 3. 多路复用
- 解决浏览器对同域名请求数量的限制
- 更容易实现全速传输
- 避免了TCP连接的慢启动过程

### 4. Server Push(服务器推送)
- 服务器可主动向客户端发送消息
- 例如:浏览器请求HTML时,服务器提前推送可能用到的JS、CSS文件
- 减少等待延迟

### 5. 提高安全性
- 虽然不强制加密,但主流浏览器只支持加密的HTTP/2
- 实际应用的HTTP/2都是加密的
- 协议标识:"h2"表示加密,"h2c"表示明文

---

## HTTP报文结构是怎么样的?

### 请求报文结构
```
请求行 + 请求头 + 空行 + 请求内容
```

**请求行**:请求方法 + URL + 协议版本(空格分隔)
- 请求方法:GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT

**请求头**:key/value对,每行一对,冒号分隔
- User-Agent:浏览器类型
- Accept:可识别的响应内容类型
- Accept-Language:可接受的自然语言
- Host:请求的主机名
- Connection:连接方式(close或keepalive)
- Cookie:客户端扩展字段

**空行**:标识请求头结束

**请求内容**:POST请求的body,配合Content-Type和Content-Length使用

### 响应报文结构
```
状态行 + 响应头 + 空行 + 响应内容
```

**状态行**:HTTP协议版本 + 状态码 + 状态描述(空格分隔)
- 1xx:接收请求,继续处理
- 2xx:成功处理
- 3xx:重定向
- 4xx:客户端错误
- 5xx:服务器错误

**常见状态码**:
- 200 OK:请求成功
- 304 Not Modified:资源未修改,可使用缓存
- 400 Bad Request:请求语法错误
- 401 Unauthorized:未经授权
- 404 Not Found:资源不存在
- 500 Internal Server Error:服务器内部错误
- 503 Service Unavailable:服务不可用

**响应头**:
- Location:重定向位置
- Server:服务器软件信息
- Vary:不可缓存请求头列表
- Connection:连接方式
- Keep-Alive:保持连接时间

**空行**:标识响应头结束

**响应内容**:服务器返回的文本信息

---

## HTTP状态码502,503,504各自代表着什么?

### 502 Bad Gateway
- **含义**:网关(一般是Nginx)从后端服务器接收到无效响应
- **常见原因**:后端服务器挂了、服务崩溃、无法响应
- **示例**:后端Java应用进程突然退出

### 503 Service Unavailable
- **含义**:服务不可用,请求过载
- **常见原因**:请求超过Nginx限流设置的阈值
- **示例**:服务器配置了每秒最多处理100个请求,超过则返回503

### 504 Gateway Timeout
- **含义**:网关(一般是Nginx)从后端服务器接收响应超时
- **常见原因**:后端处理时间过长,超过Nginx等待时间
- **示例**:Nginx配置了60秒超时,但后端接口处理需要90秒

---

**本文总结**:计算机网络核心知识涵盖了从应用层(HTTP/HTTPS)到传输层(TCP)的关键机制。HTTPS通过CA证书体系保障安全,HTTP通过缓存策略提升性能,TCP通过三次握手、四次挥手、可靠性保证和拥塞控制,为上层应用提供稳定可靠的数据传输服务。掌握这些基础知识,对于后端开发、系统架构和问题排查都至关重要。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐