TCP的三次握手和四次挥手

149 阅读4分钟

TCP三次握手是浏览器和服务器建立连接的方式,目的是为了使二者能够建立连接,便于后续的数据交互传输。

TCP是什么?

TCP(Transmission Control Protocol 传输控制协议)是一种面向连接(连接导向)的、可靠的、 基于IP的传输层协议。

三次握手是什么?

所谓的“三次握手”:为了对每次发送的数据量进行跟踪与协商,确保数据段的发送和接收同步,根据所接收到的数据量而确认数据发送、接收完毕后何时撤消联系,并建立虚连接。

三次握手都发生了什么?

第一次握手:

  • 建立连接时,客户端发送syn包(seq=j)到服务器,并进入SYN_SENT状态,等待服务器确认。

第二次握手:

  • 服务器收到syn包,必须确认客户端的SYN(ack=j+1),同时自己也发送一个SYN包(seq=k),即SYN+ACK包,此时服务器进入SYN_RECV状态。

第三次握手:

  • 客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

下面用白话文进行描述

  • 客户端发送请求给服务端:我要开始跟你产生连接;
  • 服务端接收到后向客户端发送确定的响应,并发送状态码告诉客户端可以连接了;【其实这里最初是两次响应,但是由于此时是没有数据进行传输的,所以为了加快进度,这里进行了合并】
  • 客户端接收到后发送请求给服务端确定链接。

如图所示:

连接成功后,开始传送数据。

为什么需要三次握手?

三次握手可以阻止重复连接、可以同步双方的初始序列号、可以避免重复建立连接。


四次挥手是什么?

对于一个已经建立的连接,TCP使用改进的四次挥手来释放连接(使用一个带有FIN附加标记的报文段)。

四次挥手都发生了什么?

第一次挥手:

  • 客户端发送一个FIN,用来关闭客户端到服务器的数据传送,客户端进入FIN_WAIT_1状态,等待服务器的确认。

第二次挥手:

  • 服务器收到连接释放报文段(FIN报文)后,就向客户端发送ACK应答报文,以客户端的FIN报文的序列号 seq+1 作为ACK应答报文段的确认序列号ack = seq+1 = u + 1。
  • 接着服务器进入CLOSE_WAIT(等待关闭)状态,此时的TCP处于半关闭状态,客户端到服务器的连接释放。
  • 客户端收到来自服务器的ACK应答报文段后,进入FIN_WAIT_2状态。

第三次挥手:

  • 服务器也打算断开连接,向客户端发送连接释放(FIN)报文段,之后服务器进入LASK_ACK(最后确认)状态,等待客户端的确认。
  • 服务器的连接释放(FIN)报文段的FIN=1,ACK=1,序列号seq=m,确认序列号ack=u+1。

第四次挥手:

  • 客户端收到来自服务器的连接释放(FIN)报文段后,会向服务器发送一个ACK应答报文段,以连接释放(FIN)报文段的确认序号 ack 作为ACK应答报文段的序列号 seq,以连接释放(FIN)报文段的序列号 seq+1作为确认序号ack。
  • 之后客户端进入TIME_WAIT(时间等待)状态,服务器收到ACK应答报文段后,服务器就进入CLOSE(关闭)状态,到此服务器的连接已经完成关闭。
  • 客户端处于TIME_WAIT状态时,此时的TCP还未释放掉,需要等待2MSL后,客户端才进入CLOSE状态。

下面用白话文进行描述

  • 客户端告诉服务端,我要关闭链接了【这个时候客户端就不再发送请求到服务端了】;
  • 服务端接收后进行响应,告诉客户端:好的;
  • 服务端发送请求给客户端:我这边数据传输完毕了,可以关闭了;
  • 客户端接收后发送“确定”。

此时链接正式关闭。 这里服务端“告知客户端:好的”和“可以关闭”这两次信息传递并没有合并在一起的原因是:虽然客户端那边请求已结束,但是服务端这边的数据传输可能还未结束,服务端要等在数据传输确定结束后,再去通知客户端关闭。

为什么第四次挥手服务器进入CLOSE状态后,客户端需要等2MSL?

MSL(Maximum Segment LifeTime)是报文最大生成时间,它是任何报文在网络上存在的最长时间,超过这个时间的报文将被丢弃。
2MSL时间是从客户端接收到FIN后发送ACK开始计时的。如果在这个时间段内,服务器没有收到ACK应答报文段,会重发FIN报文段,如果客户端收到了FIN报文段,那么2MSL的时间将会被重置。如果在2MSL时间段内,没有收到任何数据报,客户端则会进入CLOSE状态。