TCP的三次握手和四次挥手

名词解释:

三次握手:

  1. CLOSED:不在连接状态。(客户端原本所处的状态)
  2. LISTEN:等待从任何远端TCP 和端口的连接请求。(服务器原本所处的状态)
  3.  SYN_SENT:发送完一个连接请求后等待一个匹配的连接请求。(客户端在第一次握手后所处的状态)
  4.  SYN_RECEIVED:发送连接请求并且接收到匹配的连接请求以后等待连接请求确认。(服务器在第二次握手后所处的状态)
  5.  ESTABLISHED:表示一个打开的连接,接收到的数据可以被投递给用户。连接的数据传输阶段的正常状态。(客户端和服务器在第三次握手成功后所处的状态)

四次挥手:

  1. FIN_WAIT_1:等待远端TCP 的连接终止请求,或者等待之前发送的连接终止请求的确认。(客户端在第一次挥手后所处的状态)
  2.  CLOSE_WAIT:等待本地用户的连接终止请求。(服务器在第二次挥手后所处的状态)
  3.  FIN_WAIT_2:等待远端TCP 的连接终止请求。(客户端在第二次挥后前所处的状态)
  4.  LAST_ACK:等待先前发送给远端TCP 的连接终止请求的确认,包括它字节的连接终止请求的确认。(服务器在第三次挥手后所处的状态)
  5. TIME_WAIT:等待足够的时间过去以确保远端TCP 接收到它的连接终止请求的确认。(客户端在第四次挥后前所处的状态)
  6.  CLOSING:等待远端TCP 的连接终止请求确认。

三次握手:

        三次握手(Three-way Handshake)其实就是指建立一个TCP连接时,需要客户端和服务器总共发送3个包。

三次握手的主要作用:

        就是为了确认双方的接收能力和发送能力是否正常、指定自己的初始化序列号为后面的可靠性传送做准备。

三次握手的过程:

第一次握手

  • 客户端发送网络包,服务端收到了。
  • 客户端的发送能力、服务端的接收能力是正常的。
  1. 客户端给服务端发一个 SYN 报文,并指明客户端的初始化序列号 ISN。
  2. 此时客户端处于 SYN_SENT 状态。
  3. 首部的同步位SYN=1,初始序号seq=x,SYN=1的报文段不能携带数据,但要消耗掉一个序号。

第二次握手

  • 服务端发包,客户端收到了。
  • 服务端的接收、发送能力,客户端的接收、发送能力是正常的。
  • 但此时服务器并不能完全确认客户端的接收能力是否正常。
  1. 服务器收到客户端的 SYN 报文之后,会以自己的 SYN 报文作为应答,并且也是指定了自己的初始化序列号 ISN。同时会把客户端的 ISN + 1 作为ACK 的值,表示自己已经收到了客户端的 SYN,
  2. 此时服务器处于 SYN_RCVD 的状态。
  3. 在确认报文段中SYN=1,ACK=1,确认号ack=x+1,初始序号seq=y。

第三次握手:

  • 客户端发包,服务端收到了。
  • 客户端的接收、发送能力正常,服务器的发送、接收能力也正常。
  • 只有当客户端接受了服务器发送的包,并成功发送给服务器,才能确认客服端的接受能力是正常的。
  1. 客户端收到 SYNACK 报文之后,会发送一个 ACK 报文,当然,也是一样把服务器的 ISN + 1 作为 ACK 的值,表示已经收到了服务端的 SYN 报文,
  2. 此时客户端处于 ESTABLISHED 状态。服务器收到 ACK 报文之后,也处于 ESTABLISHED 状态,此时,双方已建立起了连接。
  3. 确认报文段ACK=1,确认号ack=y+1,序号seq=x+1(初始为seq=x,第二个报文段所以要+1),ACK报文段可以携带数据,不携带数据则不消耗序号。

第三次握手的作用:

        前两次握手只能确认服务器和客户端的发送和接收能力正常,但服务器并不知道客户端是否成功接收到了自己发送的消息。通过第三次握手,客户端返回确认消息给服务器,服务器才能确认自己的发送和客户端的接收都正常。

第三次握手的主要目的是为了确认客户端的接收能力正常

三次握手的图文表示:

为什么两次握手不行:

        三次握手的首要原因是为了防止旧的重复连接初始化造成混乱

        考虑一个场景,客户端先发送了 SYN(seq = 90)报文,然后客户端宕机了,而且这个 SYN 报文还被网络阻塞了,服务端并没有收到,接着客户端重启后,又重新向服务端建立连接,发送了 SYN(seq = 100)报文。

根据下图来理解三次握手是如何阻止历史连接的:

客户端连续发送多次 SYN建立连接的报文,在网络拥堵情况下:

  1. 一个“旧 SYN 报文”比最“新的 SYN 报文”早到达了服务端,那么此时服务端就会回一个 SYN + ACK 报文给客户端,此报文中的确认号是 91(90+1)。
  2. 客户端收到后,发现自己期望收到的确认号应该是 100 + 1,而不是 90 + 1,于是就会回 RST 报文。
  3. 服务端收到 RST 报文后,就会释放连接。
  4. 后续最新的 SYN 抵达了服务端后,客户端与服务端就可以正常的完成三次握手了。

