TCP三次握手(建立连接)

TCP是面向连接的,需要通过三次握手建立可靠连接

1
2
3
4
5
客户端(Client)                       服务端(Server
| ------ SYN = 1, seq = x ------> |
| <--- SYN = 1, ACK = 1, y,x+1 ---|
| ------ ACK = 1, ack = y+1 -----> |
连接建立

第一次:Client->Server:SYN=1

客户端发送一个SYN包(同步序列号),告诉服务器:我要发起连接,并带上初始序列号seq=x

让服务器知道客户端想建立连接

第二次:Server->client:SYN=1,ACK=1

服务器收到SYN后,发送SYN+ACK
ACK=1表示:我收到了你的SYN,确认号ack=x+1
SYN=1表示:我也准备好了建立连接,序列号seq=y

服务器同意连接
服务器也要同步序列号(SYN)

第三次:Client->Server:ACK=1

客户端收到SYN+ACK后返回ACK:
ack=y+1,表示收到服务端的SYN
双方建立连接

客户端最终确认
连接正式建立,可以传输数据

为什么是三次?

因为需要 双向确认双方序列号都正常
第一次:客户端 → 服务器(客户端序列号)
第二次:服务器 → 客户端(服务器序列号 + 确认客户端)
第三次:客户端 → 服务器(确认服务器)

三次握手的目的,是双方都确认彼此的接收能力和发送能力以及初始序列号,保证可靠通信。

TCP四次挥手(断开连接)

关闭连接需要 四次挥手,因为 TCP 是全双工,必须分别关闭两个方向的通道。

1
2
3
4
5
6
客户端(Client)                       服务端(Server
| ------ FIN = 1, seq = u ------> |
| <--------- ACK = 1, u+1 ------- |
| <------ FIN = 1, seq = v ------ |
| ------- ACK = 1, v+1 ---------> |
连接断开

第一次挥手:Client->Server:FIN

客户端说:我想关闭客户端->服务端的数据通道(我不发数据了)

第二次挥手:Server->Client:ACK

服务器回复ACK:我收到了,但我还可能要发数据给你

此时状态为:Client:FIN-WAIT-2;Server:CLOSE-WAIT(服务器还在处理剩余数据)

第三次挥手:Server->Client:FIN

服务器处理完数据后发送FIN
告诉客户端:我也发完了,可以关闭了

第四次挥手:Client->Server:ACK

客户端确认服务器的FIN
此时:客户端进入TIME_WAIT(等待2MSL),服务器进入CLOSE

为什么要等待2MSL(TIME_WAIT)?

因为需要保证:

  1. 确保 ACK 能让服务端收到:如果服务端没收到 ACK,会重发 FIN;如果客户端还在,能重新 ACK
  2. 让本次连接所有旧报文在网络中消失:避免下一次连接收到旧包造成混乱

四次挥手是因为 TCP 是全双工模式,双方都必须独立发送 FIN 来关闭通信方向。TIME_WAIT 是为了保证可靠关闭,防止旧报文影响后续连接。

总结

三次握手:SYN->SYN+ACK->ACK
四次挥手:FIN->ACK->FIN->ACK