TCP的四次挥⼿为什么是四次?为什么不能是三 次
TCP 四次挥手(Four-way Handshake)用于终止一个已经建立的 TCP 连接。之所以是四次挥手,而不是三次,是因为 TCP 是全双工的(full-duplex),这意味着数据可以在两个方向上同时传输。因此,关闭连接需要双方分别确认关闭请求。
四次挥手的过程:
-
FIN (Client -> Server):
- 客户端想要关闭连接(假设客户端主动关闭)。
- 客户端发送一个 FIN 报文段(FIN=1,seq=u)到服务器。
- FIN=1 表示这是一个 FIN 报文段(请求关闭连接)。
- seq=u 表示客户端的序列号。
- 客户端进入 FIN_WAIT_1 状态。
-
ACK (Server -> Client):
- 服务器收到客户端的 FIN 报文段。
- 服务器发送一个 ACK 报文段(ACK=1, seq=v, ack=u+1)到客户端。
- ACK=1 表示这是一个 ACK 报文段。
- seq=v 表示服务器的序列号。
- ack=u+1 表示服务器期望接收的下一个序列号(即客户端的 FIN 报文段的序列号加 1)。
- 服务器进入 CLOSE_WAIT 状态。
- 客户端收到服务器的 ACK 报文段后,进入 FIN_WAIT_2 状态。
-
FIN (Server -> Client):
- 服务器准备好关闭连接(例如,服务器已经发送完所有数据)。
- 服务器发送一个 FIN 报文段(FIN=1, seq=w, ack=u+1)到客户端。
- FIN=1 表示这是一个 FIN 报文段。
- seq=w 表示服务器的序列号 (注意, w可能等于v, 也可能不等于,取决于服务器是否在等待 ACK 期间发送了数据)。
- ack=u+1,表示服务器期望接收的下一个序列号与上次 ACK 相同。
- 服务器进入 LAST_ACK 状态。
-
ACK (Client -> Server):
- 客户端收到服务器的 FIN 报文段。
- 客户端发送一个 ACK 报文段(ACK=1, seq=u+1, ack=w+1)到服务器。
- ACK=1 表示这是一个 ACK 报文段。
- seq=u+1 表示客户端的下一个序列号(即客户端上次发送的 FIN 报文段的序列号加 1)。
- ack=w+1 表示客户端期望接收的下一个序列号(即服务器的 FIN 报文段的序列号加 1)。
- 客户端进入 TIME_WAIT 状态(等待 2MSL 时间,以确保服务器收到 ACK,并防止延迟的报文段影响新的连接)。
- 服务器收到客户端的 ACK 报文段后,进入 CLOSED 状态。
为什么不能是三次挥手?
不能是三次挥手的主要原因是 TCP 的半关闭(half-close)特性。
-
半关闭: TCP 允许一方(例如客户端)关闭它的发送通道,但仍然可以接收数据。这意味着即使客户端发送了 FIN 报文段,它仍然可以接收来自服务器的数据,直到服务器也发送 FIN 报文段。
-
三次挥手的问题: 如果只有三次挥手,服务器在收到客户端的 FIN 报文段后,立即发送 FIN+ACK 报文段,那么客户端就无法再接收服务器可能发送的剩余数据。
-
四次挥手如何解决问题
- 服务器收到客户端的FIN后,发送ACK,表示自己知道客户端要关闭连接了。
- 但是服务器可能还有数据要发送,所以需要等待。
- 当服务器数据发送完毕,再发送FIN给客户端。
- 客户端回复ACK,连接关闭。
四次挥手的必要性:
- 确保数据完整传输: 服务器在收到客户端的 FIN 报文段后,可以继续发送数据,直到数据发送完毕。
- 允许半关闭: 客户端可以先关闭发送通道,但仍然可以接收数据。
- 避免数据丢失: 四次挥手确保了双方都确认了对方要关闭连接,避免了数据丢失。
四次挥手的状态变化:
- FIN_WAIT_1: 客户端发送 FIN 报文段后进入的状态。
- FIN_WAIT_2: 客户端收到服务器的 ACK 报文段后进入的状态。
- CLOSE_WAIT: 服务器收到客户端的 FIN 报文段后进入的状态。
- LAST_ACK: 服务器发送 FIN 报文段后进入的状态。
- TIME_WAIT: 客户端发送 ACK 报文段后进入的状态(等待 2MSL 时间)。
- CLOSED: 连接完全关闭。
TIME_WAIT 状态的作用:
- 确保服务器收到 ACK: 如果服务器没有收到客户端的 ACK 报文段,它会重传 FIN 报文段。TIME_WAIT 状态允许客户端重新发送 ACK 报文段。
- 防止延迟的报文段影响新的连接: 2MSL (Maximum Segment Lifetime,报文段最大生存时间) 时间足够长,可以确保网络中所有延迟的报文段都消失,避免影响新的连接。
总结:
- TCP 四次挥手是为了可靠地关闭全双工连接。
- 不能是三次挥手,因为 TCP 支持半关闭,需要双方分别确认关闭请求。
- 四次挥手确保了数据完整传输,允许半关闭,并避免了数据丢失。
- TIME_WAIT 状态确保了服务器收到 ACK,并防止延迟的报文段影响新的连接。
四次挥手是 TCP 协议为了保证可靠性而设计的,虽然比三次挥手多了一次交互,但它确保了连接的正确关闭,避免了数据丢失和潜在的问题。