TCP/IP
三次握手与四次挥手,到底在握什么
TCP 是面向连接的,所谓"连接"其实只是双方各自维护的一份状态。握手的过程,就是双方确认彼此的初始序列号和接收窗口。
三次握手
客户端 服务端
|--- SYN, seq=x ----------->|
|<-- SYN+ACK, seq=y, ack=x+1 ------|
|--- ACK, ack=y+1 ----------->|
- 第一次:客户端说"我要连你,我的起始序号是 x";
- 第二次:服务端说"收到,我的起始序号是 y,你的 x 我确认";
- 第三次:客户端说"你的 y 我也收到了"。
为什么不是两次?两次握手只能确认客户端到服务端这一条路是通的,服务端无法确认自己的序列号被对端收到了。少了第三次,服务端可能会为一个早已失效的连接请求白白建立连接——这就是 SYN 洪泛的由来之一。
四次挥手
关闭要四次,是因为 TCP 是全双工的,两个方向要分别关:
主动方 --- FIN ----> 被动方 (我不再发了)
主动方 <-- ACK ----- 被动方 (知道了)
主动方 <-- FIN ----- 被动方 (我也不发了)
主动方 --- ACK ----> 被动方 (好,再见)
主动关闭方发完最后的 ACK 后会进入 TIME_WAIT,等 2MSL(通常 60 秒)。等这么久有两个原因:一是确保最后的 ACK 能到对端,二是让这次连接的残留报文在网络中消散,避免和新连接串台。
线上如果看到大量 TIME_WAIT,通常是短连接太多。可以考虑长连接、连接池,或者调 net.ipv4.tcp_tw_reuse——但改内核参数之前,先确认是不是应用层的连接策略有问题。