握手协议
浏览器需要与服务器建立连接前的协商过程,核心目的是通过双方通信能力、交换密钥、和验证身份。
1. 三次握手(TCP 连接)
为了建立报文段,通信双方必须从对象了解以下信息:
- 对方报文发送的开始序列号
- 对象发动数据的缓存区大小
- 能被接收的最大报文段长度 MSS
- 被支持的 TCP 选项
所以通信双方需要进行三次握手:
- 客户端发送 SYN 包,请求建立连接,并指明客户端的初始化序列号(iSN),等待服务器确认
- 服务器确认(收到 SYN 包),并返回自己的 SYN 包和 ACK 包,此时服务器进入 SYN_RECV 状态(确认连接请求并同步序列号,指明服务器的初始化序列号 ISN)
- 客户端收到服务器的 SYN + ACK 包,向服务器发送自己的 ACK 包(确认服务器的同步序列号),双方进入 ESTABLISHED 状态,完成三次握手
三次握手
客户端 服务器
| |
|---- 1. 发送 SYN 包, 请求建立连接 ---------> |
| |
| <---- 2. 返回服务器的 SYN 包和 ACK 包 ------| 服务器确认后
| |
确认服务器的同步序列号 |---- 3. 向服务器发送 ACK 包 ---------------> | 双方进入 ESTABLISHED 状态
信息
HTTPS 的底层是基于 TCP 协议,因此其TCP 连接的建立(三次握手)和断开(四次挥手)过程与 HTTP 完全一致。但 HTTPS 在此基础上额外添加了 TLS/SSL 加密握手过程(TLS 握手)。
2. 四次挥手(TCP 断开)
当 HTTPS/HTTP 通信结束时,TCP 断开连接需要遵循四次挥手,确保双方数据可靠传输完毕后再释放连接。
- 主动关闭方发送 FIN 包(请求关闭连接)
- 被动关闭方返回 ACK 包(确认收到 FIN)
- 被动关闭方发送 FIN(自身也请求关闭连接)
- 自动关闭方返回 ACK 包(确认收到 FIN),连接完全关闭
四次挥手
主动关闭方 被动关闭方
| |
|---- 1. 发送 FIN 包, 请求关闭连接 ---------> |
| |
| <--------------------- 2. 返回 ACK 包 ----|
| |
| <------ 3. 发送 FIN 包,自身请求关闭连接 ----|
| |
|---- 4. 返回 ACK 包 连接完全关闭 -----------> |
3. TCP 异常断开处理
TCP 协议本身设计了应对异常断开的机制,核心通过保活探测和状态超时确保服务器不会无限等待。
ⅰ TCP 保活机制(Keep-Alive)
TCP 栈默认开启保活功能(可配置),用户检测对端是否存活。
- 当客户端异常断开(如断电、断网),TCP 连接进入“半开”状态(服务器仍认为连接有效,但客户端无响应)
- 服务器会在**约 2 小时(默认间隔)**后发送第一个保活探测包(ACK 报文),若客户端无响应,后续每隔 75 秒重试一次
- 若连续** 9 次探测无反应**(总耗时 2 小时 + 9 x 75 秒 ≈ 2 小时 11 分),服务器判断连接失败,关闭该 TCP 连接并释放资源
信息
保活时间可通过系统参数调整(如 Linux 的 net.ipv4.tcp_keepalive_time),实际场景中可能缩短(如某些服务设置为 30 秒探测一次)
ⅱ TCP 状态机与超时回收
即使未使用保活,TCP 连接也会因长时间无数据传输触发超时
- 若客户端异常断开前未发送 FIN (即未完成四次挥手),服务器的 TCP 状态会停留在 ESTABLISHED 或 CLOSE_WAIT
- TCP 栈会为每一个连接维护重传计时器:若服务器尝试发送数据(如应用层有未发送的响应)打不客户端无 ACK ,会重传多次(指数退避),最终放弃并关闭连接
- 对于纯接收方,服务器若长时间无数据发送,连接也可能因双方无交互而被系统回收
4. 应用层(含 HTTPS )的额外处理
应用层(如 HTTP 服务器、HTTPS 服务器)通常会在 TCP 基础上叠加更严格的超时策略,避免资源浪费。
ⅰ. HTTP 服务器的超时机制
- 读写超时:服务器会“读取请求头/体的超时时间”(如 Nginx 的
client_header_timeout和client_body_timeout,默认 60 秒) - 空闲连接超时:即使客户端未异常,服务器也关闭长时间无数据的连接(如 Nginx 的
keepalive_timeout默认 75 秒) - 异常请求处理:若客户端在发送请求过程中断网,服务器可能收到不完整的 HTTP 报文(如截断的 URL 或头部),此时服务器会直接丢弃该请求并关闭连接
ⅱ. HTTPS 的 TLS 层影响
HTTPS 在 TCP 之上增加了 TLS 加密层,但 TLS 本身不处理连接存活问题,依赖 TCP 和应用层的机制:
- TLS 会话的清理:若客户端异常断开,服务器的 TLS 会话(Session)会被标记为无效,后续不会复用(除非重新协商)
- TLS 连接的关闭:即使未完成四次挥手,服务器也会在 TCP 连接关闭后,释放对应的 TLS 上下文(如密钥、会话缓存)