二次握手会出现什么情况:

        所有如果只有两次握手,那么客户端和服务器之间的连接可能无法正常建立。具体来说的话,可能会出现以下情况:

  1. 已失效的连接请求报文段可能会突然传送到服务器,导致服务器错误地认为客户端已经建立了连接,从而发送数据给客户端。但是,由于客户端并没有发送第三次握手,所以客户端无法接收到这些数据,从而导致数据丢失或连接中断。
  2. 客户端和服务器之间的网络可能会存在延迟或丢包等问题,导致第二次握手无法到达客户端或服务器。如果只有两次握手,那么客户端和服务器都无法确定对方是否成功接收到了自己的消息,从而导致连接无法正常建立。

        为了避免这些问题,TCP 引入了第三次握手,以确保客户端和服务器之间的连接能够正常建立,并且防止已失效的连接请求报文段突然传送到服务器产生错误。

三次握手过程中可以携带数据吗:

        在第三次握手的时候,是可以携带数据的。但是,第一次、第二次握手不可以携带数据。

        大家可以想一个问题,假如第一次握手可以携带数据的话,如果有人要恶意攻击服务器,那他每次都在第一次握手中的 SYN 报文中放入大量的数据,这时攻击者根本就不关心服务器的接收、发送能力是否正常,只是疯狂重复发 SYN 报文,这会让服务器花费很多时间、内存空间来接收这些报文。所以第一次握手不可以放数据,其中一个简单的原因就是会让服务器更加容易受到攻击了。

        而对于第三次的话,此时客户端已经处于 ESTABLISHED 状态。对于客户端来说,他已经建立起连接了,并且也已经知道服务器的接收、发送能力是正常的了,所以可以携带数据了。

四次挥手:

        TCP 连接的拆除需要发送四个包,因此称为四次挥手(Four-way handshake),客户端或服务端均可主动发起挥手动作。

为什么要四次挥手,而不是三次:

        建立一个连接需要三次握手,而终止一个连接要经过四次挥手,这是由TCP的半关闭(half-close)造成的。

        所谓的半关闭,其实就是TCP提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力。

        所以要想终止一个链接,除了客户端(主动关闭者)发起关闭,还要经过服务器(被关闭者)的同意,才能最终终止数据的传输。因此在第三次挥手时,是由服务器向客户端放送包,来告诉它我没有要传输的数据,可以关闭。所以比起三次握手,在挥手的时候,会多一次发送包的过程。

四次挥手的过程:

        刚开始双方都处于ESTABLISHED 状态,假如是客户端先发起关闭请求。四次挥手的过程如下:

第一次挥手:

客户端发送一个 FIN 报文,报文中会指定一个序列号。

  1. 即发出连接释放报文段(FIN=1,序号seq=u),并停止再发送数据,主动关闭TCP连接。
  2. 进入FIN_WAIT1(终止等待1)状态,等待服务端的确认。

第二次挥手:

服务端收到 FIN 之后,会发送 ACK 报文,且把客户端的序列号值 +1 作为 ACK 报文的序列号值,表明已经收到客户端的报文了

  1. 即服务端收到连接释放报文段后即发出确认报文段(ACK=1,确认号ack=u+1,序号seq=v)。
  2. 服务端进入CLOSE_WAIT(关闭等待)状态。
  3. 此时的TCP处于半关闭状态,客户端到服务端的连接释放。客户端收到服务端的确认后,进入FIN_WAIT2(终止等待2)状态,等待服务端发出的连接释放报文段。

第三次挥手:

如果服务端也想断开连接了,和客户端的第一次挥手一样,发给 FIN 报文,且指定一个序列号。

  1. 即服务端没有要向客户端发出的数据,服务端发出连接释放报文段(FIN=1,ACK=1,序号seq=w,确认号ack=u+1)
  2. 服务端进入LAST_ACK(最后确认)状态,等待客户端的确认。

第四次挥手:

客户端收到 FIN 之后,一样发送一个 ACK 报文作为应答,且把服务端的序列号值 +1 作为自己 ACK 报文的序列号值,需要过一阵子以确保服务端收到自己的 ACK 报文之后才会进入 CLOSED 状态,服务端收到 ACK 报文之后,就处于关闭连接了,处于 CLOSED 状态。

  1. 即客户端收到服务端的连接释放报文段后,对此发出确认报文段(ACK=1,seq=u+1,ack=w+1)
  2. 客户端进入TIME_WAIT(时间等待)状态。
  3. 此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,客户端才进入CLOSED状态。

四次挥手的图文表示:

四次挥手释放连接时,等待2MSL的意义:

        为了保证客户端发送的最后一个ACK报文段能够到达服务器。因为这个ACK有可能丢失,从而导致处在LAST-ACK状态的服务器收不到对FIN-ACK的确认报文。服务器会超时重传这个FIN-ACK,接着客户端再重传一次确认,重新启动时间等待计时器。最后客户端和服务器都能正常的关闭。假设客户端不等待2MSL,而是在发送完ACK之后直接释放关闭,一但这个ACK丢失的话,服务器就无法正常的进入关闭连接状态。

参考链接:

面试官,不要再问我三次握手和四次挥手_猿人谷 三次握手四次挥手-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值