在Tcp关闭连接时,客户端a与服务端b之间需要进行4次报文通信,称为Tcp的四次挥手。
下面是连接释放的图解:
第一次:由于a已经木有数据要发给b了,a发送释放请求报文,即fin=1,并把序列号seq=u告知对方(此时序列号为上次传输的最后一字节序列号+1),a进入fin-wait-1状态。
第二次:**b收到a的释放请求报文,并向a发送确认报文即ACK=1,**表示收到你的释放请求,并设置自己的序列号seq=v,以及确认号ack=u+1(对方发的报文序列号为u,注意fin=1的报文即使不携带数据也会消耗一个序列号,期望下次收到对方数据序列号从u+1开始),b进入close-wait状态。
第三次:a收到b确认报文,随机进入fin-wait-2状态,此时从a到b方向的连接已经关闭了,但是b仍然可以发数据给a,整个tcp处于半关闭状态。**当b也木有数据发给a了,则向a发送释放请求报文,即fin=1,**同时设置确认号ack=u+1(不变,因为a已经没法数据了),为了ack有效,要加上ACK=1,同时设置序列号seq=w,(不是v,因为半关闭状态b可能继续向a发送数据,当然如果b没发,v=w也有可能),之后b进入last-ack状态
第四次:a收到b关闭请求报文,会向b发送确认报文,告诉b可以关闭,由于a向b发了一个fin报文消耗一个序列号,所以seq=u+1,
然后ack=w+1,必然加上ACK=1。a进入time-wait等待2倍MSL时间才能进入closed状态。至于b,收到a的释放确认报文后就立即从last-ack变为closed状态。
为什么要四次挥手才能断开tcp连接?
因为Tcp是双向通信的,两边都需要关闭连接
为什么要让a等待2MSL时间?
为了保证a发送的最后确认报文到达b.如果a不等待发送了最后报文直接关闭,那么如果b未接收到最后的确认报文,会重新向a发送释放请求报文,而此时a已经关闭无法接收,这样b永远收不到a最后的确认报文,就无法关闭连接