TCP三次握手与四次挥手(全网最易懂保姆级教程)

一、前置知识准备


1. TCP协议特性
- 面向连接:通信前需要建立专用通道
- 可靠传输:通过确认机制保证数据可达
- 全双工通信:双方可同时发送数据
- 流量控制:滑动窗口机制
- 拥塞控制:慢启动算法

2. 关键概念说明
| 术语       | 说明                                                                 |
|------------|----------------------------------------------------------------------|
| **SYN**    | 同步序列号(Synchronize),用于建立连接                              |
| **ACK**    | 确认标志(Acknowledgment),用于确认收到数据                         |
| **FIN**    | 结束标志(Finish),用于释放连接                                     |
| **SEQ**    | 序列号(32位随机数),保证数据有序性                                 |
| **ACK号**  | 期望收到的下一个数据包的序列号(SEQ+1)                             |
| **状态码** | 如SYN_SENT、ESTABLISHED等,描述TCP连接状态                          |

二、三次握手深度解析(连接建立)


场景模拟
想象你在打电话:
- 你:"喂,听得到吗?"(第一次握手)
- 对方:"听得到,你那边呢?"(第二次握手)
- 你:"我也能听到"(第三次握手)

技术细节分解
sequenceDiagram
    participant Client
    participant Server

    Client->>Server: SYN=1, SEQ=X(进入SYN_SENT状态)
    Note right of Client: 生成随机初始序列号X
    Server->>Client: SYN=1, ACK=1, SEQ=Y, ACK=X+1(进入SYN_RCVD状态)
    Note left of Server: 生成随机初始序列号Y
    Client->>Server: ACK=1, SEQ=X+1, ACK=Y+1(进入ESTABLISHED状态)
    Server->>Server: 收到ACK后进入ESTABLISHED状态

第一次握手(SYN)
  • 客户端发送SYN包:

    • 设置SYN标志位为1

    • 生成随机初始序列号X(防止历史连接冲突)

    • 不携带应用数据

  • 客户端状态变为SYN_SENT

第二次握手(SYN+ACK)
  • 服务端返回确认包:

    • 同时设置SYN和ACK标志位为1

    • 生成随机初始序列号Y

    • 确认号为X+1(期待下次收到X+1)

  • 服务端状态变为SYN_RCVD

第三次握手(ACK)
  • 客户端发送确认包:

    • 设置ACK标志位为1

    • 序列号变为X+1(与第一次握手呼应)

    • 确认号为Y+1(期待服务端下次发送Y+1)

  • 双方进入ESTABLISHED状态

❓ 高频面试题:为什么需要三次握手?

  1. 防止历史连接:避免失效的SYN包突然到达导致错误连接

  2. 同步初始序列号:双方确认对方的收发能力正常

  3. 避免资源浪费:二次握手时服务端会提前分配资源,可能遭受SYN攻击

三、四次挥手深度解析(连接释放)

场景模拟

想象结束通话:

  • 你:"我说完了,挂了啊"(第一次挥手)

  • 对方:"好的,知道了"(第二次挥手)

  • 对方:"我也说完了"(第三次挥手)

  • 你:"好的,断开吧"(第四次挥手)

技术细节分解

sequenceDiagram
    participant Client
    participant Server

    Client->>Server: FIN=1, SEQ=U(进入FIN_WAIT_1状态)
    Server->>Client: ACK=1, ACK=U+1(进入CLOSE_WAIT状态)
    Server->>Client: FIN=1, SEQ=V(进入LAST_ACK状态)
    Client->>Server: ACK=1, ACK=V+1(进入TIME_WAIT状态)
第一次挥手(FIN)
  • 主动关闭方发送FIN包:

    • 设置FIN标志位为1

    • 序列号为当前已传输数据的最后一个字节序号+1(U)

  • 进入FIN_WAIT_1状态

第二次挥手(ACK)
  • 被动关闭方返回ACK包:

    • 确认号设置为U+1

    • 仍可以继续发送未传输完的数据

  • 进入CLOSE_WAIT状态(半关闭状态)

  • 主动方收到后进入FIN_WAIT_2状态

第三次挥手(FIN)
  • 被动关闭方发送FIN包:

    • 当数据全部发送完毕后发送FIN

    • 序列号为V(基于自己的数据传输进度)

  • 进入LAST_ACK状态

第四次挥手(ACK)
  • 主动关闭方发送ACK包:

    • 确认号设置为V+1

    • 进入TIME_WAIT状态(等待2MSL)

  • 被动关闭方收到后关闭连接

❓ 高频面试题:为什么需要四次挥手?

  1. 半关闭特性:收到FIN仅表示对方不再发送数据,己方可能仍需发送剩余数据

  2. ACK延迟:将FIN和ACK分开发送,避免因延迟导致状态混乱

  3. 确保可靠终止:TIME_WAIT状态处理延迟到达的数据包(等待2MSL)

四、关键补充知识

1. TIME_WAIT状态详解

  • 持续时间:2倍MSL(Maximum Segment Lifetime)

    • Linux默认MSL=60秒,因此TIME_WAIT=120秒

  • 核心作用

    • 确保最后一个ACK到达

    • 让旧连接的重复分节在网络中失效

2. 异常情况处理

场景 处理机制
握手丢包 超时重传(SYN重试次数由/proc/sys/net/ipv4/tcp_syn_retries控制)
FIN丢失 重传FIN包直到收到ACK或超时
服务端进程崩溃 客户端发送数据会触发RST复位响应
网络中断 心跳包检测机制(TCP Keepalive)

五、实战抓包分析(Wireshark演示)

三次握手过程
No.  Time     Source        Destination   Protocol Info
1    0.0000   192.168.1.2   192.168.1.3   TCP      [SYN] Seq=0 
2    0.0008   192.168.1.3   192.168.1.2   TCP      [SYN, ACK] Seq=0 Ack=1
3    0.0010   192.168.1.2   192.168.1.3   TCP      [ACK] Seq=1 Ack=1

四次挥手过程
4    5.1234   192.168.1.2   192.168.1.3   TCP      [FIN, ACK] Seq=1 Ack=1
5    5.1235   192.168.1.3   192.168.1.2   TCP      [ACK] Seq=1 Ack=2
6    5.2345   192.168.1.3   192.168.1.2   TCP      [FIN, ACK] Seq=1 Ack=2
7    5.2346   192.168.1.2   192.168.1.3   TCP      [ACK] Seq=2 Ack=2

六、常见问题汇总

Q1:SYN洪水攻击原理?

攻击者伪造大量SYN包耗尽服务端资源,服务端维护半连接队列导致正常请求无法处理

Q2:为什么不能三次挥手?

因为TCP是全双工的,必须保证两个方向的连接都正确关闭

Q3:CLOSE_WAIT状态过多怎么办?

通常是应用程序未正确调用close(),需要检查代码是否正确关闭socket

Q4:TIME_WAIT状态优化方案?

  • 修改内核参数:net.ipv4.tcp_tw_reuse

  • 使用SO_REUSEADDR选项

  • 改用长连接

你可能感兴趣的:(JAVA,网络,服务器,运维,java,tcp/ip,三次握手)