You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 lines
11 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 02 | TCP协议如何保证页面文件能被完整送达浏览器
在衡量Web页面性能的时候有一个重要的指标叫“**FPFirst Paint**”,是**指从页面加载到首次开始绘制的时长**。这个指标直接影响了用户的跳出率更快的页面响应意味着更多的PV、更高的参与度以及更高的转化率。那什么影响FP指标呢其中一个重要的因素是**网络加载速度**。
要想优化Web页面的加载速度你需要对网络有充分的了解。而理解网络的关键是要对网络协议有深刻的认识不管你是使用HTTP还是使用WebSocket它们都是基于TCP/IP的如果你对这些原理有足够了解也就清楚如何去优化Web性能或者能更轻松地定位Web问题了。此外TCP/IP的设计思想还有助于拓宽你的知识边界从而在整体上提升你对项目的理解和解决问题的能力。
因此,在这篇文章中,我会给你**重点介绍在Web世界中的TCP/IP是如何工作的**。当然协议并不是本专栏的重点这篇文章我会从我的角度结合HTTP来分析网络请求的核心路径如果你想对网络协议有更深入的理解那我推荐你学习刘超老师的《趣谈网络协议》专栏以及陶辉老师的《Web协议详解与抓包实战》视频课程。
好,接下来我们回到正题,开始今天的内容。在网络中,一个文件通常会被拆分为很多数据包来进行传输,而数据包在传输过程中又有很大概率丢失或者出错。**那么如何保证页面文件能被完整地送达浏览器呢?**
这篇文章将站在数据包的视角,给出问题答案。
## 一个数据包的“旅程”
下面我将分别从“数据包如何送达主机”“主机如何将数据包转交给应用”和“数据是如何被完整地送达应用程序”这三个角度来为你讲述数据的传输过程。
**互联网,实际上是一套理念和协议组成的体系架构**。其中,协议是一套众所周知的规则和标准,如果各方都同意使用,那么它们之间的通信将变得毫无障碍。
互联网中的数据是通过数据包来传输的。如果发送的数据很大,那么该数据就会被拆分为很多小数据包来传输。比如你现在听的音频数据,是拆分成一个个小的数据包来传输的,并不是一个大的文件一次传输过来的。
### 1\. IP把数据包送达目的主机
数据包要在互联网上进行传输,就要符合**网际协议**Internet Protocol简称**IP**)标准。互联网上不同的在线设备都有唯一的地址,地址只是一个数字,这和大部分家庭收件地址类似,你只需要知道一个家庭的具体地址,就可以往这个地址发送包裹,这样物流系统就能把物品送到目的地。
**计算机的地址就称为IP地址访问任何网站实际上只是你的计算机向另外一台计算机请求信息。**
如果要想把一个数据包从主机A发送给主机B那么在传输之前数据包上会被附加上主机B的IP地址信息这样在传输过程中才能正确寻址。额外地数据包上还会附加上主机A本身的IP地址有了这些信息主机B才可以回复信息给主机A。这些附加的信息会被装进一个叫IP头的数据结构里。IP头是IP数据包开头的信息包含IP版本、源IP地址、目标IP地址、生存时间等信息。如果你要详细了解IP头信息可以参考[该链接](https://zh.wikipedia.org/wiki/%E4%BC%A0%E8%BE%93%E6%8E%A7%E5%88%B6%E5%8D%8F%E8%AE%AE)。
为了方便理解,我先把网络简单分为三层结构,如下图:
![](https://static001.geekbang.org/resource/image/00/4d/00d9bcad0bda1fdb43ead428e89ae74d.png)
简化的IP网络三层传输模型
下面我们一起来看下一个数据包从主机A到主机B的旅程
* 上层将含有“极客时间”的数据包交给网络层;
* 网络层再将IP头附加到数据包上组成新的 **IP数据包**,并交给底层;
* 底层通过物理网络将数据包传输给主机B
* 数据包被传输到主机B的网络层在这里主机B拆开数据包的IP头信息并将拆开来的数据部分交给上层
* 最终含有“极客时间”信息的数据包就到达了主机B的上层了。
### 2\. UDP把数据包送达应用程序
IP是非常底层的协议只负责把数据包传送到对方电脑但是对方电脑并不知道把数据包交给哪个程序是交给浏览器还是交给王者荣耀因此需要基于IP之上开发能和应用打交道的协议最常见的是“**用户数据包协议**User Datagram Protocol简称**UDP**。
UDP中一个最重要的信息是**端口号**端口号其实就是一个数字每个想访问网络的程序都需要绑定一个端口号。通过端口号UDP就能把指定的数据包发送给指定的程序了所以**IP通过IP地址信息把数据包发送给指定的电脑而UDP通过端口号把数据包分发给正确的程序**。和IP头一样端口号会被装进UDP头里面UDP头再和原始数据包合并组成新的UDP数据包。UDP头中除了目的端口还有源端口号等信息。
为了支持UDP协议我把前面的三层结构扩充为四层结构在网络层和上层之间增加了传输层如下图所示
![](https://static001.geekbang.org/resource/image/3e/ea/3edb673a43f23d84253c52124ce447ea.png)
简化的UDP网络四层传输模型
下面我们一起来看下一个数据包从主机A旅行到主机B的路线
* 上层将含有“极客时间”的数据包交给传输层;
* 传输层会在数据包前面附加上**UDP头**组成新的UDP数据包再将新的UDP数据包交给网络层
* 网络层再将IP头附加到数据包上组成新的IP数据包并交给底层
* 数据包被传输到主机B的网络层在这里主机B拆开IP头信息并将拆开来的数据部分交给传输层
* 在传输层数据包中的UDP头会被拆开**并根据UDP中所提供的端口号把数据部分交给上层的应用程序**
* 最终含有“极客时间”信息的数据包就旅行到了主机B上层应用程序这里。
在使用UDP发送数据时有各种因素会导致数据包出错虽然UDP可以校验数据是否正确但是对于错误的数据包UDP并不提供重发机制只是丢弃当前的包而且UDP在发送之后也无法知道是否能达到目的地。
虽说**UDP不能保证数据可靠性但是传输速度却非常快**所以UDP会应用在一些关注速度、但不那么严格要求数据完整性的领域如在线视频、互动游戏等。
### 3\. TCP把数据完整地送达应用程序
对于浏览器请求或者邮件这类要求数据传输可靠性reliability的应用如果使用UDP来传输会存在**两个问题**
* 数据包在传输过程中容易丢失;
* 大文件会被拆分成很多小的数据包来传输这些小的数据包会经过不同的路由并在不同的时间到达接收端而UDP协议并不知道如何组装这些数据包从而把这些数据包还原成完整的文件。
基于这两个问题我们引入TCP了。**TCPTransmission Control Protocol传输控制协议是一种面向连接的、可靠的、基于字节流的传输层通信协议**。相对于UDPTCP有下面两个特点:
* 对于数据包丢失的情况TCP提供重传机制
* TCP引入了数据包排序机制用来保证把乱序的数据包组合成一个完整的文件。
和UDP头一样TCP头除了包含了目标端口和本机端口号外还提供了用于排序的序列号以便接收端通过序号来重排数据包。
下面看看TCP下的单个数据包的传输流程
![](https://static001.geekbang.org/resource/image/94/32/943ac29f7d5b45a8861b0cde5da99032.png)
简化的TCP网络四层传输模型
通过上图你应该可以了解一个数据包是如何通过TCP来传输的。TCP单个数据包的传输流程和UDP流程差不多不同的地方在于通过TCP头的信息保证了一块大的数据传输的完整性。
下面我们再看下**完整的TCP连接过程**通过这个过程你可以明白TCP是如何保证重传机制和数据包的排序功能的。
从下图可以看出一个完整的TCP连接的生命周期包括了“**建立连接**”“**传输数据**”和“**断开连接**”三个阶段。
![](https://static001.geekbang.org/resource/image/44/44/440ee50de56edc27c6b3c992b3a25844.png)
一个TCP连接的生命周期
* **首先,建立连接阶段**。这个阶段是通过“三次握手”来建立客户端和服务器之间的连接。TCP 提供面向连接的通信传输。**面向连接**是指在数据通信开始之前先做好两端之间的准备工作。所谓**三次握手**是指在建立一个TCP连接时客户端和服务器总共要发送三个数据包以确认连接的建立。
* **其次,传输数据阶段**。在该阶段,**接收端需要对每个数据包进行确认操作**也就是接收端在接收到数据包之后需要发送确认数据包给发送端。所以当发送端发送了一个数据包之后在规定时间内没有接收到接收端反馈的确认消息则判断为数据包丢失并触发发送端的重发机制。同样一个大的文件在传输过程中会被拆分成很多小的数据包这些数据包到达接收端后接收端会按照TCP头中的序号为其排序从而保证组成完整的数据。
* **最后,断开连接阶段**。数据传输完毕之后,就要终止连接了,涉及到最后一个阶段“四次挥手”来保证双方都能断开连接。
到这里你应该就明白了TCP为了保证数据传输的可靠性牺牲了数据包的传输速度因为“三次握手”和“数据包校验机制”等把传输过程中的数据包的数量提高了一倍。
## 总结
好了,这一节就到这里,下面我来做一个简单的总结。
* 互联网中的数据是通过数据包来传输的,数据包在传输过程中容易丢失或出错。
* IP负责把数据包送达目的主机。
* UDP负责把数据包送达具体应用。
* 而TCP保证了数据完整地传输它的连接可分为三个阶段建立连接、传输数据和断开连接。
其实了解TCP协议是为了全方位了解HTTP包括其实际功能和局限性之后才会更加深刻地理解为什么要推出HTTP/2以及为什么要推出QUIC协议也就是未来的HTTP/3。这是一个由浅入深、循序渐进的过程我希望你能稳扎稳打学好这每一步、每一个协议后面“水到自然渠成”。
## 思考时间
今天这篇文章我没有讲HTTP协议但是相信你应该听说过HTTP协议是基于TCP协议的那么今天我留给你的问题是你怎么理解HTTP和TCP的关系
欢迎在留言区与我分享你的想法,也欢迎你在留言区记录你的思考过程。感谢阅读,如果你觉得这篇文章对你有帮助的话,也欢迎把它分享给更多的朋友。