加入收藏 | 设为首页 | 会员中心 | 我要投稿 | RSS
您当前的位置:首页 > 公告

面试官,不要再问我三次握手和四次挥手

时间:2024-11-13 13:52:28  来源:http://www.baidu.com/  作者:亲卫队请问

面试中经常遇到关于三次握手和四次挥手的考点,这些问题不仅检验基础知识的掌握程度,更考察思维的深度和广度。许多求职者在面对这类问题时,虽然一开始回答得不错,但往往越说越紧张,最后无法充分展示自己的能力。

面试官常常会从三次握手开始问起。当求职者回答“第一次握手是客户端发送报文给服务器,第二次是服务器回应,第三次是客户端再次确认”时,面试官可能会进一步追问更多细节。如:“为什么要进行三次握手?”或者“什么是半连接队列?”等等。这些问题不仅需要求职者回答正确,更需要他们深入理解并扩展相关知识。

那么,三次握手到底是什么呢?其实,它是一个建立TCP连接的过程,需要客户端和服务器共发送三个包。它的主要作用是确认双方的接收和发送能力是否正常,为后续的可靠传输做准备。在这个过程中,双方的状态会从Closed到SYN_SEND,再到SYN_REVD,最后达到ESTABLISHED状态。

那么,为什么需要三次握手而不是两次呢?这是因为,只有通过三次握手,双方才能确认彼此的接收和发送能力均正常。如果只进行两次握手,服务器无法确认客户端的接收能力是否正常。为了确保通信的顺利进行,三次握手是必要的。

除了三次握手,还有四次挥手。当连接需要释放时,需要进行四次挥手。这个过程涉及到等待2MSL的意义以及SYN攻击等问题。在四次挥手的过程中,双方通过发送ACK报文来确认连接的释放,确保数据的完整性和可靠性。等待2MSL是为了确保双方都能收到最后的ACK报文,避免因网络延迟导致的问题。而SYN攻击则是一种利用TCP协议漏洞进行的恶意攻击方式,需要采取相应的防范措施来保护网络安全。

设想一下,如果采用两次握手来建立连接,情形会是这样的:客户端发出连接请求,但由于某些原因,连接请求报文丢失了,客户端不得不再次发送连接请求。这次,确认信息终于收到了,连接得以建立。在数据传输完成后释放连接时,出现了一个问题。客户端总共发送了两个连接请求报文段,其中第一个丢失了,第二个成功到达了服务端。但第一个丢失的报文段在网络中的某些节点上滞留了很长时间,延迟到连接释放之后才到达服务端。服务端误以为客户端又发起了一次新的连接请求,于是回复确认报文,同意建立连接。在没有采用三次握手的情况下,只要服务端发出确认,新的连接就被建立了。客户端选择忽略服务端的确认,并不发送数据,导致服务端一直等待客户端的数据,造成资源浪费。

那么,什么是半连接队列呢?当服务器初次收到客户端的SYN信号时,它会进入SYN_RCVD状态。在这个阶段,双方尚未完全建立连接,服务器会将这种状态下的请求连接放入一个特殊的队列中,我们称之为半连接队列。还有另一个全连接队列,已经完成了三次握手的连接会被放入此队列中。如果队列满了,就可能出现丢包的现象。

再补充一点关于SYN-ACK重传次数的问题:服务器发送完SYN-ACK包后,如果没有收到客户的确认包,服务器会进行首次重传。等待一段时间后仍未收到确认,就会进行第二次重传。如果重传次数超过了系统设定的最大重传次数,系统会将该连接信息从半连接队列中删除。值得注意的是,每次重传的等待时间并不固定,一般会呈指数增长,例如1秒、2秒、4秒、8秒……

接下来,我们来探讨ISN(Initial Sequence Number)是否固定。当一方为了建立连接而发送SYN时,它会为连接选择一个初始序号。这个ISN是随时间变化的,所以每个连接都会有一个独特的ISN。ISN可以看作是一个32比特的计数器,每4毫秒加1。选择序号的目的在于防止网络中的延迟分组被重新传送,导致连接的一方对其做出错误的解释。在三次握手的过程中,客户端和服务端交换ISN,以便正确地组装数据。由于攻击者容易猜测固定的ISN的后续确认号,因此ISN是动态生成的。

那么在三次握手的过程中能否携带数据呢?实际上,第三次握手是可以携带数据的,但第一次和第二次握手则不可以。为什么这样规定呢?想象一下,如果第一次握手就可以携带数据,那么如果有人恶意攻击服务器,他们可以在SYN报文中放入大量数据。因为攻击者并不关心服务器的接收、发送能力,所以他们可能会不停地重复发送SYN报文。这会让服务器花费大量时间和内存来接收这些报文。也就是说,第一次握手不放数据的原因之一是为了防止服务器受到更严重的攻击。而对于第三次握手来说,此时客户端已经处于ESTABLISHED状态,知道服务器的接收、发送能力是正常的,所以携带数据是没有问题的。

当我们探讨TCP协议的精髓时,不得不提其强大的连接管理能力。“半关闭”状态,是TCP赋予连接的一种独特能力,即当连接的一端完成发送后,依然能够接收来自另一端的数据。这种机制为数据传输提供了极大的灵活性。

