TCP连接管理——三次握手和四次挥手

TCP连接管理:三次握手与四次挥手详解

TCP(Transmission Control Protocol)是一种面向连接可靠的传输层协议。在数据传输前必须建立连接,传输结束后必须释放连接。这个过程分别由三次握手(Three-Way Handshake)和四次挥手(Four-Way Handshake)完成。

1. TCP报文段首部关键字段

理解握手和挥手前,先记住以下6个关键控制位(flags):

字段含义作用场景
SYN同步序列号(Synchronize)发起连接请求
ACK确认(Acknowledgment)确认收到对方报文
FIN结束(Finish)请求释放连接
RST复位(Reset)异常中断连接
PSH推送(Push)尽快交付应用层
URG紧急(Urgent)紧急数据

另外两个重要字段:

  • seq(Sequence Number):本方发送数据的起始序号
  • ack(Acknowledgment Number):期待收到的对方下一个字节的序号(即已确认收到 ack-1 之前的字节)

2. 三次握手(建立连接)

目的:双方确认彼此的发送能力和接收能力正常,并协商初始序号(ISN)。

过程图示:

客户端                          服务端
   |   SYN (seq=x)                  |
   |------------------------------>|
   |   SYN+ACK (seq=y, ack=x+1)      |
   |<------------------------------|
   |   ACK (seq=x+1, ack=y+1)        |
   |------------------------------>|

详细步骤:

  1. 第一次握手(SYN)
    客户端发送 SYN 报文:
  • SYN=1
  • seq = x(客户端随机初始序号)
  • ACK=0(此时还没确认)
    客户端进入 SYN_SENT 状态。
    → 告诉服务端:“我想和你建立连接,我的初始序号是 x”
  1. 第二次握手(SYN+ACK)
    服务端收到 SYN 后回复:
  • SYN=1, ACK=1
  • seq = y(服务端随机初始序号)
  • ack = x+1(确认收到客户端的 SYN,期待下一个序号为 x+1)
    服务端进入 SYN_RCVD 状态。
    → 告诉客户端:“我同意建立连接,我的初始序号是 y,我已收到你的 SYN”
  1. 第三次握手(ACK)
    客户端收到 SYN+ACK 后发送最终确认:
  • SYN=0, ACK=1
  • seq = x+1
  • ack = y+1
    双方都进入 ESTABLISHED 状态,可以开始传输数据。

为什么是三次而不是两次?
两次握手只能确认客户端→服务端的单向通信能力,无法确认服务端→客户端的通道是否正常(旧的重复 SYN 可能导致服务端误以为是新连接)。三次握手确保双方都能正常收发。

3. 四次挥手(释放连接)

目的:确保双方都有机会优雅地关闭连接,数据都能可靠送达(半关闭特性:支持单方向先关闭)。

过程图示(假设客户端主动关闭):

客户端                          服务端
   |   FIN (seq=a)                  |
   |------------------------------>|
   |   ACK (ack=a+1)                 |
   |<------------------------------|
   |                                |  (服务端可能还有数据要发)
   |   (可能收到数据)              |
   |<------------------------------|
   |   FIN (seq=b)                  |
   |<------------------------------|
   |   ACK (ack=b+1)                 |
   |------------------------------>|

详细步骤:

  1. 第一次挥手(客户端发送 FIN)
    客户端数据发送完毕,发送 FIN 报文:
  • FIN=1, seq=a
    客户端进入 FIN_WAIT_1 状态。
    → “我发完了,你还有数据要发吗?”
  1. 第二次挥手(服务端回复 ACK)
    服务端收到 FIN,立刻回复确认:
  • ACK=1, ack=a+1
    服务端进入 CLOSE_WAIT 状态。
    客户端收到后进入 FIN_WAIT_2 状态。
    → “我收到你发完的通知了,但我要处理完剩余数据” 注意:此时连接处于半关闭状态,客户端不再发送数据,但仍能接收服务端数据。
  1. 第三次挥手(服务端发送 FIN)
    服务端处理完所有数据后,发送自己的 FIN:
  • FIN=1, seq=b
    服务端进入 LAST_ACK 状态。
    → “我也发完了,可以关闭了”
  1. 第四次挥手(客户端回复 ACK)
    客户端收到服务端 FIN 后回复最终确认:
  • ACK=1, ack=b+1
    客户端进入 TIME_WAIT 状态,等待 2MSL(最大报文生存时间,通常 1-4 分钟)后才完全关闭。
    服务端收到 ACK 后立即进入 CLOSED 状态。

为什么客户端要 TIME_WAIT 等待 2MSL?

  • 确保最后的 ACK 能到达服务端(如果丢失,服务端会重发 FIN,客户端可重新确认)
  • 防止旧连接的延迟报文干扰新连接(同一四元组的旧报文在网络中存活不超过 MSL)

为什么是四次而不是三次?
因为 TCP 是全双工的,关闭需要分别关闭两个方向。服务端收到客户端 FIN 后可能还有数据要发,不能立即关闭,必须等自己也准备好再发 FIN。

4. 常见状态变迁总结(客户端主动关闭)

客户端状态服务端状态
CLOSEDCLOSED
SYN_SENTLISTEN
ESTABLISHEDSYN_RCVD
FIN_WAIT_1ESTABLISHED
FIN_WAIT_2CLOSE_WAIT
TIME_WAITLAST_ACK
CLOSEDCLOSED

5. 常见面试延伸问题

  • 为什么初始序号 ISN 要随机?→ 防止历史旧连接的报文被误认为是新连接的数据。
  • 如果第三次握手丢失会怎样?→ 服务端超时重发 SYN+ACK,客户端重新发送第三次 ACK。
  • 大量 TIME_WAIT 如何处理?→ 调小 time_wait 时间、开启 tcp_tw_reuse/recycle(慎用)。
  • SYN Flood 攻击?→ 攻击者发送大量 SYN 不完成第三次握手,耗尽服务端半连接队列。防御:syn cookies、增加 backlog 等。

希望这个详解清晰易懂!如果需要结合 Wireshark 抓包示例、状态机图或其他深入点(如同时打开、同时关闭),随时告诉我。

文章已创建 3572

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部