为什么TCP握手是三次挥手是四次?

修改

修改于2018年11月18日,之前的理解有误,今天听了老师的解释,重新理解了三次握手和四次挥手,从服务端承担空连接的风险分析我认为更为合理。

三次握手

回顾三次握手

三次握手建立连接,客户端在创建socket网络套接字后,会通过三次握手这个过程来进行连接:

  1. 调用connect向服务端发起连接请求,发送了一个SYN,阻塞等待服务端回复(第一次握手)
  2. 服务端收到客户端发送的SYN,为了让客户端知道他这准备好了,于是回了一个ACK告诉客户端我准备好了,并且发了一个SYN问客户端准备好没(第二次握手)
  3. 客户端收到服务端回复的ACK,进入ESTABLELISHED状态,准备就绪,并回了一个ACK给服务端说我也准备好了,服务端收到ACK确认了对方状态,于是也进入ESTABLELISHED状态,连接建立(第三次握手)

为什么是三次握手而不是两次或四次?

三次肯定是有道理的,存在即合理,三次可以让双方都确定连接到对方后能收到对方的回复,双方都准备好了。

如果是两次,那么看下面过程,仔细对比上面的三次握手:

  1. 客户端调用connect,发送了一个SYN,然后服务端接收这个SYN(第一次握手)
  2. 服务端接收之后就会返回一个ACK,那么客户端就进入ESTABLELISHED状态(第二次握手)

图片解释:看不清请点击放大查看大图
三次握手
这其中有一个问题,那就是服务端并不知道,如果服务端发送一个消息,客户端会不会回复,如果客户端不回复,那么这个连接就是不可靠的,我服务端给你发数据,你居然不回我你收到没,那服务端怎么可能知道客户端是收到还是没收到?????

也就是说当我两次握手的时候,首先,客户端知道他到服务端的连接已成功,但是服务端并不知晓连接是否成功。假如客户端没有收到服务端发送的ACK,那么服务端不知晓的情况下,这个空连接的负载就挂在服务端了,如果一个服务端有很多个这样的连接请求,那么就会挂很多的空连接,浪费很多的服务端资源,这是很可怕的一件事情,因为阻挡了正常请求资源的连接。

要知道世界上没有绝对可靠的连接协议,由于TCP的回复机制,尽管最后一条消息,可能接收方并不知道是否成功,但是倒数第二条的消息肯定是可靠的,因为最后一条消息会回复收到没,但是这个回复不一定成功。

同样的在TCP连接过程中,如果是两次握手,那么这个连接的最后回复的永远是服务端,那么最后一条回复的消息,可能失效,那么失效的后果就是服务端要去承担这个风险,服务端一直发数据,结果没人接收,这个空连接会挂载相当长一段时间。

如果是三次握手,那么在连接过程中,最后一次回复是客户端,那么即使服务端没有收到这个回复,也无关紧要,这个风险就让客户端去承担吧,无非是客户端认为连接成功了,但是发送数据没有回应而已,一个客户端能挂几个连接,相比于服务端,要服务很多客户端,当然是服务端更重要。

所以服务端也要回一个SYN进行第三次握手,而不是光返回一个ACK,这个SYN需要由客户端回复的ACK确认,客户端回复ACK的时候就认为连接建立成功了,即使失效,客户端挂载空连接而已,大不了去重新新建连接去连接服务端。

所以二次不行,同样的,四次的话,首先握手多余,其次这个连接无效的风险还是要服务端去承担,这肯定不行;五次握手理论上是可以的,但是显然三次可以做到的事情,做五次的话,只能默默骂一句,傻逼。。。。

四次挥手

回顾四次挥手

如果客户端没有请求了,主动关闭,那么便会调用close关闭连接

  1. 客户端调用close,发送了一个FIN包给服务端,告诉服务端要断开了(第一次挥手)
  2. 服务端收到FIN后,告诉客户端我知道了要断开连接了,于是发了一个ACK给客户端,同时recv(或read)会返回0(第二次挥手)
  3. recv和read返回0,于是服务端也调用了close关闭套接字问价,并给客户端发了一个FIN包,告诉客户端我也要关了(第三次挥手)
  4. 客户端收到FIN,回了一个ACK,说我知道了,断了吧(第四次挥手)

为什么是四次挥手,不是三次或五次?

首先,主动关闭方是会先发送FIN包给被动关闭方的,这个主动关闭方可能是客户端也可能是服务端,只不过大部分的情况都是客户端主动关闭。

那为啥是四次???我们以客户端主动关闭举例

首先我们已经知道了TCP的连接是全双工的,可以发送也可以接收,主动关闭方发送FIN,表明主动方已经没有数据需要发送了,告诉被动方我要断了,被动方回一个ACK,表明已知晓主动方无数据,准备断开了。

但是被动方也就是服务端可能依旧有数据还没有发送完毕,客户端没有数据发送不代表服务端没有数据发送啊,于是等服务端数据发送完毕。等到服务端这一端数据发完了,就可以彻底断开连接的,所以服务端也发了一个FIN包,告诉客户端我工作做完了,我也要关了,等到服务端收到客户端的ACK或者超出等待时间那么就断开连接,此时的连接才算真正意义上的断开。

三次的话如果类比三次握手,在第二次挥手的时候直接发FIN + ACK明显不合理,因为被动方可能没有数据发送完,你这么关太草率了,所以需要四次,至于五次,四次就能断开了,还来五次。。。多此一举。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值