相关:谈传输层协议:TCP 与 UDP

TCP 收发数据流程

  1. 建立连接(三次握手)
  2. 收发数据
  3. 断开连接(四次挥手)

TCP 如何收发数据

分段发送

可靠传输

在 TCP 协议中,任何时候、任何一方都可以主动发送数据给另一方

为了解决数据报丢失、数据报错乱等问题,TCP 协议要求:接收方收到数据报后,必须对数据报进行确认:

  • seq:表示这次数据报的序号
  • ACK:表示这次数据报是一个确认数据报
  • ack:表示期望下一次接收的数据报序号

发送方如果长时间没有收到确认数据报(ACK=1),则会判定丢失或者是错误,会进行重发

连接的建立(三次握手)

TCP 协议要实现数据的收发,必须要先建立连接,通过三次握手建立可靠的点对点连接

连接的本质其实就是双方各自开辟的一块儿内存空间,空间中主要是数据缓冲区和一些变量。

连接建立的过程需要经过三次数据报传输,因此称之为三次握手:

通俗解释

开始

客户端:我说话能听见吗?

服务器:能听见,我说话能听见吗?

客户端:能听见

结束

首先服务器进入监听状态,然后即可处理连接

第一次握手:建立连接时,客户端发送 SYN 包到服务器,并进入 SYN_SENT(同步已发送)状态,等待服务器确认。在发送的包中包含 SYN=1 表示是一个同步(连接)包和一个初始序列号 seq。此次握手的含义是客户端希望与服务器建立连接。

第二次握手:服务器收到 SYN 包,然后回应给客户端一个 SYN+ACK 包,此时服务器进入 SYN_RCVD(同步已接收)状态。此次握手的含义是服务端回应客户端,表示已收到并同意客户端的连接请求。

第三次握手:客户端收到服务器的 SYN+ACK 包后,向服务器再次发送 ACK 包,并进入 ESTAB_LISHED(连接已建立)状态。

最后,服务端收到客户端的 ACK 包后,也进入 ESTAB_LISHED(连接已建立)状态,至此,连接建立完成,可以进行后续的数据传输了。

连接的销毁(四次挥手)

通俗解释

开始

客户端:我说完了,挂了?

服务器:我明白你说完了,但别忙挂,我还有话要说。

服务器继续说…

服务器:我也说完了,挂了?

客户端:好的!

结束

当需要关闭连接时,需要进行四次挥手才能关闭。一般是客户端主动关闭连接,当然也可以是服务器主动关闭连接,这里以客户端主动关闭连接为例

第一次挥手:客户端向服务器发送 FIN 包,表示客户端要主动关闭连接,然后进入 FIN_WAIT_1(完成等待 1)状态,等待服务器返回 ACK 包。此后客户端不能再向服务器发送数据,但能读取数据。

第二次挥手:服务器收到 FIN 包后向客户端发送 ACK 包,然后进入 CLOSE_WAIT(等待关闭)状态,此后服务器不能再读取数据,但可以继续向客户端发送数据。

客户端收到服务器返回的 ACK 包后进入 FIN_WAIT_2(完成等待 2)状态,等待服务器继续发送完所有数据。

第三次挥手:服务器完成数据的发送后,将 FIN 包发送给客户端,然后进入 LAST_ACK(最后确认)状态,等待客户端返回 ACK 包,此后服务器既不能读取数据,也不能发送数据。

第四次挥手:客户端收到 FIN 包后向服务器发送 ACK 包,然后进入 TIME_WAIT(时间等待)状态,接着等待足够长的时间(2MSL)以确保服务器接收到 ACK 包,最后回到 CLOSED(关闭)状态,释放网络资源。

服务器收到客户端返回的 ACK 包后便回到 CLOSED(关闭)状态,释放网络资源。如果没有收到就会重发第三次挥手的 FIN+ACK 包,这也是客户端要等待 2MSL 的原因

HTTP 和 TCP 的关系

HTTP 协议是对内容格式的规定(应用层),它使用了 TCP 协议完成消息的可靠传输(传输层)

HTTP 协议规定:

  1. 客户端发消息给服务器叫做请求,服务器发消息给客户端叫做响应
  2. 使用 HTTP 协议的服务器不会主动发消息给客户端(尽管 TCP 可以),只对请求进行响应
  3. 每一个 HTTP 请求-响应,都要先建立 TCP 连接(三次握手),然后完成请求-响应后,再销毁连接(四次挥手)。这就导致每次请求-响应都是相互独立的,无法保持状态。

HTTP 协议的更新:

  1. HTTP/2 支持服务器推送
  2. HTTP/1.1 默认使用长连接,不必每个请求-响应结束后就销毁连接
  3. 由于 TCP 队头阻塞的原因,HTTP/3 传输层采用 UDP,在应用层保证传输可靠