TCP三次握手和四次挥手

TCP三次握手和四次挥手

三次握手

明确目的

TCP(传输控制协议)是一种可靠的面向连接的协议,用于在计算机之间传输数据。TCP 使用三次握手建立连接,四次挥手关闭连接。

在不可靠通信中,建立可靠数据通信, 三次握手让双放都能明确自己和对象的收发能力是正常的。

建立连接流程

第一次握手 客户端向服务端发送SYN(同步序列编号)包,并进入SYN_SEND状态,等待服务器确认

第二次握手 服务器收到SYN包,必须确认客户的SYN,同时自己也发送一个SYN+ACK包,此时服务器进入SYN_RECV状态

第三次握手 客户端收到SYN+ACK包,向服务器发送确认包---ACK 包,此包发送完毕后,双方进入ESTABLISHED状态, 至此,完成三次握手,TCP连接成功建立

分析三次握手的细节和原因

三次握手的最基本的目的是为了确认双放的收发能力均正常,可建立可靠连接

1. 第一次握手,客户端发送SYN包,由服务端接收

服务端视角: (当客户端接收到握手请求)

客户端发的东西我收到了,说明客户端发送正常,我(服务端)接收正常
  • 客户端发送能力ok
  • 客户端接收能力?
  • 服务端发送能力?
  • 服务端接收能力ok

客户端视角:

东西我是发出去了,我(客户端)是否发送成功——未知,服务端是否接收成功——未知
  • 客户端发送能力?
  • 客户端接收能力?
  • 服务端发送能力?
  • 服务端接收能力?

2. 第二次握手, 服务器确认客户端的SYN,并发送SYN+ACK包,由客户端接收

服务端视角:

 东西我发出去了,我(服务端)是否发送成功——未知,客户端是否接收成功——未知
  • 客户端发送能力ok
  • 客户端接收能力?
  • 服务端发送能力?
  • 服务端接收能力ok

客户端视角: (当收到服务端的SYN + ACK)

服务器发的东西我收到了,说明
1. 之前我(客户端)发送的消息,服务端收到了,说明我(客户端)的发送能力和服务端的接收能力正常
2. 服务端给我(客户端)回应了消息,我收到了,说明服务端的发送能力和我(客户端)的接收能力正常
  • 客户端发送能力ok
  • 客户端接收能力ok
  • 服务端发送能力ok
  • 服务端接收能力ok

至此,我(客户端)已经可以确定,双方的收发能力都正常,可以建立可靠的通讯连接。

3. 第三次握手, 客户端发送表示确认的ACK包,由服务端接收

服务端视角:

收到客户端ACK包,说明客户端接收到了我之前发的ACK包,可以确认我(服务端)的发送能力正常,客户端的接收能力也正常
  • 客户端发送能力ok
  • 客户端接收能力ok
  • 服务端发送能力ok
  • 服务端接收能力ok

至此,我(服务端)已经可以确定,双方的收发能力都正常,可以建立可靠的通讯连接

客户端视角:

第二次握手已经确定,双方的收发能力都正常,可以建立可靠的通讯连接

三次握手完成,双方都已确认彼此的发送、接收能力是正常的,TCP连接成功建立

三次握手的作用

  1. 确认双方的接收能力、发送能力是否正常。
  2. 指定自己的初始化序列号(ISN),为后面的可靠传送做准备。
  3. 如果是 https 协议的话,三次握手这个过程,还会进行数字证书的验证以及加密密钥的生成到。

相关问题

  1. (ISN)是固定的吗

    三次握手的一个重要功能是客户端和服务端交换ISN(Initial Sequence Number), 以便让对方知道接下来接收数据的时候如何按序列号组装数据。

    如果ISN是固定的,攻击者很容易猜出后续的确认号,因此 ISN 是动态生成的。

  2. 什么是半连接队列

    服务器第一次收到客户端的 SYN 之后,就会处于 SYN_RCVD 状态,此时双方还没有完全建立其连接,服务器会把此种状态下请求连接放在一个队列里,我们把这种队列称之为半连接队列。当然还有一个全连接队列,就是已经完成三次握手,建立起连接的就会放在全连接队列中。如果队列满了就有可能会出现丢包现象。

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

    很多人可能会认为三次握手都不能携带数据,其实第三次握手的时候,是可以携带数据的。也就是说,第一次、第二次握手不可以携带数据,而第三次握手是可以携带数据的。

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

四次挥手

1、第一次挥手:客户端发送一个 FIN 报文,报文中会指定一个序列号。此时客户端处于FIN_WAIT1状态。(还可发送和接受),通俗的说就是:

客户端:服务器大哥,我这请求的任务都完成啦,后面就没了(挥挥手并甩出一个 FIN)

2、第二次挥手:服务端收到 FIN 之后,会发送 ACK 报文,且把客户端的序列号值 + 1 作为 ACK 报文的序列号值,表明已经收到客户端的报文了,此时服务端处于 CLOSE_WAIT状态。 (还可发送和接受),通俗的说就是:

服务端:好的老弟,我明白了(比一个OK手势[ACK]),等我把你之前的请求的数据处理完,咱就断开连接(等我把之前你发的处理完[CLOSE_WAIT])

3、第三次挥手:如果服务端也想断开连接了,和客户端的第一次挥手一样,发给 FIN 报文,且指定一个序列号。此时服务端处于 LAST_ACK 的状态。通俗的说就是:

服务端:行了老弟,我这也把你之前所有的请求都处理完成啦,后面没了(甩一个FIN)。你把我发给你的东西接收完,最后和我确认一下,就自己关闭吧

4、第四次挥手:客户端收到 FIN 之后,一样发送一个 ACK 报文作为应答,且把服务端的序列号值 + 1 作为自己 ACK 报文的序列号值,此时客户端处于 TIME_WAIT 状态。需要等待2倍的MSL时间(Maximum Segment Lifetime,最大报文生存时间)后,客户端会释放TCP连接并关闭套接字。通俗的说就是:

客户端:好的大哥(ACK),等我确保最后你发的这些报文我都收到了(处于TIME_WAIT状态),我就自动关闭了

TIME_WAIT状态的持续时间通常为2倍的MSL时间,这是因为在网络中,数据包可能会丢失或延迟,因此需要等待足够长的时间以确保所有数据包都已经传输完成。

5、服务端收到 ACK 报文之后,就会关闭连接,处于 CLOSED 状态。

关于四次挥手衍生出的问题:

这里特别需要主要的就是TIME_WAIT这个状态了,这个是面试的高频考点,就是要理解,为什么客户端发送 ACK 之后不直接关闭,而是要等一阵子才关闭。这其中的原因就是,要确保服务器是否已经收到了我们的 ACK 报文,如果没有收到的话,服务器会重新发 FIN 报文给客户端,客户端再次收到 ACK 报文之后,就知道之前的 ACK 报文丢失了,然后再次发送 ACK 报文。

至于 TIME_WAIT 持续的时间至少是一个报文的来回时间。一般会设置一个计时,如果过了这个计时没有再次收到 FIN 报文,则代表对方成功就是 ACK 报文,此时处于 CLOSED 状态。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注