以输入 http://github.com/appleguardu... web 请求本质上就是一台主机去另外一台主机获取对应的资源.css
当导航栏输入 http://github.com/appleguardu... 浏览器进程把这个url交给网络进程处理, 给我去这台主机下取资源;html
protocol: 协议头, 譬若有http,ftp等 host: 主机域名或IP地址 port: 端口号 path: 目录路径 query: 即查询参数 fragment: 即#后的hash值,通常用来定位到某个位置
因为不一样主机之间都是经过IP地址来肯定的,因此首先会进行域名解析,查询; 浏览器会向域名服务器去查询http://github.com对应的Ip. // Ip查询也有一套优化机制: 缓存机制(能够减小网络请求) 浏览器缓存: 浏览器会按照必定的频率缓存 DNS 记录; 操做系统缓存: 若是浏览器缓存中找不到须要的 DNS 记录,那就去操做系统中找; 路由缓存: 路由器也有 DNS 缓存; ISP(互联网服务提供商)的DNS服务器: ISP 有专门的 DNS 服务器应对 DNS 查询请求; 根服务器: ISP 的 DNS 服务器还找不到的话,它就会向根服务器发出请求,进行递归查询; (DNS 服务器先问根域名服务器.com 域名服务器的 IP 地址,而后再问.github 域名服务器,依次类推)
若是不是特别指定,http协议默认的80端口, https: 443
chorome浏览器有个机制, 统一域名下同时最多只能创建 6 个 TCP链接(浏览器的限制可能不同), 若是超过 6 个请求, 那么剩下的会进入排队等待的状态, 等待前面的完过后本身再去创建链接node
TCP 协议git
TCP运行: 链接建立、数据传送和链接终止
1.客户端经过向服务器端发送一个SYN来建立一个主动打开,做为三次握手的一部分; 客户端把这段链接的序号设定为随机数A。 2.服务器端应当为一个合法的SYN回送一个SYN/ACK。 ACK的确认码应为A+1,SYN/ACK包自己又有一个随机产生的序号B。 3.最后,客户端再发送一个ACK。此时包的序号被设定为A+1,而ACK的确认码则为B+1。 当服务端收到这个ACK的时候,就完成了三次握手,并进入了链接建立状态。 client侧: SYN ACK server侧: SYN+ACK
使用序号,对收到的TCP报文段进行排序以及检测重复的数据; 使用校验和检测报文段的错误,即无错传输; 使用确认和计时器来检测和纠正丢包或延时; 流量控制(Flow control);拥塞控制(Congestion control);丢失包的重传。
链接终止使用了四路握手过程(或称四次握手,four-way handshake),在这个过程当中链接的每一侧都独立地被终止。 当一个端点要中止它这一侧的链接,就向对侧发送FIN,对侧回复ACK表示确认。 所以,拆掉一侧的链接过程须要一对FIN和ACK,分别由两侧端点发出。 client侧: FIN ACK server侧: ACK FIN
当 TCP 链接创建以后, 浏览器与服务器之间开始通讯,传输数据github
GET /appleguardu HTTP/1.1 // 请求方式:(Get、POST、OPTIONS、PUT、HEAD、DELETE、CONNECT、TRACE // 资源路径URI: /appleguardu // 协议版本: HTTP 1.1
Accept: 接收类型,表示浏览器支持的MIME类型(对标服务端返回的Content-Type) Accept-Encoding: 浏览器支持的压缩类型,如gzip等,超出类型不能接收 Content-Type: 客户端发送出去实体内容的类型 Cache-Control: 指定请求和响应遵循的缓存机制,如no-cache If-Modified-Since: 对应服务端的Last-Modified,用来匹配看文件是否变更,只能精确到1s以内,http1.0中 Expires: 缓存控制,在这个时间内不会请求,直接使用缓存,http1.0,并且是服务端时间 Max-age: 表明资源在本地缓存多少秒,有效时间内不会请求,而是使用缓存,http1.1中 If-None-Match: 对应服务端的ETag,用来匹配文件内容是否改变(很是精确),http1.1中 Cookie: 有cookie而且同域访问时会自动带上 Connection: 当浏览器与服务器通讯时对于长链接如何进行处理,如keep-alive Host: 请求的服务器URL Origin: 最初的请求是从哪里发起的(只会精确到端口),Origin比Referer更尊重隐私 Referer: 该页面的来源URL(适用于全部类型的请求,会精确到详细页面地址,csrf拦截经常使用到这个字段) User-Agent: 用户客户端的一些必要信息,如UA头部等
post 请求中参数常放在请求体中 如参数的序列化形式(a=1&b=2这种; 或者直接放表单对象(Form Data对象,上传时能够夹杂参数以及文件的等
终止请求
浏览器会对请求的文件资源进行检查, 若是这个请求的资源存在于浏览器缓存当中, 请求就会被拦截, 浏览器直接从本地缓存中获取后发给网络进程, 并结束此处请求过程
关于http缓存介绍web
缓存能够简单的划分红两种类型: 强缓存(200 from cache)与协商缓存(服务端返回304);强缓存
: 浏览器若是判断本地缓存未过时,就直接使用,无需发起http请求;协商缓存304:
当浏览器再次
向服务端发起http请求,而后服务端(304)告诉浏览器文件未改变,让浏览器使用本地缓存apache
# 几种头部缓存属性 强缓存(http1.1): Cache-Control/Max-Age 强缓存(http1.0): Pragma/Expires 协商缓存(http1.1): If-None-Match/E-tag 协商缓存(http1.0): If-Modified-Since/Last-Modified <META HTTP-EQUIV="Pragma" CONTENT="no-cache"> HTML页面中也有一个meta标签能够控制缓存方案-Pragma,不过通常都是服务端设置
Pragma: 严格来讲,它不属于专门的缓存控制头部,可是它设置no-cache时可让本地强缓存失效(属于编译控制,来实现特定的指令,主要是由于兼容http1.0,因此之前又被大量应用) Expires: 服务端配置的,属于强缓存,用来控制在规定的时间以前,浏览器不会发出请求,而是直接使用本地缓存, 注意: Expires通常对应服务器端时间,如Expires: Fri, 30 Oct 1998 14:19:41 若是客户端时间和服务端不一样步,可能形成浏览器本地的缓存无用或者一直没法过时 If-Modified-Since/Last-Modified: 这两个是成对出现的,属于协商缓存的内容; 其中浏览器的头部是If-Modified-Since,而服务端的是Last-Modified; 它的做用是,在发起请求时,若是If-Modified-Since和Last-Modified匹配, 那么表明服务器资源并未改变,所以服务端不会返回资源实体,而是只返回头部,通知浏览器可使用本地缓存... Last-Modified,顾名思义,指的是文件最后的修改时间,并且只能精确到1s之内 注意: 若是服务端的文件会周期性的改变, 致使缓存失效
Cache-Control: 缓存控制头部,有no-cache、max-age等多种取值 Max-Age: 服务端配置的,用来控制强缓存,在规定的时间以内,浏览器无需发出请求,直接使用本地缓存, 注意,Max-Age是Cache-Control头部的值,不是独立的头部, 譬如Cache-Control: max-age=3600,并且它值得是绝对时间,由浏览器本身计算 If-None-Match/E-tag: 这两个是成对出现的,属于协商缓存的内容; 其中浏览器的头部是If-None-Match,而服务端的是E-tag, 一样,发出请求后,若是If-None-Match和E-tag匹配,则表明内容未变,通知浏览器使用本地缓存; 和Last-Modified不一样,E-tag更精确,它是相似于指纹同样的东西,因此会优先级也更高... 基于FileEtag INode Mtime Size生成,也就是说,只要文件变,指纹就会变,并且没有1s精确度的限制。
当服务器接收到浏览器的请求报文后, 会交给对应的处理程序进行处理(此处省略...),而后想服务器返回响应报文json
HTTP/1.1 200 OK // 协议版本 状态码 状态码信息 // 200——代表该请求被成功地完成,所请求的资源发送回客户端 // 304——自从上次请求后,请求的网页未修改过,请客户端使用本地缓存 // 400——客户端请求有错(譬如能够是安全模块拦截) // 401——请求未经受权 // 403——禁止访问(譬如能够是未登陆时禁止) // 404——资源未找到 // 500——服务器内部错误 // 503——服务不可用
Access-Control-Allow-Headers: 服务器端容许的请求Headers Access-Control-Allow-Methods: 服务器端容许的请求方法 Access-Control-Allow-Origin: 服务器端容许的请求Origin头部(譬如为*) Content-Type: 服务端返回的实体内容的类型 Date: 数据从服务器发送的时间 Cache-Control: 告诉浏览器或其余客户,什么环境能够安全的缓存文档 Last-Modified: 请求资源的最后修改时间 Expires: 应该在何时认为文档已通过期,从而再也不缓存它 Max-age: 客户端的本地资源应该缓存多少秒,开启了Cache-Control后有效 ETag: 请求变量的实体标签的当前值 Set-Cookie: 设置和页面关联的cookie,服务器经过这个头部把cookie传给客户端 Keep-Alive: 若是客户端有keep-alive,服务端也会有响应(如timeout=38) Server: 服务器的一些相关信息
响应体通常是服务端须要传给客户端的内容; 如接口请求时: 实体中就是对应的信息的 json格式对象 如页面请求时: 实体中就是对应的 html 字符串
通常来讲, 请求头部和响应头部是互相匹配的
如请求头部的Accept要和响应头部的Content-Type匹配,不然会报错;
跨域请求时,请求头部的Origin要匹配响应头部的Access-Control-Allow-Origin,不然会报跨域错误
还有在使用缓存时,
请求头部的If-Modified-Since、If-None-Match分别和
响应头部的Last-Modified、ETag相对应跨域
以上基本都是经过服务端程序来控制的
浏览器
当响应状态码是 301 时,会发生重定向, 浏览器进程从新让导航进行工做, 修改 location 字段中的地址,继续上述的请求流程
浏览器进程开始调度, 渲染进程经过管道接受网络进程的html数据,开始解析html工做
当渲染进程接收到导航的确认信息,开始接受HTML数据时,主线程会解析文本字符串为 DOM; 这里依靠 HTMl 解析器: 接受字节流 -> 维护 token 栈 -> 生成节点node -> 组成 DOM; 遇到内嵌 script 时, DOM解析工做中止; js引擎介入执行(可能会修改dom结构); 执行完 js 后恢复解析工做, 因此 js 会阻塞 dom 解析. 遇到其余内联资源时(css,img)会通知网络进程去下载, 特别是 css; js 在操做dom 样式时会依赖cssom,生成 layoutTree也须要 cssom; 因此 css 又会阻塞 js 的执行
这里会基于 CSS 选择器解析 CSS 获取每个节点的最终的计算样式值; 对应的就是styleSheets
想要渲染一个完整的页面,除了获知每一个节点的具体样式,还须要获知每个节点在页面上的位置, 布局实际上是找到全部元素的几何关系的过程。 这里经过遍历 DOM 及相关元素的计算样式,主线程会构建出包含每一个元素的坐标信息及盒子大小的布局树。 布局树和 DOM 树相似,可是其中只包含页面可见的元素,若是一个元素设置了 `display:none` , 这个元素不会出如今布局树上,伪元素虽然在 DOM 树上不可见,可是在布局树上是可见的。
为特定的节点生成专用图层(will-change属性), 生成 图层树; 为图层生成绘制表(记录了绘制指令和顺序), 提交到合成线程
合成线程将图层分为图块, 经过光栅化生成位图(GPU 进程)
图块被光栅化后会生成一个绘制命令, 经过 IPC 提交给浏览器进程去执行, 绘制到内存中而后展现在显示器上
当数据传送完毕,须要断开 tcp 链接,此时发起 tcp 四次挥手;
一般状况下,一旦服务器向客户端返回了请求数据,它就要关闭 TCP 链接。
不过若是浏览器或者服务器在其头信息中加入了
Connection: Keep-Alive (http/1.1下默认启用, http/1.0默认close) // keep-alive不会永远保持,它有一个持续时间,通常在服务器中配置(如apache, 另外长链接须要客户端和服务器都支持时才有效
TCP 链接在发送后将仍然保持打开状态,这样浏览器就能够继续经过同一个 TCP 链接 发送请求。
保持 TCP 链接能够省去下次请求时须要创建链接的时间,提高资源加载速度。 好比,一个 Web 页面中内嵌的图片就都来自同一个 Web 站点,若是初始化了一个持久连 接,你就能够复用该链接,以请求其余资源,而不须要从新再创建新的 TCP 链接。
- 多路复用(即一个tcp/ip链接能够请求多个资源) - 首部压缩(http头部压缩,减小体积) - 二进制分帧(在应用层跟传送层之间增长了一个二进制分帧层,改进传输性能,实现低延迟和高吞吐量) - 服务器端推送(服务端能够对客户端的一个请求发出多个响应,能够主动通知客户端) - 请求优先级(若是流被赋予了优先级,它就会基于这个优先级来处理,由服务器决定须要多少资源来处理该请求。)