我们来全面、系统地讲解浏览器(客户端)与服务器建立和关闭 TCP 连接的“三次握手”与“四次挥手”过程。这是所有 HTTP/HTTPS 网络通信的基石。
第一部分:三次握手 - 建立连接
在浏览器发送任何请求(如输入网址后回车)之前,必须先与服务器建立一条可靠的 TCP 连接。这个过程就像打电话前的拨通和问候。
目标: 双方确认彼此的发送和接收能力正常,并同步初始序列号。
我们以浏览器作为主动打开方(客户端),服务器作为被动打开方。
第一次握手:SYN 从客户端发向服务器
- 动作:浏览器(客户端)发送一个 TCP 报文。
- 报文内容:
SYN标志位 = 1,表示这是一个连接请求报文。- 序列号
seq = x(x 是一个随机生成的初始值)。
- 含义:客户端对服务器说:“你好,我想和你建立连接。我的初始序列号是 x。”
- 状态变化:客户端进入
SYN-SENT状态。
第二次握手:SYN-ACK 从服务器发向客户端
- 动作:服务器收到
SYN报文后,如果同意连接,则回复一个报文。 - 报文内容:
SYN标志位 = 1ACK标志位 = 1- 确认号
ack = x + 1(表示我确实收到了你的序列号 x,期待你下一个发 x+1 的数据) - 序列号
seq = y(服务器自己也随机生成一个初始序列号)。
- 含义:服务器对客户端说:“我收到你的请求了,我同意建立连接。这是我的初始序列号 y,请你确认。”
- 状态变化:服务器进入
SYN-RCVD状态。
第三次握手:ACK 从客户端发向服务器
- 动作:客户端收到服务器的
SYN-ACK报文后,必须再次进行确认。 - 报文内容:
ACK标志位 = 1- 确认号
ack = y + 1(表示我确实收到了你的序列号 y) - 序列号
seq = x + 1(因为第一次握手已被确认)。
- 含义:客户端对服务器说:“我收到你的确认了。现在我们可以开始传输数据了!”
- 状态变化:
- 客户端发送完 ACK 后,进入
ESTABLISHED状态(连接已建立)。 - 服务器收到这个 ACK 后,也进入
ESTABLISHED状态。
- 客户端发送完 ACK 后,进入
至此,连接建立成功,浏览器可以开始发送 HTTP 请求了。
为什么是三次,而不是两次?
核心是防止已失效的连接请求报文突然又传送到服务器,因而产生错误。
假设只有两次握手:如果一个滞留在网络中的旧连接请求报文突然到达服务器,服务器会误以为是新的请求,直接建立连接并等待数据,但客户端并不会发送数据,这就导致了服务器资源的浪费。第三次握手是一个“双重保险”,客户端需要基于服务器的响应来做出最终确认,只有双方都确认无误后,连接才真正建立。
第二部分:四次挥手 - 关闭连接
当数据交换完毕(例如网页已加载完成),任何一方都可以发起关闭连接的请求。我们以浏览器作为主动关闭方来举例。
目标: 可靠地关闭一个全双工的数据通道。
第一次挥手:FIN 从客户端发向服务器
- 动作:浏览器(客户端)发送一个 TCP 报文。
- 报文内容:
FIN标志位 = 1,表示请求终止连接。- 序列号
seq = u。
- 含义:客户端对服务器说:“我这边没有数据要发送了,我想关闭我到你方向的连接。”
- 状态变化:客户端进入
FIN-WAIT-1状态。
第二次挥手:ACK 从服务器发向客户端
- 动作:服务器收到
FIN后,立即回复一个确认报文。 - 报文内容:
ACK标志位 = 1- 确认号
ack = u + 1 - 序列号
seq = v。
- 含义:服务器对客户端说:“好的,我同意你关闭你那边的连接。”
- 状态变化:
- 服务器进入
CLOSE-WAIT状态。 - 客户端收到这个 ACK 后,进入
FIN-WAIT-2状态。
- 服务器进入
- 注意:此时是 “半关闭”状态。从客户端到服务器的连接已关闭,但服务器到客户端的连接仍然存在,服务器可能还有未发送完的数据。
第三次挥手:FIN 从服务器发向客户端
- 动作:当服务器也准备关闭连接时,它发送一个
FIN报文。 - 报文内容:
FIN标志位 = 1ACK标志位 = 1- 确认号
ack = u + 1(保持不变) - 序列号
seq = w(因为中途可能又发送了数据)。
- 含义:服务器对客户端说:“我这边也处理完了,没有数据要发了,我也要关闭我这边到你的连接。”
- 状态变化:服务器进入
LAST-ACK状态。
第四次挥手:ACK 从客户端发向服务器
- 动作:客户端收到服务器的
FIN后,必须发出确认。 - 报文内容:
ACK标志位 = 1- 确认号
ack = w + 1 - 序列号
seq = u + 1。
- 含义:客户端对服务器说:“收到,同意你关闭。”
- 状态变化:
- 客户端发送 ACK 后,进入
TIME-WAIT状态,等待 2MSL(两倍最大报文段生存时间)后,才进入CLOSED状态。 - 服务器一旦收到这个 ACK,立即进入
CLOSED状态。
- 客户端发送 ACK 后,进入
为什么是四次挥手?
因为 TCP 连接是全双工的,关闭时需要双方各自独立关闭。当客户端发起
FIN时,只表示它没有数据发送了,但服务器可能还有数据要传,所以服务器的ACK和FIN通常不能合并,需要分两步进行,这就比握手多了一次。
为什么客户端最后要等待 2MSL?
- 确保最后的 ACK 能到达服务器:如果服务器没收到 ACK,会重传 FIN,客户端在
TIME-WAIT状态下能收到并重发 ACK。- 让旧连接的报文在网络中消逝:防止本次连接的延迟报文被之后新建的、相同四元组(源IP、源端口、目的IP、目的端口)的连接错误地接收。
总结对比
| 特性 | 三次握手 | 四次挥手 |
|---|---|---|
| 目的 | 建立可靠连接,同步序列号 | 可靠地终止全双工连接 |
| 发起方 | 客户端 | 客户端或服务器均可 |
| 次数 | 3次 | 4次 |
| 关键标志 | SYN, ACK | FIN, ACK |
| 核心状态 | SYN-SENT, SYN-RCVD, ESTABLISHED | FIN-WAIT-1/2, CLOSE-WAIT, LAST-ACK, TIME-WAIT |
| 为何不能合并 | 服务器的 SYN 和 ACK 是可以且必须合并的 | 服务器的 ACK 和 FIN 通常不能合并,因为中间可能有数据要发送 |
简单来说,三次握手是“你好,你好,好的,开始说话”;四次挥手是“我说完了,好的,我也说完了,好的,再见”。这个过程确保了浏览器与服务器之间通信的可靠性和有序性。
1274

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



