TCP/HTTP协议

HTTP 发展史

http1.0中,每请求一个http请求都需要建立一次tcp连接,而tcp的三次握手四次挥手相对比较耗时,且会带来1.5+2=3.5个RTT

因此在http1.1中,引入了长链接的概念,当在请求头部设置了Connection:keep-alive时,表示一个http请求完成不会断开连接,而是接着发送下一下http连接,然而http请求是按照顺序请求的,如果一个http延迟了,队列后面的所有请求都会延迟,这就是队头阻塞问题。http1.1同时规定一个域名同时可以有6个tcp连接,这6个tcp连接中的http请求是可以并行的,但是每个tcp是一个慢启动的过程,tcp发送数据的过程类似于地铁启动,比较耗时(慢启动是tcp为了减少网络拥塞的一种策略),并且6个tcp连接直接会对带宽进行竞争,导致tcp会动态的减慢接收数据的速度,而不会管资源是否是关键资源。并且http1.1还支持了虚拟主机(Host字段)和客户端Cookie,虚拟主机有不同的域名,但只想同一个Ip地址,这样浏览器和同一个服务器就不止可以有6个tcp连接了。

因此在http2.0中,引入了多路复用,只需要一个tcp连接,多路复用解决了队头阻塞和多个tcp的慢启动以及竞争问题。多路复用的实现是:在网络层级中增加了二进制分帧层,不同的请求包会被加上编号,同时可以发送不同请求的包,客户端和服务端会根据编号来拼凑出一个完整的包。并且http2.0中支持给请求设置优先级(这样服务器就会优先处理这些请求并返回)、服务器推送(服务器在接收到html请求后,会附带将html中引用的js灯发送给浏览器)和头部压缩功能。但是http2.0依然是基于tcp协议的,tcp依然存在数据包级别的队头阻塞问题,即在数据传输的过程中如果丢包了,那么整个tcp连接会处于一个暂停状态,等待数据包的重传,这是tcp只所以是可靠协议的原因。

HTTP 方法
  • head:请求资源的头部信息,可以在下载一个大文件前先获取其大小在决定是否要下载以节约带宽。
  • patch:用于对资源进行部分修改。
  • get
  • post
  • put
  • delete
如何保证页面文件能被完整地送达浏览器呢?
  • 互联网中的数据是通过数据包来传输的,数据包在传输过程中容易丢失或出错。
  • IP 负责把数据包送达目的主机。
  • UDP 负责把数据包送达具体应用。
  • TCP 保证了数据完整地传输,它的连接可分为三个阶段:建立连接、传输数据和断开连接。

HTTP是基于TCP的协议,因此建立HTTP连接的第一步是建立TCP连接,而建立TCP连接的第一步是获取ip和port,所以第一步就是dns解析,根据域名拿到ip和port。然而,同一个域名下,最多只可以建立6个TCP连接(HTTP1.1,而http2同个域名只能维持一个长连接。)。所以拿到ip和Port后并不是直接连接连接。域名也会有重定向的问题,如果浏览器返回相应报文中,状态码是301或302,并有一个Location字段,表示该域名需要重定向到另一个地址,该操作是服务器设置的。

Content-Type 是 HTTP 头中一个非常重要的字段, 它告诉浏览器服务器返回的响应体数据是什么类型

HTTP是一个无状态协议,那么登录状态是如何保持的?

cookie方式

  • 浏览器发送用户信息到服务器
  • 服务器校验用户合法后,生成一段表示用户的字符串,并写入到响应头的Set-Cookie字段中
  • 浏览器解析响应头,将cookie信息保存到本地
  • 当浏览器再次发送请求时,会读取本地存储的cookie中,并将其写入请求头的Cookie字段中
  • 服务器收到请求后,解析请求头,获取Cookie字段中的信息,然后查询后台,判断该用户为已登录状态,然后返回对应数据
    token方式
  • 前端发送用户信息到服务器
  • 服务器校验用户合法后,会根据密钥、过期时间和一些加密算法生成token
  • 前端将token保存下来
  • 当前端再次发送请求时,会携带上token值
  • 服务器收到请求后,若还有有效期则返回数据,若过期会返回响应状态码,前端根据状态码做一些处理,如跳转到登录页,要求用户重新登录

浏览器的URL导航流程?
渲染流程?

JavaScript -> Style -> Layout(布局,回流) -> Paint(绘制) -> Composite(合成)

当从服务器接收HTML页面的第一批数据时,DOM解析器就开始工作了,在解析过程中,如果遇到了JS脚本,如下所示:


    
        极客时间
        
    

那么DOM解析器会先执行JavaScript脚本,执行完成之后,再继续往下解析。

那么第二种情况复杂点了,我们内联的脚本替换成js外部文件,如下所示:


    
        极客时间
        
    

这种情况下,当解析到JavaScript的时候,会先暂停DOM解析,并下载foo.js文件,下载完成之后执行该段JS文件,然后再继续往下解析DOM。这就是JavaScript文件为什么会阻塞DOM渲染。

我们再看第三种情况,还是看下面代码: