TCP的四次挥手你真的理解了吗

105 阅读2分钟

想一想

大家都知道TCP是全双工的,连接需要三次握手,以保证双方都有收发消息的能力,但是大家有没有理解为什么挥手的时候需要四次呢?

前提知识

先了解下挥手报文标志位
标志位(=1)说明
ACK确认标志位,用于数据进行应答确认
FIN结束标志位,用于关闭连接
SYN同步标志位,用于建立连接
序列号和确认号

序列号(Sequence number):初始序列号是随机的,用来跟踪发送的数据包,下一个序列号=当前序列号+发送数据的字节.
确认号(Acknowledge number):当ACK标志为1时有效,表示期望收到的下一个字节的序号.

四次挥手流程

sequenceDiagram
Client->>Server: (1)FIN, seq=x
Server-->>Client: (2)ACK, ack=x+1, seq=y
Server-->>Client: (3)FIN + ACK, ack=x+1, seq=z
Client-)Server: (4)ACK, ack=z+1, seq=x+1
Client-)Client: 等待2MSL

从四次挥手的流程上看主要有两点不太好理解:

  1. 第2、3的挥手,为什么不合并一次挥手,这也是为什么挥手是四次的主要原因?
    主要原因是因为:当其中一方要关闭的时候,对方可能还有数据要发送,必须等数据发送完成才能关闭链接
    由于TCP是全双工的,双方都能相互发送数据,当其中一方要关闭数据(比如Client),发送FIN报文,即要关闭连接,说明client的数据已经发送完毕,发送FIN(1)报文后,client出于FIN-WRITE-1状态,对端(Server)收到FIN报文后,立刻回复ACK(2)报文,然后等待数据发送完毕后,发送FIN+ACK(3)报文,如果把这两个(2)(3)报文合并发送呢?但是由于(3)报文发送时间可能会很长,导致client多次重发

  2. 为什么要等待2MSL
    为了确认发出的ACK报文已经确认被接受,因为如果服务端未收到ACK报文,则会重发FIN报文,如果在2MSL再次收到FIN报文,则再等待2MSL


这里推荐一个好用的记账小程序:墨子记账