TCP 协议的三次握手和四次挥手 | 计算机基础

TCP 协议的三次握手和四次挥手 | 计算机基础

建链接三次握手

  • 第一次握手
    • 客户端发送连接请求报文段,将 SYN 位置为 1,Sequence Number 为 x;然后,客户端进入 SYN_SEND 状态,等待服务器的确认
  • 第二次握手
    • 服务器收到 SYN 报文段。服务器收到客户端的 SYN 报文段,需要对这个 SYN 报文段进行确认,设置 Acknowledgment Number 为 x+1(Sequence Number+1);同时,自己自己还要发送 SYN 请求信息,将 SYN 位置为 1,Sequence Number 为 y;服务器端将上述所有信息放到一个报文段(即 SYN+ACK 报文段)中,一并发送给客户端,此时服务器进入 SYN_RECV 状态
  • 第三次握手
    • 客户端收到服务器的 SYN+ACK 报文段。然后将 Acknowledgment Number 设置为 y+1,向服务器发送 ACK 报文段,这个报文段发送完毕以后,客户端和服务器端都进入 ESTABLISHED 状态,完成 TCP 三次握手

为什么要进行三次握手

对于建连接的三次握手,主要是要初始化 Sequence Number 的初始值。通信的双方要互相通知对方自己的初始化的 Sequence Number,所以叫 SYN。也就上图中的 x 和 y。这个号要作为以后的数据通信的序号,以保证应用层接收到的数据不会因为网络上的传输问题而乱序(TCP 会用这个序号来拼接数据)。

当客户端向服务器端发送一个连接请求时,由于某种原因长时间驻留在网络节点中,无法达到服务器端,由于 TCP 的超时重传机制,当客户端在特定的时间内没有收到服务器端的确认应答信息,则会重新向服务器端发送连接请求,且该连接请求得到服务器端的响应并正常建立连接,进而传输数据,当数据传输完毕,并释放了此次 TCP 连接。

若此时第一次发送的连接请求报文段延迟了一段时间后,到达了服务器端,本来这是一个早已失效的报文段,但是服务器端收到该连接请求后误以为客户端又发出了一次新的连接请求,于是服务器端向客户端发出确认应答报文段,并同意建立连接。

如果没有采用三次握手建立连接,由于服务器端发送了确认应答信息,则表示新的连接已成功建立,但是客户端此时并没有向服务器端发出任何连接请求,因此客户端忽略服务器端的确认应答报文,更不会向服务器端传输数据。而服务器端却认为新的连接已经建立了,并在一直等待客户端发送数据,这样服务器端一直处于等待接收数据,直到超出计数器的设定值,则认为服务器端出现异常,并且关闭这个连接。在这个等待的过程中,浪费服务器的资源。如果采用三次握手,客户端就不会向服务器发出确认应答消息,服务器端由于没有收到客户端的确认应答信息,从而判定客户端并没有请求建立连接,从而不建立该连接。

断链接四次挥手

  • 第一次挥手
    • 主机 1(可以使客户端,也可以是服务器端),设置 Sequence Number 和 Acknowledgment Number,向主机 2 发送一个 FIN 报文段;此时,主机 1 进入 FIN_WAIT_1 状态;这表示主机 1 没有数据要发送给主机 2 了
  • 第二次挥手
    • 主机 2 收到了主机 1 发送的 FIN 报文段,向主机 1 回一个 ACK 报文段,Acknowledgment Number 为 Sequence Number 加 1;主机 1 进入 FIN_WAIT_2 状态;主机 2 告诉主机 1,我“同意”你的关闭请求
  • 第三次挥手
    • 主机 2 向主机 1 发送 FIN 报文段,请求关闭连接,同时主机 2 进入 LAST_ACK 状态
  • 第四次挥手
    • 主机 1 收到主机 2 发送的 FIN 报文段,向主机 2 发送 ACK 报文段,然后主机 1 进入 TIME_WAIT 状态;主机 2 收到主机 1 的 ACK 报文段以后,就关闭连接;此时,主机 1 等待 2MSL 后依然没有收到回复,则证明 Server 端已正常关闭,那好,主机 1 也可以关闭连接了

为什么要进行四次挥手

对于四次挥手,其实仔细看则是两次,因为 TCP 是全双工的,所以发送方和接收方都需要 FIN 和 ACK。只不过有一方是被动的,所以看上去就成了所谓的四次挥手。如果两边同时断连接,那就会就进入到 CLOSING 状态,然后到达 TIME WAIT 状态。

参考

《后台开发:核心技术与应用实践》