引言

毫无疑问,HTTP 三次握手和四次挥手在实际应用场景和面试上都属于重点。虽然此前进行过学习,但由于在开发过程中遇到的次数太少,便没有记住多少。为了加强记忆,也为了梳理自身混乱的知识体系,特地记录下来,以便反复学习记忆。

三次握手

三次握手.png

  • seq : sequence
  • SYN : synchronize
  • ACK : acknowledgment
  • SYN_SENT : syn package has been sent
  • SYN_RCVD : syn package has been received

第一次握手

Client 发送一个 SYN(seq = x) 包给 Server,然后等待 server 的 ACK 回复,进入SYN-SENT状态。

张三首先向李四招手 (SYN)

第二次握手

Server 接收到 SYN(seq = x) 包后就返回一个 ACK(x + 1) 包以及一个自己的 SYN(seq = y) 包,然后等待 Client 的 ACK 回复,Server 进入SYN-RECIVED状态。

李四看到张三向自己招手后,向对方点了点头挤出了一个微笑 (ACK)。 但是李四还有点狐疑,向四周看了一看,有没有可能张三是在看别人呢,他也需要确认一下。所以李四也向张三招了招手 (SYN)。

第三次握手

Client 接收到 Server 发回的 ACK(x + 1) 包后,进入ESTABLISHED状态。然后根据 Server 发来的 SYN(seq = y) 包,返回给等待中的 Server 一个 ACK(x + 1) 包。等待中的 Server 收到 ACK 回复,也把自己的状态设置为ESTABLISHED。到此 TCP 三次握手完成,Client 与 Server 可以正常进行通信了。

张三看到李四微笑后确认了李四成功辨认出了自己(进入 ESTALISHED 状态)。 张三看到李四向自己招手后知道对方是在寻求自己的确认,于是也点了点头挤出了微笑 (ACK),李四看到对方的微笑后确认了张三就是在向自己打招呼(进入 ESTALISHED 状态)。


为什么是三次

这个问题在谢希仁版《计算机网络》里说了。 三次是保证双方互相明确对方能收能发的最低值。 理论上讲不论握手多少次都不能确认一条信道是“可靠”的,但通过3次握手可以至少确认它是“可用”的,再往上加握手次数不过是提高“它是可用的”这个结论的可信程度。

四次挥手

四次挥手.png

第一次挥手

Initiator 发送一个 FIN(seq = x + 2) + ACK(y + 1) 包,此时 Initiator 进入FIN-WAIT-1状态,这表明Initiator 已经没有数据要发送了。

张三挥手 (FIN)

第二次挥手

Recipient 收到了 Initiator 发来的 FIN(seq = x + 2) + ACK(y + 1) 包后,向client发回一个ACK(x + 3)包,此时Recipient 进入CLOSE-WAIT状态,Initiator 进入FIN-WAIT-2状态。

李四伤感地微笑 (ACK)


第三次挥手

Recipient 向 Initiator 发送 FIN(seq = y + 1) 包,请求关闭连接,同时 Recipient 进入LAST-ACK状态。

李四挥手 (FIN)

第四次挥手

Initiator 收到 Recipient 发送的 FIN(seq = y + 1) 包,进入TIME-WAIT状态。向 Recipient 发送 ACK(y + 2) ,Recipient 收到client的 ACK(y + 2) 以后,进入CLOSE状态;Initiator 等待一段时间还没有得到回复后判断Recipient 已正式关闭,进入CLOSE状态。

张三伤感地微笑 (ACK)

为什么是四次

TCP断开链接的过程和建立链接的过程比较类似,只不过中间的两部并不总是会合成一步走,所以它分成了4个动作,张三挥手(fin)——李四伤感地微笑(ack)——李四挥手(fin)——张三伤感地微笑(ack)。
之所以中间的两个动作没有合并,是因为tcp存在「半关闭」状态,也就是单向关闭。张三已经挥了手,可是人还没有走,只是不再说话,但是耳朵还是可以继续听,李四呢继续喊话。等待李四累了,也不再说话了,朝张三挥了挥手,张三伤感地微笑了一下,才彻底结束了。

参考链接