TCP传输的三次握手与四次挥手策略

在这里插入图片描述
从图片可以得到三次握手可以简化为:C发起请求连接S确认,也发起连接C确认
每次握手的作用:

first:S只可以确认自己可以接受C发送的报文段
second:C可以确认 S收到了自己发送的报文段,并且可以确认自己可以接受S发送的报文段
third:S可以确认 C收到了自己发送的报文段

考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。可是,C在S的应答分组在传输中被丢失的情况下,将不知道S是否已准备好,不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。

一、为了准确无误地把数据送达目标处,TCP采用了三次握手策略:

  • first:用TCP把数据包发送出去后,TCP不会对传送后的数据置之不理,它一定会向对方确认是否成功送达。握手过程中使用了TCP的标志,即SYN和ACK。

  • second:发送端首先给接收端发送一个带SYN标志的数据包。接收端收到后,回传一个带有SYN/ACK标志的数据包以表示正确传达,并确认信息。

  • third:最后,发送端再回传一个带ACK标志的数据包,代表“握手”结束。

:若在握手过程中的某个阶段莫名中断,TCP会再次以相同的顺序发送相同的数据包。

二、断开一个TCP连接则需要“四次挥手”:

  • first:主动关闭方发送一个FIN,用来关闭主动关闭方到被动关闭方的数据传送,也就是主动关闭方告诉被动关闭方,主动关闭方已经不会再给被动关闭方发送数据了(当然,在FIN包之前发送出去的数据,如果没有收到对应的ACK确认报文,主动关闭方依然会重发这些数据),但是,此时主动关闭方还可以接收数据。

  • second:被动关闭方收到FIN包后,给对方发送一个ACK,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号)。

  • third:被动关闭方发送一个FIN,用来关闭被动关闭方到主动关闭方的数据传送,也就是告诉主动关闭方,被动关闭方的数据也发送完了,不会再给主动关闭方发送数据了。

  • fourth:主动关闭方收到FIN后,给被动关闭方发送一个ACK,确认序号为收到序号+1,至此,完成四次挥手。

常见面试题

【问题1】为什么连接的时候是三次握手,关闭的时候却是四次握手?

  • 当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。
  • 但在关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,“你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

【问题2】为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

  • 在挥手结束时需要Client发送一个最后的ACK应答报文,但这个ACK报文可能会丢失。

  • 如果Server没有收到这个ACK报文,它将不断重复发送FIN片段,因此Client不能立即关闭,它需要确定Server接收到了该ACK。

  • Client会在发送出ACK之后进入TIME_WAIT状态,Client会设置一个计时器,等待2MSL的时间。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。

  • 如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL;如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。

【问题3】为什么不能用两次握手进行连接?

  • 第三次是为了防止出现死锁现象。

解释:客户端给服务端发送一个连接请求报文,服务端收到后会回传给客户端一个确认应答报文;但服务端在回传的过程中,若出现了该确认应答报文丢失的情况,则之前的连接请求报文就将失效,客户端将不知道服务端是否已准备好,不知道服务端建立什么样的序列号,客户端甚至怀疑服务端是否收到自己的连接请求分组。在这种情况下,客户端认为连接还未建立成功,将忽略服务端发来的任何数据分组,只等待连接确认应答分组。而服务端在发出的分组超时后,重复发送同样的分组,出现死锁现象。

  • 客户端有可能因为网络阻塞等原因会发送多个请求报文,这时服务器就会建立连接,浪费掉许多服务器的资源。

解释:客户端发出的第一个连接请求报文段并没有丢失,而是在某些网络结点长时间滞留了,一直延迟到连接释放以后的某个时间才到达服务器,本来这是一个早已失效的报文段。但服务器收到此失效的连接请求报文段后,就误认为是客户端又发出一次新的连接请求,于是就向客户端发出确认报文段,同意建立连接。假定不采用三次握手,那么只要服务端发出确认,新的连接就建立了,这样一直等待客户端发来数据,服务端的许多资源就浪费了。

【问题4】如果已经建立了连接,但是客户端突然出现故障了怎么办?

  • TCP还设有一个保活计时器,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。

  • 服务器每收到一次客户端的请求后都会复位这个计时器,时间通常是设置为两小时。若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章