3.2.2 传输过程
互联网网络传输基于TCP协议传输,TCP三次握手过程,如图3-1所示。
图3-1 TCP三次握手交互图
注意,第1次SYN是请求建立连接,并在其序列号的字段进行序列号的初始值设定。建立连接,设置为1。ACK是确认号是否有效,一般置为1。
第一次握手:建立连接时,客户端发送SYN包(SYN=1)到服务器,并进入SYN_SENT状态,等待服务器确认。SYN是同步序列编号(Synchronize Sequence Number)。
第二次握手:服务器收到SYN包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(SYN=1),即SYN+ACK包,此时服务器进入SYN_RECV状态。
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
网络传输完毕后,客户端进程发出连接释放报文,并且停止发送数据。此时会经过TCP四次挥手,其过程如图3-2所示。
图3-2 TCP四次挥手交互图
注意,第1次FIN是希望断开连接,一般置FIN为1。挥手处理过程如下。
1)客户端进程发出连接释放报文,并且停止发送数据,释放数据报文首部,FIN=1,序列号为seq=u,TCP规定FIN报文段不携带数据也要消耗一个序号。
2)服务器接收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自身序列号seq=v,服务端进入CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端没有数据要发送,但是服务器若发送数据,客户端依然要接收。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
3)收到服务器的确认请求后,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接收服务器发送的最后的数据)。
4)服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于处于半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,那么服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
5)客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
6)服务器只要收到了客户端发出的确认信息,就会立即进入CLOSED状态,同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
互联网中Web请求过程如图3-3所示。
图3-3 Web请求过程图
注意,输入URL地址或点击URL链接后,浏览器打开呈现的请求过程具体分为以下步骤。
1)查找DNS,解析出与URL对应的IP地址(公网IP)。
2)初始化网络连接(包括TCP三次握手)。
3)发送HTTP请求。
4)通过网络传输请求到服务器。
5)Web服务器接收请求,经过处理转发到Web应用。
6)Web应用处理请求,如MVC框架,返回内容。
7)通过网络传输应答内容到前端浏览器。
8)浏览器解析从服务器返回的应答内容,并开始渲染和绘制。
9)根据HTML内容来构建DOM(文档对象模型)。
10)加载和解析样式,构建CSSOM(CSS对象模型)。
11)根据DOM和CSSOM来构建渲染树,按照文档顺序从上到下依次进行。
12)根据渲染树的过程,适当把已经构建好的部分绘制到界面上,中间会伴随着重绘和回流,循环操作,直到渲染绘制完成。
13)整个页面加载完成,触发OnLoad事件。
详细流程分析如下。
1)要通过URL将请求发送到服务器,浏览器就要知道这个URL对应的IP是什么,只有知道了IP地址,浏览器才能将请求发送到指定服务器的具体IP和端口。浏览器的DNS解析器负责把URL解析为正确的IP地址,这个解析很花时间,而且在解析过程中,浏览器不能从服务器那里下载任何东西。浏览器和操作系统提供了DNS解析缓存支持。
2)获取IP之后,浏览器会请求与服务器建立连接,TCP经过3次握手后建立连接通道。
3)浏览器真实发送HTTP请求,发送请求报文,包含请求行(包含请求方法、URI、HTTP版本信息;请求首部字段)、请求内容实体、空行。
- 通用首部字段(请求报文与响应报文都会使用的首部字段)如下。
-
- Date:创建报文时间。
- Connection:连接的管理。
- Cache-Control:缓存的控制。
- Transfer-Encoding:报文主体的传输编码方式。
- 请求首部字段(请求报文会使用的首部字段)如下。
-
- Host:请求资源所在服务器。
- Accept:可处理的媒体类型。
- Accept-Charset:可接收的字符集。
- Accept-Encoding:可接受的内容编码。
- Accept-Language:可接受的自然语言。
4)网络开始传输请求到服务器,这个会包含很多时间,如网络阻塞时间、网络延迟时间、真正传输内容时间等。
5)Web服务器收到请求,会根据URL上下文转交给相应Web应用进行处理。
6)Web应用会进行很多处理,如filter、aop前置处理、IOC处理、创建对象,处理后会生成Response对象。熟悉Spring的读者对此过程会更清晰。
7)返回HTTP响应报文,包含状态行(包含HTTP版本、状态码、状态码的原因短语)、响应首部字段、响应内容实体、空行。
- 响应首部字段(响应报文会使用的首部字段):
-
- Accept-Ranges:可接收的字节范围。
- Location:令客户端重新定向到的URI。
- Server:HTTP服务器的安装信息。
- 实体首部字段(请求报文与响应报文的实体部分使用的首部字段):
-
- Allow:资源可支持的HTTP方法。
- Content-Type:实体主类的类型。
- Content-Encoding:实体主体适用的编码方式。
- Content-Language:实体主体的自然语言。
- Content-Length:实体主体的的字节数。
- Content-Range:实体主体的位置范围,一般在发出部分请求时使用。
8)通过网络将应答内容传送回前端浏览器,先返回HTML代码,不包含图片、外部脚本、CSS等。
9)在浏览器解析页面进行渲染和绘制,具体过程如下:
a)装载和解析HTML文档,构建DOM,如果在解析过程中发现需要其他资源,如图片,浏览器会发出获取资源的请求;
b)装载和解析CSS,构建cssom;
c)根据DOM和cssom构建渲染树;
d)对渲染树节点进行布局处理,确认其屏幕位置;
e)将渲染好的节点绘制到界面上,渲染引擎不会等到所有HTML都解析完后才创建布局渲染树,而是在处理解析渲染树的同时向后端请求资源。