TCP:如何保证页面文件能被完整的送达浏览器?

332 阅读4分钟

IP:把数据包送达目的主机

下面我们一起来看下一个数据包从主机 A 到主机 B 的旅程:

  1. 上层将含有“极客时间”的数据包交给网络层;
  2. 网络层再将 IP 头附加到数据包上,组成新的 IP 数据包,并交给底层;
  3. 底层通过物理网络将数据包传输给主机 B;
  4. 数据包被传输到主机 B 的网络层,在这里主机 B 拆开数据包的 IP 头信息,并将拆开来的数据部分交给上层
  5. 最终,含有“极客时间”信息的数据包就到达了主机 B 的上层了。

UDP:把数据包送达应用程序

在使用 UDP 发送数据时,有各种因素会导致数据包出错,虽然 UDP 可以校验数据是否正确,但是对于错误的数据包,UDP 并不提供重发机制,只是丢弃当前的包,而且 UDP 在发送之后也无法知道是否能达到目的地。

虽说 UDP 不能保证数据可靠性,但是传输速度却非常快,所以 UDP 会应用在一些关注速度、但不那么严格要求数据完整性的领域,如在线视频、互动游戏等。

TCP:把数据完整的送达到应用程序

对于浏览器请求,或者邮件这类要求数据传输可靠性(reliability)的应用,如果使用 UDP 来传输会存在两个问题:

  1. 数据包在传输过程中容易丢失;
  2. 大文件会被拆分成很多小的数据包来传输,这些小的数据包会经过不同的路由,并在不同的时间到达接收端,而 UDP 协议并不知道如何组装这些数据包,从而把这些数据包还原成完整的文件。

基于这两个问题,我们引入 TCP 了。TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。相对于 UDP,TCP 有下面两个特点:

  1. 对于数据包丢失的情况,TCP 提供重传机制;
  2. TCP 引入了数据包排序机制,用来保证把乱序的数据包组合成一个完整的文件。

首先,建立连接阶段。这个阶段是通过“三次握手”来建立客户端和服务器之间的连接。TCP 提供面向连接的通信传输。面向连接是指在数据通信开始之前先做好两端之间的准备工作。所谓三次握手,是指在建立一个 TCP 连接时,客户端和服务器总共要发送三个数据包以确认连接的建立。

其次,传输数据阶段。在该阶段,接收端需要对每个数据包进行确认操作,也就是接收端在接收到数据包之后,需要发送确认数据包给发送端。所以当发送端发送了一个数据包之后,在规定时间内没有接收到接收端反馈的确认消息,则判断为数据包丢失,并触发发送端的重发机制。同样,一个大的文件在传输过程中会被拆分成很多小的数据包,这些数据包到达接收端后,接收端会按照 TCP 头中的序号为其排序,从而保证组成完整的数据。

最后,断开连接阶段。数据传输完毕之后,就要终止连接了,涉及到最后一个阶段“四次挥手”来保证双方都能断开连接。

三次握手

TCP共有6个标志位,分别是:

  1. SYN(synchronous),建立联机。
  2. ACK(acknowledgement),确认。
  3. PSH(push),传输。
  4. FIN(finish),结束。
  5. RST(reset),重置。
  6. URG(urgent),紧急。

第一次握手,客户端向服务器发送SYN包(SYN=j)

第二次握手,服务器接收到客户端发送的SYN包,确认客户端的SYN包(ACK=j+1),并自己也发送一个SYN包(SYN=k)给客户端。第二次握手中,将确认客户端的连接请求和发送服务器的连接请求合并为一次。

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

四次挥手

第一次挥手,客户端向服务器发送FIN包(FIN=h),用来关闭客户端到服务器的数据传输。

第二次挥手,服务器接收到客户端发送的FIN包,确认客户端的FIN包(ACK=h+1),发送给客户端。

第三次挥手,服务器关闭客户端的连接,发送一个FIN包(FIN=i)给客户端。

第四次挥手,客户端接收到服务器发送的FIN包,确认FIN包(ACK=i+1),发送给服务器。