关于TCP连接的终止,它需要通过四次握手,我们称之为“四次挥手”。这一过程的精髓在于客户端与服务器之间的协同工作,双方均可主动发起关闭动作。

想象一下,双方初始时都处于“ESTABLISHED”状态,当客户端决定结束其连接请求时,四次挥手的旅程就开始了。

第一次挥手:客户端首先发送一个带有特定序列号的FIN报文,它表达了一种意愿:我要结束了。客户端进入FIN_WAIT1状态,等待服务器的回应。

第二次挥手:服务器收到FIN报文后,通过发送ACK报文确认收到。这个ACK报文带有特殊的序列号,表明它已经收到客户端的报文。服务器进入CLOSE_WAIT状态,而TCP连接处于半关闭状态。

第三次挥手:如果服务器也准备断开连接,它会发送一个带有特定序列号的FIN报文给客户端。这是服务器的告别信号。服务器进入LAST_ACK状态,等待客户端的确认。

第四次挥手:客户端收到服务器的FIN报文后,回应一个ACK报文,确认收到。客户端进入TIME_WAIT状态。这是一个等待期,确保服务器收到自己的ACK报文后再完全关闭。一旦这个时间段过去,连接就完全关闭了。

那么,为什么需要四次挥手呢?因为当服务端收到客户端的SYN连接请求报文后,可以直接发送SYN+ACK报文,其中SYN用于同步,而ACK用于应答。但在关闭连接时,服务端的响应需要分两步进行:首先回复ACK报文告知收到FIN报文;然后等所有报文发送完毕后,再发送FIN报文结束连接。因此不能同时进行这两步操作,所以必须是四次挥手。

关于TIME_WAIT状态的2MSL等待期也非常重要。这是为了确保客户端发送的最后一个ACK报文能够到达服务器。每个TCP实现都会选择一个MSL值(报文段的最大生存时间),在这个时间内报文段在网络内存在的时间是有限的。对于TCP来说,当执行主动关闭并发回最后一个ACK时,连接必须在TIME_WAIT状态停留的时间为两倍的MSL。这样做的目的是为了防止ACK丢失并导致重新发起连接关闭请求的情况。在等待期间,与该连接相关的插口不能被再次使用,确保网络连接的唯一性和稳定性。这样的设计确保了数据传输的可靠性和效率。为何要确保TCP连接的ACK报文段的成功传输,以及为何TIME_WAIT状态需要经过两倍的报文段生存时间(MSL)才能返回到CLOSE状态?

理解TCP连接的稳定性:

在TCP协议的运作过程中,每个连接都会经历一系列的通信过程,其中包括建立连接时的三次握手和断开连接时的四次挥手。在这个过程中,ACK报文段起到了至关重要的作用。ACK丢失或未到达服务器可能会引发一系列的问题,如连接无法顺利关闭。我们需要确保ACK报文段的成功传输。以下是其中的两个核心原因:

一、确保客户端发送的最后一个ACK报文段能够到达服务端。在TCP连接关闭的过程中,当客户端接收到服务器的FIN报文段后,它会发送一个ACK报文段进行确认。如果此时这个ACK报文段丢失了,那么服务器可能会因为收不到确认而重新发送FIN报文段。为了处理这种情况,客户端需要在发送完ACK报文段后进入TIME_WAIT状态等待一段时间。这样,如果服务器重发了FIN报文段,客户端可以重新确认并重新启动计时器。如果客户端在发送完ACK后立即释放连接,那么它就无法收到服务器重发的FIN报文段,导致连接无法正常关闭。TIME_WAIT状态的存在是为了确保所有必要的确认都已成功发送并收到。

二、防止“已失效的连接请求报文段”出现在本连接中。当客户端完成最后的ACK报文段发送后,它会进入一段等待期即2MSL。这个等待期是为了确保本连接的所有报文段都从网络中消失。这是为了确保在下一个新的连接中不会出现旧的连接请求报文段,避免混淆和错误。这是一个确保网络稳定性和可靠性的重要步骤。这也是为什么在TCP协议设计中,即使所有报文都已经发送完毕,我们仍然需要等待一段时间才能完全关闭连接的原因。这种设计反映了网络世界的复杂性及其对可靠性的要求。理论上,当所有的报文都发送完毕后,可以直接进入CLOSE状态。但由于网络的不可靠性,为了确保信息的完整传输和连接的顺利关闭,我们必须采取这样的策略。这种策略虽然可能增加了一些延迟,但它确保了连接的稳定性和可靠性。这就是TCP协议的设计理念之一:可靠传输优于快速传输。理解了这些背后的原因和逻辑,我们就可以更深入地理解TCP协议的设计初衷和工作机制了。下次再谈论TCP的三次握手和四次挥手时,就可以分享这些深入的理解了。参考《TCP/IP详解 卷1:协议》,其中的TCP状态变迁图就是一个很好的工具,能够帮助我们直观地理解这一过程。

来顶一下
返回首页
返回首页
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
推荐资讯
相关文章
栏目更新
栏目热门