当前位置: 首页 > 后端技术 > Java

面试官:为什么TCP需要三次握手四次分手?大多数人都答不上来!

时间:2023-04-01 13:17:19 Java

作者:Can'twaitfortheharmonica\来源:cnblogs.com/Courage129/p/14324605.htmlTCP协议简介用于将消息发送到另一台机器上的对等层(假设是服务器),每个依赖层都会对消息进行打包。例如TCP协议依赖于网络层的IP协议,所以发送的报文会经过如下封装:当数据包到达服务器后,服务器的网络层会解封装并校验其中的内容IP相关协议,然后传输层将解封装TCP层。解封装涉及一系列步骤,比如这个包是干什么用的?是寄给我吗?这些操作需要根据TCP报文的头部信息来判断。Header包含以下内容:主要是通过header信息来了解这个数据包是干什么用的。关于header信息,这里列举几个需要用到的。:ACK:TCP协议规定只有ACK=1时才有效,同时也规定连接建立后所有发送报文的ACK必须为1SYN(SYNchronization):用于在连接建立时同步序号已确立的。当SYN=1,ACK=0时,表示这是一条连接请求报文。如果对方同意建立连接,则应在响应消息中设置SYN=1和ACK=1。因此,将SYN设置为1表示这是一个连接请求或连接接受消息。FIN(finis):即终止的意思,用来释放一个连接。当FIN=1时,表示本段发送方的数据已经发送完毕,需要释放连接。《注意》:URG、ACK、PSH、PST、RST、SYN、FIN只有一位,即只有0或1两种状态。TCP协议三次握手“第一次握手”:客户端先发送一个请求连接到服务器的消息段。该报文段的SYN位设置为1,序号Seq(SequenceNumber)设置为某个值。假设对于X,客户端发出后进入SYN_SEND状态,等待服务器的确认;“第二次握手”:服务器收到SYN报文段。服务端收到客户端的SYN报文段后需要对SYN报文段进行确认,将AcknowledgementNumber设置为x+1(SequenceNumber+1);同时需要自己发送SYN请求报文,并将SYN位设置为1,SequenceNumber为y;服务器将上述所有信息放入一个报文段(即SYN+ACK报文段),一并发送给客户端,此时服务器进入SYN_RECV状态;“第三次握手”:客户端收到服务器的SYN+ACK报文段。然后将AcknowledgementNumber设置为y+1,向服务器发送一个ACK报文段。报文段发送完毕后,客户端和服务器都进入ESTABLISHED状态,完成TCP三次握手。完成三次握手后,客户端和服务器就可以开始传输数据了。以上就是TCP三次握手的大致介绍。为什么我们需要握手三次而不是两次?为什么要建立三个连接?两次可以吗?谢希仁的《计算机网络》中说:为了防止突然向服务器发送无效的连接请求段,出现错误。如下:“无效连接请求段”的产生发生在这样一种情况:客户端发送的第一个连接请求段并没有丢失,而是长时间停留在某个网络节点,导致延迟直到连接被释放到达服务器后的某个时间。原来这是一个已经过期的段。但是,服务端在收到无效的连接请求报文后,误认为是客户端再次发送的新的连接请求。然后向客户端发送确认消息段,同意建立连接。假设不使用“三次握手”,只要服务器发送确认,就建立了新的连接。由于客户端还没有发出建立连接的请求,所以会忽略服务器的确认,不会向服务器发送数据。但是服务端认为新的传输连接已经建立,一直等待客户端发送数据。这样就浪费了服务器的很多资源。“三次握手”的方法可以防止上述现象的发生。比如刚才的情况,客户端不会发送确认给服务器的确认。由于服务端没有收到确认,就知道客户端没有请求建立连接。",这样可以防止服务器等待和浪费资源。第三次握手失败怎么办?tcp三次握手中,第二次握手完成后,connect返回成功。如果第三次握手的ack包丢失,则客户端已经认为连接成功。如果没有应用层心跳包,客户端会一直保持这个连接,如何避免这种情况呢?第二次握手服务器收到SYN包,然后发送SYN+ACK包确认收到并请求建立连接,服务器进入SYN_RECV状态。此时客户端在第三次握手时未能向服务器发送ACK,服务器也没有办法进入ESTABLISH状态。此时,不得传输数据。无论客户端是否主动发送数据,服务端都会有一个定时器发送第二步。SYN+ACK包,如果客户端再次发送ACK成功,则连接建立。如果一直不成功,服务器肯定会有超时(64s左右)的设置。超时后,它会向客户端发送“RTS消息”(连接重置)并进入CLOSED状态,以防止SYN泛洪攻击。这时,客户端应该也会关闭连接。“SYNfloodattack:”SYN攻击利用了TCP的三次握手机制。攻击端使用伪造的IP地址向被攻击端发送请求,被攻击端发送的响应报文永远不会发送到目的地。“被攻击端在等待关闭此连接时消耗资源。”如果有数万个这样的连接,就会耗尽主机的资源,从而达到攻击的目的。TCP协议的四次分手还是这张图镇贴:四次分手,意思是某一端(要么是客户端,要么是服务端)要结束会话,断开连接,那么具体过程就是:“第一次分手”:Host1,设置序号Seq(SequenceNumber)和确认包ACK(AcknowledgmentNumber),假设seq为x+2,ACK=y+1,然后设置FIN标志为1,发送一个FIN报文段给host2;之后,主机1进入FIN_WAIT_1状态;这意味着主机1没有数据要发送给主机2;“二次分离”:主机2收到主机1发送的FIN报文段,并向主机1返回一个ACK报文段(其值为收到的FIN报文的seq值+1);主机1进入FIN_WAIT_2状态,等待主机2的断开连接请求包FIN;“第三次分离”:主机2向主机1发送一个FIN报文段,表示我可以断开连接,请求关闭连接,主机2同时进入CLOSE_WAIT状态;“第四次分手”:主机1收到主机2发送的FIN报文段,向主机2发送ACK报文段,值为刚刚收到的FIN包Seq值+1,然后主机1进入TIME_WAIT状态;主机2收到主机1的ACK报文后,关闭连接;此时主机1在等待2MSL后仍然没有收到回复,证明Server端已经正常关闭,好了,主机1也可以关闭连接了。为什么要挥手四次TCP是全双工模式,也就是说当主机1发送一个FIN报文段的时候,只是说明主机1没有数据要发送,而主机1告诉主机2它所有的数据都有了发送完毕;但是此时主机1仍然可以接受来自主机2的数据;当主机2返回ACK报文段时,表示它已经知道主机1没有数据发送,但主机2仍然可以向主机1发送数据;当主机2也发送一个FIN报文段时,说明主机2没有数据要发送,它会告诉主机1我没有数据要发送,然后双方愉快的中断这个TCP连接。要想正确理解四次分手的原理,就需要了解四次分手过程中的状态变化。四次挥手状态解释“FIN_WAIT_1”:这个状态需要仔细解释一下。其实FIN_WAIT_1和FIN_WAIT_2状态的真正含义就是等待对方的FIN报文。这两种状态的区别在于,FIN_WAIT_1状态实际上是指当SOCKET处于ESTABLISHED状态时,想要主动关闭连接,向对方发送FIN报文。此时SOCKET进入FIN_WAIT_1状态。“即发送FIN包后进入FIN_WAIT_1状态”,当对方回复ACK报文后,进入FIN_WAIT_2状态。当然,在实际正常情况下,不管是什么情况,对方都应该立即响应ACK报文。所以FIN_WAIT_1状态一般很难看到,而FIN_WAIT_2状态用netstat经常可以看到。"即发送ACK报文后进入FIN_WAIT_2状态""ActivepartyFIN_WAIT_2":这个状态上面已经详细解释过了。其实处于FIN_WAIT_2状态的SOCKET表示半连接,也就是一方要求关闭连接,但是另外也要告诉对方我暂时还有一些数据要发给你(ACK信息),我稍后会关闭连接。“ActivesideCLOSE_WAIT”:这个状态的意思其实就是等待关闭。你怎么理解的?当对方关闭一个SOCKET并给自己发送FIN报文时,你的系统无疑会回应一个ACK报文给对方,然后进入CLOSE_WAIT状态。接下来,您真正需要考虑的是检查您是否还有数据要发送给对方。如果没有,那么可以关闭SOCKET,向对方发送FIN报文,即关闭连接。所以在CLOSE_WAIT状态下你需要做的就是等待你关闭连接。“被动方LAST_ACK”:这个状态比较好理解。是被动关闭方,在发送完FIN报文后等待对方的ACK报文。收到ACK报文后,可以进入CLOSED可用状态。"即收到对方的FIN包后,自己发送ACK和FIN包后的状态""被动方的TIME_WAIT":表示已经收到对方的FIN报文,ACK消息已发送,只需等待2MSL回到CLOSED可用状态。如果在FIN_WAIT1状态,当收到对方同时带有FIN标志和ACK标志的报文时,可以直接进入TIME_WAIT状态,不经过FIN_WAIT_2状态。“ActivepartyCLOSED”:表示连接中断。TCP状态图状态图解释CLOSED:起点,超时或连接关闭时进入该状态。LISTEN:svr端等待连接时的状态。svr端需要调用socket、bind、listen函数进入该状态。这称为被动打开应用程序(等待客户端连接)。SYN_SENT:客户端发起连接,向服务器发送SYN。如果服务器连接不上,则直接进入CLOSED状态。SYN_RCVD:对应3,服务器接受客户端的SYN请求,服务器从LISTEN状态进入SYN_RCVD状态。同时服务端要回应一个ACK,同时向客户端发送一个SYN;还有一种情况,当客户端在发起SYN的同时收到服务器的SYN请求,客户端会从SYN_SENT变为SYN_RCVD。ESTABLISHED:服务器和客户端完成3次握手后进入状态,表示已经可以开始数据传输了。以上就是对建立连接时服务端和客户端之间的状态转换的描述。比较简单明了。如果熟悉三次握手,建立连接时的状态转换还是很容易理解的。接下来,服务端和客户端进行数据传输。...,当然这里面的知识也很多,这里就先说到这里了,后面再讲解。接下来我们看一下连接关闭时状态转换的描述。关闭需要双方进行4次交互,包括一些善后工作(TIME_WAIT状态)。注意这里主动关闭的一方或者被动关闭的一方并不是特指服务器端或者客户端,这是相对于谁先发起关闭请求而言的。FIN_WAIT_1:主动关闭的一方,从状态5进入该状态,发送FIN给对方进行具体操作。FIN_WAIT_2:主动关闭的一方收到对方的FINACK,进入该状态。结果,无法再接收到对方的数据。但是能够互相发送数据。CLOSE_WAIT:收到FIN后,被动关闭的一方进入该状态。当接收到具体动作时,接收到FIN,同时发送ACK。LAST_ACK:被动关闭的一方发起关闭请求,从状态8进入该状态。具体动作时向对方发送FIN,收到ACK时进入CLOSED状态。CLOSING:当双方同时发起关闭请求时,FIN_WAIT_1会进入该状态。具体动作是收到一个FIN请求,同时回应一个ACK。TIME_WAIT:最纠结的状态来了。从状态图中可以看出,有3种状态可以转化成它。让我们一一分析:通过FIN_WAIT_2进入该状态:当双方没有同时发起FIN时,主动关闭的一方在完成自己发起的关闭请求后,收到被动关闭方的FIN后进入该状态。b.从CLOSING状态进入:双方同时发起关闭,都发起了FIN请求,当收到FIN并同时做出ACK时,从CLOSING状态进入。C。从FIN_WAIT_1状态进入:同时收到FIN(对方发起)和ACK(自己发起的FIN响应)。与b不同的是,自己发起的FIN响应的ACK先于对方的FIN请求到达,b表示FIN先到。这是最不可能的情况。4个关闭的连接中最不可理解的状态是TIME_WAIT。TIME_WAIT有2个原因:可靠地实现TCP全双工连接的终止。允许旧的重复部分在网络中消失。近期热点文章推荐:1.1000+Java面试题及答案(2022最新版)2.厉害了!Java协程来了。..3.SpringBoot2.x教程,太全面了!4.20w程序员红包封面,快拿。..5.《Java开发手册(嵩山版)》最新发布,赶快下载吧!感觉不错,别忘了点赞+转发!