tcp四次挥手

四次挥手

四次挥手是浏览器和服务器断开连接的一种方式,目的是断开连接,结束数据传输的过程
第一次挥手:浏览器告诉服务器,我的数据传输完了,我要断开连接了。
第二次挥手:服务器告诉浏览器,好的我知道你要断开连接了,但我还有数据没传完,我传完再告诉你
第三次挥手:服务器的数据传完了,告诉浏览器自己也要断开连接了
第四次挥手:浏览器告诉服务器,我收到了你的两次挥手报文,可以成功断开。
至此,双方数据都传输完了,并知道对方做好了断开连接的准备,也知道对方知道自己的情况。可以正式断开了。
在这里插入图片描述
1、主动关闭方发送FIN连接释放报文段
客户端调用 close 方法,告诉服务器自己要主动关闭连接,会发送一个 FIN 报文给服务端,客户端进入FIN-WAIT-1状态。

FIN 段是可以携带数据的,比如客户端可以在它发送的最后一块数据块中“捎带” FIN 段。当然也可以单独发送FIN。不管 FIN 段是否携带数据,都需要消耗一个序列号

半关闭和半连接
客户端发送 FIN 包以后不能再发送数据给服务端,但是还可以接受服务端发送的数据。这个状态就是半关闭,而三次握手中服务器收到SYN报文时的连接即为半连接

2、被动关闭方发送对FIN的ACK普通确认报文段
由于此时服务器数据很可能还没有发完,需要继续向客户端发送未完成的数据,又不能让客户端等太久,所以先向客户端发送ACK 确认报文段,服务端进入 CLOSE_WAIT,客户端收到ACK之后进入FIN-WAIT-2状态。

3、被动关闭方发送FIN连接释放报文段
当服务器数据发送完毕之后。发送 FIN 报文给客户端,然后进入LAST-ACK 状态,等待客户端的 ACK。(同前面一样如果 FIN 段没有携带数据,也需要消耗一个序列号)

4、主动关闭方发送对FIN的ACK普通确认报文段
客户端收到服务端的 FIN 报文以后,回复 ACK 报文用来确认第三步里的 FIN 报文,随后进入TIME_WAIT状态(主动关闭连接的一方才有 TIME_WAIT 状态),等待 2 个 MSL (MSL:最长报文段寿命)以后进入 CLOSED状态。服务端收到 ACK 以后进入CLOSED状态。正常情况下服务器结束TCP连接的时间要比客户端早一些。

一些自己的思考

为什么建立连接是三次握手,关闭连接确是四次挥手呢?

建立连接的时候,实际是把四次握手优化为了三次

而关闭连接时无法优化为三次,原因如下:

服务器收到对方的FIN报文时,很可能还有数据没发完,需要等到数据发送完毕之后才向客户端发送FIN报文,但是又不能让客户端等太久,就先发ACK告诉客户端我收到了你的FIN释放连接请求,客户端收到ACK之后便不会重复发送断开连接的请求。
等到服务器数据传输完毕后,才会发FIN释放连接报文。

另外,如果服务端确定没有数据需要发给客户端,那么当然是可以把 FIN 和 ACK 合并成一个包,四次挥手的过程就成了三次。

为什么 TIME_WAIT 等待的时间是 2MSL?

先看什么是MSL
MSL 是 Maximum Segment Lifetime,报文最大生存时间,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。

补充:最大生存时间怎么来的?
报文每经过一次路由器的转发,IP 头部的 TTL 字段就会减 1,减到 0 时报文就被丢弃,这就限制了报文的最长存活时间
MSL 与 TTL 的区别:MSL 的单位是时间,而 TTL 是经过路由跳数。所以 MSL 应该要大于等于 TTL 消耗为 0 的时间,以确保报文已被自然消亡。

再看为什么是2MSL?
因为设置成2MSL可以保证两点:

1、保证服务端的连接能够正确关闭
客户端是发出了第四次握手的报文后进入的TIME_WAIT。如果第四次握手中,客户端发给服务器的ACK报文丢失了,服务器就会超时重发 FIN报文给客户端,客户端要保证极端情况下也能接受到服务器的超时重发FIN报文,然后给服务器重传第四次握手报文,确保服务器能正常关闭。

2、防止收到历史数据,从而导致数据错乱的问题。
客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的历史数据。

如果TIME_WAIT小于2MSL,问题如下所示:
在这里插入图片描述
如上图黄色框框服务端在关闭连接之前发送的 SEQ = 301 报文被网络延迟了。
这时有相同端口的 TCP 连接被复用后,被延迟的 SEQ = 301 抵达了客户端,那么客户端是有可能正常接收这个过期的报文,这就会产生数据错乱等严重的问题。

数据包丢失

第一次挥手丢失了,会发生什么?
客户端重传 FIN 报文,超过阈值之后进入close 状态。

第二次挥手丢失了,会发生什么?
第二次挥手发的是ACK 报文,ACK 报文是不会重传的,所以如果服务端的第二次挥手丢失了,还是客户端这边超时重传第一次挥手的FIN 报文,直到收到服务端的第二次挥手的ACK报文,或者达到最大的重传次数进入close状态。

第三次挥手丢失了,会发生什么?
服务端重发 FIN 报文,超过阈值之后进入close 状态。

第四次挥手丢失了,会发生什么?
同样的。第四次挥手的ACK不会重传,所以服务端会重传FIN。
如果客户端在2MSL时间内能收到重传FIN,则客户端可以重传ACK,否则客户端关闭,服务端也会在重传FIN达到一定次数之后关闭。

客户端在收到第三次挥手的FIN 报文之后,再次收到服务端的数据包会怎么处理

客户端如果收到乱序的 FIN 报文,会将FIN包加入到「乱序队列」,并不会进入到 TIME_WAIT 状态。
等收到前面被网络延迟的数据包时,重组报文得到完整顺序的数据包之后,发现有 FIN 标志,这时才会进入 TIME_WAIT 状态。

客户端在 TIME_WAIT 状态下收到服务端的数据包会怎么处理?

客户端会发送该数据包的 ACK 确认报文,然后丢掉该数据包。

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值