外观
为什么是三次握手、四次挥手?
三次握手是为了双方确认对方能收到自己的报文,并同步起始序号。两次不够:服务器还不知道自己的响应有没有到达客户端。四次挥手是因为 TCP 是全双工,每一端都要单独关掉自己的发送方向。
原理
握手:
- 客户端发 SYN,带上自己的初始序号。
- 服务器回 SYN+ACK,确认客户端的序号,并带上自己的初始序号。
- 客户端发 ACK,确认服务器的序号。
这三次之后,双方都知道连接可用。初始序号不能从 0 固定递增,否则旧连接的延迟报文可能被新连接接受。
挥手:
- 主动关闭方发 FIN。
- 对方 ACK。这时对方可能还有数据要发,连接处于半关闭。
- 对方发完后也发 FIN。
- 主动方 ACK,再等一段时间才真正释放,用来消化迟到的报文。
第三次握手的 ACK 可以携带数据,所以建立连接的往返通常是一次。挥手的最后等待是 TIME_WAIT,主动关闭方会短时间占着这个端口对。
追问
TIME_WAIT 过多会怎样?
主动关闭的一端堆积 TIME_WAIT,新连接可能暂时用不上同一对地址。服务端应让客户端主动关闭,或复用连接(keep-alive、HTTP/2),而不是每个请求都新建再立刻关。
和 TLS 握手是一回事吗?
不是。TCP 握手之后,HTTPS 还要做 TLS 握手。见 HTTPS。
易错点
- 把四次挥手说成「必须连续四个包、中间不能带数据」。半关闭期间对端仍可发送剩余数据。
- 两次握手就被认为可以传数据。服务器发出的 SYN 还没被确认。
- 挥手次数说成三次。特殊实现可能把 ACK 和 FIN 合并,但模型上每一端都要确认对方的关闭。