求star

开源不易,喜欢请点个star吧

Ocean Han
1881 字
9 分钟
TCP三次握手和四次挥手的过程

1. 涉及到的几个重要字段:strawberry:#

:::tip

  • seq:(sequence number) 序号

    • 在所有的字节排列中,申请从哪一个字节开始发送,这个序号就一般表示当前已经发送到哪个序号,服务器同意后将会从下一个序号开始发送,第一次握手只有请求序号没有确认号
  • ack:(acknowledgement number) 确认号

  • 标志位:

    • SYN:(SYNchronization) 同步
      • SYN=1表示要建立连接,连接成功后该位置会再次被置为0
    • ACK(ACKnowlegmen) 确认
    • FIN:(FINish) 终止

:::

2. 三次握手:handshake:#

  • 一开始,客户端和服务端都都处于CLOSED状态。客户端主动打开连接,服务端被动打开连接。结束CLOSED状态,开始监听,进入LISTEN状态

三次握手

2.1 一次握手:handshake:#

:::tip

客户端随机初始化序号(client_isn),并将此序号置于TCP首部的seq[序号]字段中,同时把SYN标志位设置为1,表示SYN报文。随后把第一个SYN报文发送给服务端,表示向服务端发起连接(该报文不包含应用层数据),之后客户端处于SYN-SENT状态

:::

2.2 二次握手:handshake:#

TIP

服务端收到客户端的SYN报文后,首先也随机初始化自己的序号(server_isn),将此序号填入TCP首部的seq[序号]字段中,其次把TCP首部的ack[确认应答号]字段填入client_isn + 1,接着把SYNACK标志位设置为1。最后把该报文发送给客户端(该报文也不包含应用层数据),之后服务端处于SYN-RCVD状态

2.3 三次握手:handshake:#

TIP

客户端收到服务端报文之后,还要向服务端回应最后一个应答报文,首先该应答报文TCP首部ACK标志位设置为1,其次ack[确认应答号]字段填入client_isn + 1,最后把该报文发给服务端(这次报文可以携带客户端到服务端的数据),之后服务端处于ESTABLISHED状态

三次握手

3. 四次挥手:wave:#

四次挥手

TIP

TCP断开连接是通过四次挥手的方式

客户端和服务端双方都可以主动断开连接,断开连接后主机中的[资源]将被释放

上图是客户端主动关闭连接

3. 1 一次挥手:wave:#

TIP

客户端打算关闭连接,此时会发送一个TCP首部FIN标志位设置为1的报文,即FIN报文,之后客户端进入FIN_WAIT_1状态

3.2 二次挥手:wave:#

TIP

服务端收到该报文之后,向客户端发送ACK应答报文,然后服务端进入CLOSED_WAIT状态

3.3 三次挥手:wave:#

TIP

客户端收到服务端的ACK应答报文,然后进入FIN_WAIT_2状态。等待服务器处理完数据之后,也向客户端发送FIN报文,之后服务端进入LAST_ACK状态

3.4 四次挥手:wave:#

TIP
  • 客户端收到服务端的FIN报文之后,返回一个ACK应答报文,之后进入TIME_WAIT状态
  • 服务器收到ACK应答报文之后,就进入了CLOSED状态,至此服务端已经完成连接的关闭
  • 客户端在经过2MSL后,自动进入CLOSED状态,至此客户端也完成连接的关闭

4. 提出一些问题#

4.1 为什么要握手三次?两次行不行?#

TIP
  1. 为了防止服务端开启一些无用的连接,从而增加服务器的开销(为了确认双方的接收和发送能力是否正常)
  2. 为了防止已经失效的连接请求报文段突然又传送到了服务端,从而产生错误;为了解决网络中存在延迟的重复分组;总之为了避免资源浪费

解释:

WARNING

​ 由于网络传输是有延时的(要通过网络光纤和各种中间代理服务器),在传输的过程中:

​ 比如客户端发起了 SYN=1的第一次握手,如果服务器端就直接创建了这个连接并返回包含 SYNACKSeq等内容的数据包给客户端,这个数据包因为网络传输的原因丢失了,丢失之后客户端就一直没有接收到服务器返回的数据包

如果没有第三次握手告诉服务器端客户端收的到服务器端传输的数据的话,服务器端是不知道客户端有没有接收到服务器端返回的信息的。服务端就认为这个连接是可用的,端口就一直开着,等到客户端因超时重新发出请求时,服务器就会重新开启一个端口连接

连接失败的情况

还有一种情况是已经失效的客户端发出的请求信息,由于某种原因传输到了服务器端,服务器端以为是客户端发出的有效请求,接收后产生错误。

报文延迟

WARNING

通过第三次握手的数据告诉服务端,客户端有没有收到服务器“第二次握手”时传过去的数据,以及这个连接的序号是不是有效的。若发送的这个数据是“收到且没有问题”的信息,接收后服务器就正常建立 TCP 连接,否则建立 TCP 连接失败,服务器关闭连接端口。由此减少服务器开销和接收到失效请求发生的错误。

4.2 为什么要挥手四次?#

TIP
  1. 关闭连接时,客户端向服务端发送FIN时,仅仅表示客户端不再发送数据了,但是还能接收数据

  2. 服务器收到客户端的FIN报文时,先返回一个ACK应答报文,而服务端可能还有数据需要处理和发送,等到服务端不再发送数据时,才发送FIN报文给客户端来表示同意现在关闭连接

因为服务端通常需要等待数据的发送和处理,所以服务端的ACKFIN一般都会分开发送,从而导致比三次握手多了一次

4.3 为什么客户端在TIME-WAIT阶段要等2MSL#

TIP

答:原因是为了确认服务端是否收到客户端发出的ACK确认报文

注: MSL(Maximum Segment Lifetime):指的是一段TCP报文在传输过程中的最大生命周期。

:::tip 过程解释

  1. 因为客户端在发送完ACK报文之后,并不能确定服务端是否能够收到该段报文,所以客户端会设置一个时长为2MSL的计时器(2MSL即是服务端发出为FIN报文和客户端发出ACK确认报文所能保持有效的最大时长)
  2. 服务端在1MSL内没有收到客户端发出的ACK确认报文,就会再次向客户端发出FIN报文:
    1. 如果客户端在2MSL内,再次收到了来自服务端的FIN报文,说明服务端由于某些原因没有接收到客户端发出的ACK确认报文
  3. 于是,客户端再次向服务端发出ACK确认报文,并重置计时器(重新开始2MSL的计时)
    1. 如果客户端在2MSL内没有再次收到来自服务端的FIN报文,说明服务端正常接收了ACK确认报文,客户端可以进入CLOSED阶段,完成四次挥手

:::

TCP三次握手和四次挥手的过程
https://blog.oceanh.top/posts/network/tcp三次握手和四次挥手的过程/
作者
Ocean Han
发布于
2022-10-25
许可协议
CC BY-NC-SA 4.0
最后修改时间
2024-08-10 10:08:49