计算机网络
Get和Post的区别
Post 和 Get 是 HTTP 请求的两种方法,其区别如下:
- 应用场景:GET 请求是一个幂等(即多次请求返回值相同)的请求,一般 Get 请求用于对服务器资源不会产生影响的场景,比如说请求一个网页的资源。而 Post 不是一个幂等的请求,一般用于对服务器资源会产生影响的情景,比如注册用户这一类的操作。
- 是否缓存:因为两者应用场景不同,浏览器一般会对 Get 请求缓存,但很少对 Post 请求缓存。
- 发送的报文格式:Get 请求的报文中实体部分为空,Post 请求的报文中实体部分一般为向服务器发送的数据。
- 安全性:Get 请求可以将请求的参数放入 url 中向服务器发送,这样的做法相对于 Post 请求来说是不太安全的,因为请求的 url 会被保留在历史记录中。
- 请求长度:浏览器由于对 url 长度的限制,所以会影响 get 请求发送数据时的长度。这个限制是浏览器规定的,并不是 RFC 规定的。
- 参数类型:post 的参数传递支持更多的数据类型。
方法 | 幂等性 | 参数位置 | 缓存性 | 安全性 | 核心用途 | 典型场景 | 响应状态码 |
---|---|---|---|---|---|---|---|
GET | ✅(幂等) | URL | ✅(可缓存) | 低(参数暴露) | 获取资源当前状态 | 查询数据列表、获取详情页 | 200 OK |
POST | ❌(非幂等) | 请求体 | ❌(不可缓存) | 高(参数隐藏) | 创建新资源、提交数据 | 用户注册、提交表单、上传文件 | 201 Created |
PUT | ✅(幂等) | 请求体 | ❌ | 高 | 完整替换资源(需提供全部数据) | 更新用户完整信息、覆盖配置文件 | 200 OK/204 No Content |
DELETE | ✅(幂等) | URL / 请求体 | ❌ | 高 | 删除指定资源 | 删除用户、商品或文件 | 204 No Content |
PATCH | ❌/✅* | 请求体 | ❌ | 高 | 部分更新资源(仅传修改字段) | 修改用户邮箱、密码或部分属性 | 200 OK/204 No Content |
HEAD | ✅ | URL | ✅ | 低 | 获取资源元信息(仅响应头) | 检查文件大小、验证缓存有效性 | 200 OK |
OPTIONS | ✅ | URL | ❌ | 高 | 获取服务器支持的请求方法和 CORS 权限 | 浏览器跨域预检请求、检查 API 支持的方法 | 200 OK |
304状态码
服务器为了提高网站访问速度,对之前访问的部分页面指定缓存机制,当客户端在此对这些页面进行请求,服务器会根据缓存内容判断页面与之前是否相同,若相同便直接返回304,此时客户端调用缓存内容,不必进行二次下载。
状态码304不应该认为是一种错误,而是对客户端有缓存情况下服务端的一种响应。
搜索引擎蜘蛛会更加青睐内容源更新频繁的网站。通过特定时间内对网站抓取返回的状态码来调节对该网站的抓取频次。若网站在一定时间内一直处于304的状态,那么蜘蛛可能会降低对网站的抓取次数。相反,若网站变化的频率非常之快,每次抓取都能获取新内容,那么日积月累,的回访率也会提高。
产生较多304状态码的原因:
- 页面更新周期长或不更新
- 纯静态页面或强制生成静态html
304状态码出现过多会造成以下问题:
- 网站快照停止;
- 收录减少;
- 权重下降。
HTTP协议,从HTTP1.0到HTTP3.0
首先HTTP1.0最大的问题在于连接的持续性,其每一次发送请求都会重新走TCP连接(三次握手,四次挥手)
而HTTP1.1中,可以将连接改为持久连接,即采用一次TCP连接来发送多个http请求,但是后端服务器接受到请求的时候,受限于协议要求,必须要按照请求的顺序来响应请求,这就导致了如果服务器需要较长的时间处理前面的请求,会导致后面的请求被阻塞,浪费时间。且由于HTTP1.1中头部是明文传输的,所有会导致头部的数据量比较大,再加上多个请求中的头部可能完全一致,重复发送会导致带宽的浪费。
HTTP1.0和HTTP1.1都需要外挂TLS协议
HTTP2.0
首先通过HPACK算法(为高频出现的头部信息使用哈夫曼编码生成一份索引表,写入HTTP2框架,同时使用动态表来扩充头部信息)来压缩头部。
其次,将HTTP1中的文本格式改成二进制帧,帧包含帧头和帧数据,帧数据存放的就是HPACK压缩后的头部和数据
通过并发传输解决了队头阻塞的问题,一个TCP连接中包含多个stream,stream中包含多个messgae,每一个message中又包含多个frame
- Stream:是连接中的一个虚拟信道,有唯一整数标识符,客户端发起的流具有奇数 ID,服务器端发起的流具有偶数 ID。它承载着双向的消息传输,并且具有一些额外的信息,如优先级等,用于控制服务器对资源的分配。
- Message:即 HTTP 的请求或响应,是一个逻辑上的完整数据单元,由一系列的 Header Frames 和 Data Frames 组成。Header Frames 包含了与 HTTP 请求或响应头相关的信息,Data Frames 则包含了消息体的信息。
- Frame:包含类型(Type)、长度(Length)、标记(Flags)、流标识(Stream ID)和有效载荷(Payload)等部分。Type 表示帧的类型,如 Headers 帧用于传输头部信息,Data 帧用于传输消息体数据等;Length 表示帧的长度;Flags 用于携带一些额外的控制信息;Stream ID 用于标识该帧所属的流;Payload 则是帧实际携带的数据内容。
不同stream之间可以乱序发送和接受,但是同一个stream内部必须是有序的
此外,还通过服务器推送来推送可能用到的资源:
- 服务器端操作
- 预测资源需求:服务器接收到客户端的请求后,会根据经验、配置或请求的相关信息,预测客户端可能需要的额外资源。例如,当客户端请求一个 HTML 页面时,服务器可以分析 HTML 代码中引用的 CSS、JavaScript 文件以及图片等资源,判断这些资源可能是客户端后续需要的。
- 创建推送流:服务器为每个要推送的资源创建一个推送流(Push Stream)。推送流是一种特殊的流,用于在客户端没有显式请求的情况下,将资源发送给客户端。
- 发送 PUSH_PROMISE 帧:服务器首先发送一个特殊的
PUSH_PROMISE
帧,该帧包含了推送资源的请求头信息,如 URL、方法等。这个帧就像是一个通知,告诉客户端 “我将要推送这个资源,你做好准备”。然后,服务器在推送流上发送实际的资源数据。
- 客户端处理
- 接收和检查:客户端收到初始请求的响应后,会解析相关内容,如 HTML 页面。同时,客户端会检查是否收到了针对其他资源的
PUSH_PROMISE
帧。 - 使用推送资源:如果客户端收到了某个资源的
PUSH_PROMISE
帧,并且该资源是它所需要的,那么客户端会使用推送流中的数据,而无需再次向服务器发送请求获取该资源。 - 拒绝推送:如果客户端已经缓存了服务器推送的资源,或者由于某种原因不需要该资源,它可以发送一个
RST_STREAM
帧来取消推送流,告知服务器停止推送。
- 接收和检查:客户端收到初始请求的响应后,会解析相关内容,如 HTML 页面。同时,客户端会检查是否收到了针对其他资源的
HTTP3.0
将TCP连接换成了基于quic协议的UDP连接,来实现性能优化。
包括连接迁移(通过连接 ID来表示连接用户,从而无缝迁移),性能提升(集成了TLS)
HTTPS相较于HTTP
1 在 TCP 和 HTTP 之间加入了 SSL/TLS 安全协议
2 TCP 三次握手之后还需进行 SSL/TLS 握手
3 HTTP 的端口号是 80,HTTPS 的端口号是 443
4 HTTPS 需要向 CA 申请证书
加密过程
一、身份验证阶段:确认服务器合法性 客户端发起连接 通过 TCP 建立基础网络连接,发送支持的加密协议版本、算法套件及随机数(Client Random)。 服务器返回证书 选择协议与算法,返回随机数(Server Random)及包含公钥的数字证书(如 X.509 证书)。 客户端验证证书 通过 CA 根证书校验服务器证书的签名、有效期、域名匹配性,确保未被篡改且身份真实。 二、密钥协商阶段:安全生成会话密钥 生成预主密钥 客户端生成随机「预主密钥」,用服务器公钥加密后传输(仅服务器私钥可解密)。 计算主密钥与会话密钥 双方通过 Client Random、Server Random、预主密钥 计算出相同的「主密钥」,进一步衍生出对称加密的「会话密钥」(包含客户端和服务器各自的读写密钥)。 核心逻辑:非对称加密(公钥 + 私钥)保障密钥协商安全,对称加密(会话密钥)确保通信效率。 三、加密通信阶段:数据安全传输 验证密钥有效性 双方用会话密钥加密「握手完成」消息,确认密钥同步正确。 加密数据传输 所有后续数据通过会话密钥进行对称加密(如 AES)和完整性校验(如 HMAC),防止中间人窃取或篡改。
HTTP1.0和HTTP1.1之间的区别
HTTP 1.0和 HTTP 1.1 有以下区别:
- 连接方面,http1.0 默认使用非持久连接,而 http1.1 默认使用持久连接。http1.1 通过使用持久连接来使多个 http 请求复用同一个 TCP 连接,以此来避免使用非持久连接时每次需要建立连接的时延。
- 资源请求方面,在 http1.0 中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,http1.1 则在请求头引入了 range 头域,它允许只请求资源的某个部分,即返回码是 206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
- 缓存方面,在 http1.0 中主要使用 header 里的 If-Modified-Since、Expires 来做为缓存判断的标准,http1.1 则引入了更多的缓存控制策略,例如 Etag、If-Unmodified-Since、If-Match、If-None-Match 等更多可供选择的缓存头来控制缓存策略。
- http1.1 中新增了 host 字段,用来指定服务器的域名。http1.0 中认为每台服务器都绑定一个唯一的 IP 地址,因此,请求消息中的 URL 并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机,并且它们共享一个IP地址。因此有了 host 字段,这样就可以将请求发往到同一台服务器上的不同网站。
- http1.1 相对于 http1.0 还新增了很多请求方法,如 PUT、HEAD、OPTIONS 等。
什么是持久连接
1. Connection
头字段的控制
- HTTP/1.0:默认使用短连接(每次请求 / 响应后关闭连接),若需长连接需显式声明
Connection: keep-alive
,但不同浏览器实现可能存在差异。 - HTTP/1.1:默认启用长连接,即请求头和响应头中默认包含
Connection: keep-alive
(除非显式设置为close
)。 - 字段作用:
- 客户端在请求头中发送
Connection: keep-alive
,告知服务器 “希望保持连接”。 - 服务器在响应头中返回
Connection: keep-alive
,表示 “同意保持连接”。 - 若双方均未声明
Connection: close
,则连接会被复用(直到达到服务器设定的超时时间或手动关闭)。
- 客户端在请求头中发送
2. 连接复用流程
- 首次请求:客户端与服务器建立 TCP 连接(三次握手),发送请求并获取响应。
- 连接保持:响应完成后,连接不关闭,而是进入 “空闲状态”,等待客户端发送下一个请求。
- 后续请求:客户端直接通过该 TCP 连接发送新请求,无需重新建立连接,节省了三次握手和 TLS 握手(若使用 HTTPS)的开销。
- 连接关闭:当满足以下条件之一时,连接关闭:
- 客户端或服务器在请求 / 响应头中显式设置
Connection: close
。 - 连接空闲时间超过服务器配置的超时时间(如 Nginx 默认
keepalive_timeout 65;
)。 - 服务器主动关闭连接(如达到最大连接数限制)。
- 客户端或服务器在请求 / 响应头中显式设置
url的组成部分
从上面的URL可以看出,一个完整的URL包括以下几部分:
- 协议部分:该URL的协议部分为“http:”,这代表网页使用的是HTTP协议。在Internet中可以使用多种协议,如HTTP,FTP等等本例中使用的是HTTP协议。在"HTTP"后面的“//”为分隔符;
- 域名部分:该URL的域名部分为“www.aspxfans.com”。一个URL中,也可以使用IP地址作为域名使用
- 端口部分:跟在域名后面的是端口,域名和端口之间使用“:”作为分隔符。端口不是一个URL必须的部分,如果省略端口部分,将采用默认端口(HTTP协议默认端口是80,HTTPS协议默认端口是443);
- 虚拟目录部分:从域名后的第一个“/”开始到最后一个“/”为止,是虚拟目录部分。虚拟目录也不是一个URL必须的部分。本例中的虚拟目录是“/news/”;
- 文件名部分:从域名后的最后一个“/”开始到“?”为止,是文件名部分,如果没有“?”,则是从域名后的最后一个“/”开始到“#”为止,是文件部分,如果没有“?”和“#”,那么从域名后的最后一个“/”开始到结束,都是文件名部分。本例中的文件名是“index.asp”。文件名部分也不是一个URL必须的部分,如果省略该部分,则使用默认的文件名;
- 锚部分:从“#”开始到最后,都是锚部分。本例中的锚部分是“name”。锚部分也不是一个URL必须的部分;
- 参数部分:从“?”开始到“#”为止之间的部分为参数部分,又称搜索部分、查询部分。本例中的参数部分为“boardID=5&ID=24618&page=1”。参数可以允许有多个参数,参数与参数之间用“&”作为分隔符。
其中锚部分,即可以用作单页应用的hash路由,也可以定位到文档中id=“name” 处
状态码
2xx状态码
状态码2XX表示请求被正常处理了
状态码 | 含义 | 典型场景 |
---|---|---|
200 | 请求成功,返回完整内容 | 常规查询、页面访问 |
201 | 创建资源成功 | 注册用户、上传文件 |
202 | 请求已接受但未处理完成 | 异步任务(如发送邮件、生成报告) |
204 | 成功处理但无返回内容 | 删除资源、更新操作确认 |
206 | 成功返回部分内容 | 大文件分片下载、断点续传 |
3xx状态码
3XX 响应结果表明浏览器需要执行某些特殊的处理以正确处理请求。一般都是重定向,会在响应头中添加一个Location字段保存新的网址,浏览器会自动跳转到该网址
为什么POST会更改成GET?
避免表单等重定向后,重复操作
状态码 | 含义 | 重定向类型 | 请求方法保留 | 典型场景 |
---|---|---|---|---|
301 | 永久重定向 | 永久 | 转为 GET | 域名迁移、旧路径废弃 |
302 | 临时重定向 | 临时 | 可能改变 | 登录后跳转、临时分配服务器 |
303 | 要求查看其他地址(强制 GET) | 临时 | 转为 GET | 表单提交后重定向到结果页 |
304 | 未修改(使用缓存) | 无重定向 | - | 缓存验证,减少数据传输 |
307 | 临时重定向(保留方法) | 临时 | 保留原方法 | 需要保持 POST/GET 方法的临时跳转 |
308 | 永久重定向(保留方法) | 永久 | 保留原方法 | 资源永久迁移且需保持请求方法 |
4xx状态码
一般是客户端产生的错误
状态码 | 状态码名称 | 含义及场景说明 |
---|---|---|
400 | Bad Request(错误请求) | 客户端请求存在语法错误或参数无效,服务器无法理解请求。 - 示例:参数格式错误、缺少必填字段、JSON 解析失败。 |
401 | Unauthorized(未授权) | 客户端请求需要身份验证,但未提供有效凭证(如 Token、Cookie 等) - 常见场景:登录失效、API 接口未携带认证信息。 |
403 | Forbidden(禁止访问) | 客户端已通过身份验证,但服务器拒绝其访问资源(通常与权限相关) - 示例:用户无权限访问某个页面、IP 被封禁、文件权限设置错误。 |
404 | Not Found(未找到) | 服务器无法找到请求的资源(如 URL 错误、资源已被删除) - 常见场景:输入错误的网址、页面被重命名或移除。 |
405 | Method Not Allowed(方法不允许) | 服务器支持请求的资源,但不允许使用当前请求方法(如资源仅支持 GET,但客户端使用 POST) - 需检查接口文档中的请求方法是否正确。 |
408 | Request Timeout(请求超时) | 服务器等待客户端请求的时间过长,请求超时 - 常见原因:网络延迟过高、客户端未及时发送请求数据。 |
409 | Conflict(冲突) | 客户端请求与服务器当前状态冲突(如资源已存在、版本冲突) - 示例:重复创建相同名称的资源、并发操作导致数据冲突。 |
410 | Gone(已删除) | 请求的资源已永久删除,且服务器不再提供该资源 - 与 404 的区别:410 明确资源已不存在,404 可能是暂时不可用或路径错误。 |
411 | Length Required(需要 Content-Length) | 客户端请求未提供 Content-Length 头部字段,而服务器要求必须提供(如 POST/PUT 请求提交数据时)。 |
412 | Precondition Failed(前提条件失败) | 客户端请求的前提条件(如 If-Match 等条件请求头)不满足 - 常见于缓存验证或并发控制场景。 |
413 | Payload Too Large(请求体过大) | 客户端提交的请求体(如表单数据、JSON)超过服务器允许的最大大小 - 需调整请求数据大小或联系服务器管理员修改限制。 |
414 | URI Too Long(URI 过长) | 请求的 URI(网址)超过服务器支持的最大长度 - 常见于 GET 请求携带过多参数(浏览器对 URL 长度有限制)。 |
422 | Unprocessable Entity(不可处理的实体) | 客户端请求格式正确,但语义无法被服务器处理(如表单验证失败、数据类型不匹配) - 常见于 RESTful API 的参数校验场景。 |
429 | Too Many Requests(请求过多) | 客户端发送请求频率过高,触发服务器的速率限制(Rate Limit) - 需根据响应头中的 Retry-After 字段重试请求。 |
5xx状态码
服务器发生错误
状态码 | 名称 | 详细说明 |
---|---|---|
500 | Internal Server Error (内部服务器错误) | 最常见的服务器错误。可能由代码逻辑错误、数据库连接失败、文件权限问题等导致。 示例:服务器端脚本执行时抛出未捕获的异常。 |
501 | Not Implemented (未实现) | 服务器不支持请求所需的功能或方法。 示例:客户端请求了服务器不支持的 HTTP 方法(如 PUT /DELETE ,但服务器未启用相关功能)。 |
502 | Bad Gateway (错误网关) | 服务器作为网关或代理时,从上游服务器(如后端服务、CDN)收到无效响应。 示例:微服务架构中,网关调用的某个服务不可用或返回错误。 |
503 | Service Unavailable (服务不可用) | 服务器暂时无法处理请求,可能因过载、维护或停机导致。 示例:电商大促期间服务器流量激增,触发限流策略;或管理员主动将服务器下线维护。 |
504 | Gateway Timeout (网关超时) | 服务器作为网关或代理时,等待上游服务器响应超时。 示例:后端服务处理请求耗时过长,超过网关设置的超时时间。 |
505 | HTTP Version Not Supported (HTTP 版本不支持) | 服务器不支持请求中使用的 HTTP 协议版本(如客户端使用 HTTP/2,但服务器仅支持 HTTP/1.1)。 |
cookie,localstorage,sessionstorage的区别
维度 | Cookie | LocalStorage | SessionStorage |
---|---|---|---|
数据生命周期 | 可设置过期时间(永久或会话级) | 永久存储(除非手动删除) | 仅当前会话有效(窗口关闭即删除) |
容量限制 | 较小(通常 4KB 左右) | 较大(不同浏览器差异大,通常 5MB - 10MB) | 与 LocalStorage 相近 |
网络传输 | 自动随 HTTP 请求发送到服务器 | 不参与网络传输 | 不参与网络传输 |
作用域 | 域名 + 路径限制 | 域名限制(同域名共享) | 域名 + 标签页 / 窗口限制 |
数据类型 | 仅字符串(需手动序列化 / 反序列化) | 仅字符串(需手动处理 JSON 等格式) | 仅字符串(需手动处理 JSON 等格式) |
API 操作 | 通过 JS 或服务器设置,操作复杂 | 通过 localStorage 对象简单操作,还可以通过storage事件监听数据变化 | 通过 sessionStorage 对象简单操作 |
安全性 | 可配置 HttpOnly /Secure 增强安全 | 易受 XSS 攻击(JS 可直接访问) | 易受 XSS 攻击(JS 可直接访问) |
典型场景 | 身份验证、服务器状态同步 | 长期用户偏好、前端缓存 | 临时表单数据、单标签页状态管理 |
强缓存和协商缓存
强缓存(从内存/磁盘中读取)
从内存读取的缓存更快
🔸定义
- 强缓存是在资源未过期的情况下,直接使用缓存中的资源,而不需要与服务器进行任何交互。这种缓存机制通过HTTP响应头来设置资源的过期时间,通常使用
Cache-Control
和Expires
头来控制。
🔸工作原理
- 当浏览器请求资源时查看强缓存是否有效。如果有效,浏览器直接使用缓存的资源,而不会向服务器发送请求;如果缓存已过期,浏览器会重新向服务器请求资源。
🔸相关HTTP响应头
eg:Cache-Control: max-age=10(从第一次请求资源时开始,往后10秒内再次请求就直接从内存中读取,不需要与服务器做任何交互)
- Cache-Control:设置缓存的策略。如max-age(缓存的最大有效时间)和public/private(资源的可以被浏览器缓存也可以被代理服务器缓存/只能浏览器)。
- no-cache:强制进行协商缓存
- no-store:禁止所有缓存
- 多条属性使用逗号分隔
- Expires:指定资源过期的具体时间(在HTTP/1.0中常用,HTTP/1.1推荐使用Cache-Control)(过度依赖本地时间,未考虑本地时间和服务器时间不同步的情况)
状态码为200 OK (from disk cache)
或 200 OK (from memory cache)
, 其中js/css一般存在内存中,图片等会存在硬盘中。memory cache关闭浏览器后会清除,而disk cache会被保留
协商缓存
基于last-modified的协商缓存
第一次请求
- 首先需要在服务器端读出文件修改时间
- 将此修改时间赋给响应头的last-modified字段
- 最后设置Cache-Control:no-cache
之后的每一次请求
- 当客户端读取到
last-modified
的时候,会在下一次请求头中携带If-Modified-Since
,这个的值就是上面的修改时间。- 服务器收到事件后再次读取该资源的修改时间,做对比,如果相等说明未被修改,就返回一个304响应,表示可以直接读取,否则返回新的资源并更新修改时间到
last-modified
。
- 服务器收到事件后再次读取该资源的修改时间,做对比,如果相等说明未被修改,就返回一个304响应,表示可以直接读取,否则返回新的资源并更新修改时间到
- 当客户端读取到
基于ETag的协商缓存(HTTP1.1开始)
文件指纹:文件打包后输出的文件名的后缀,也可以是某种hash值
- 第一次请求资源的时候,服务端读取文件并计算出文件指纹,将文件指纹放在响应头的Etag字段中跟资源一起返回给客户端
- 第二次请求资源的时候,客户端自动从缓存种读取上一次返回的Etag也就是文件指纹,并赋给请求头的If-None-Match字段,让上一次的文件指纹跟随请求一起回到服务端
- 服务端拿到上一次文件指纹,和目标资源的指纹进行对比,如果完全吻合,返回304状态码和空的响应体;如果不吻合说明文件被更改,将新的文件指纹重新存储到响应头的Etag并返回给客户端
已经设置为强缓存的文件想转化为协商缓存:
- 清除浏览器的缓存
- 修改文件的URL(在JS文件的引入中加入查询参数:版本号或者时间戳;修改文件名)
- Ctrl+F5强制刷新界面
- 浏览器的开发者工具F12设置禁用缓存选项
从url到页面渲染中发生了什么
1、在浏览器地址栏输⼊URL
2、浏览器查看缓存,如果请求资源在缓存中并且新鲜,跳转到转码步骤
如果资源未缓存,发起新请求
如果已缓存,检验是否⾜够新鲜,⾜够新鲜直接提供给客户端,否则与服务器进⾏验证。
检验新鲜通常有两个HTTP头进⾏控制 Expires 和 Cache-Control:
- HTTP1.0提供 Expires,值为⼀个绝对时间表示缓存新鲜⽇期
- HTTP1.1增加了Cache-Control: max-age=time,值为以秒为单位的最⼤新鲜时间
3、浏览器解析URL获取协议,主机,端⼝,path
4、浏览器组装⼀个HTTP(GET)请求报⽂
5、浏览器获取主机 ip 地址,过程如下:
浏览器缓存
本机缓存
hosts⽂件
路由器缓存
ISP DNS缓存
DNS递归查询(可能存在负载均衡导致每次IP不⼀样)
6、打开⼀个socket与⽬标IP地址,端⼝建⽴TCP链接,三次握⼿如下:
客户端发送⼀个TCP的SYN=1,Seq=X的包到服务器端口
服务器发回SYN=1, ACK=X+1, Seq=Y的响应包
客户端发送ACK=Y+1, Seq=X+1
7、TCP链接建⽴后发送HTTP请求
8、服务器接受请求并解析,将请求转发到服务程序,如虚拟主机使⽤HTTP Host头部判断请求的服务程序
9、服务器检查HTTP请求头是否包含缓存验证信息,如果验证缓存新鲜,返回304等对应状态码
10、处理程序读取完整请求并准备HTTP响应,可能需要查询数据库等操作
11、服务器将响应报⽂通过TCP连接发送回浏览器
12、浏览器接收HTTP响应,然后根据情况选择关闭TCP连接或者保留重⽤,关闭TCP连接的四次握⼿如下:
主动⽅发送Fin=1, Seq= X报⽂
被动⽅发送ACK=X+1, Seq=Z报⽂
被动⽅发送Fin=1, ACK=X+1, Seq=Y报⽂
主动⽅发送ACK=Y+1, Seq=X+1报⽂
13、浏览器检查响应状态吗:是否为1XX,3XX, 4XX, 5XX,这些情况处理与2XX不同
14、如果资源可缓存,进行缓存
15、对响应进行解码(例如gzip压缩)
16、根据资源类型决定如何处理(假设资源为HTML⽂档)
17、解析HTML⽂档,构件DOM树,下载资源,构造CSSOM树,执⾏js脚本,这些操作没有严 格的先后顺序,以下分别解释:
16、构建DOM树:
Tokenizing:根据HTML规范将字符流解析为标记
Lexing:词法分析将标记转换为对象并定义属性和规则
DOM construction:根据HTML标记关系将对象组成DOM树
17、解析过程中遇到图⽚、样式表、js⽂件,启动下载
18、构建CSSOM树:
Tokenizing:字符流转换为标记流
Node:根据标记创建节点
CSSOM:节点创建CSSOM树
19、根据DOM树和CSSOM树构建渲染树 :
从DOM树的根节点遍历所有可⻅节点,不可⻅节点包括:
script , meta 这样本身 不可⻅的标签。 被css隐藏的节点,如 display: none 对每⼀个可⻅节点,找到恰当的CSSOM规则并应⽤
发布可视节点的内容和计算样式
20、js解析如下:
浏览器创建Document对象并解析HTML,将解析到的元素和⽂本节点添加到⽂档中,此时document.readystate为loading
HTML解析器遇到没有async和defer的script时,将他们添加到⽂档中,然后执⾏⾏内 或外部脚本。这些脚本会同步执⾏,并且在脚本下载和执⾏时解析器会暂停。这样就可以⽤document.write()把⽂本插⼊到输⼊流中。同步脚本经常简单定义函数和注册事件处理程序,他们可以遍历和操作script和他们之前的⽂档内容
当解析器遇到设置了async属性的script时,开始下载脚本并继续解析⽂档。脚本会在它 下载完成后尽快执⾏,但是解析器不会停下来等它下载。异步脚本禁止使⽤ document.write(),它们可以访问⾃⼰script和之前的⽂档元素
当⽂档完成解析,document.readState变成interactive
所有defer脚本会按照在⽂档出现的顺序执⾏,延迟脚本能访问完整⽂档树,禁止使⽤ document.write()
浏览器在Document对象上触发DOMContentLoaded事件
此时⽂档完全解析完成,浏览器可能还在等待如图⽚等内容加载,等这些内容完成载⼊ 并且所有异步脚本完成载⼊和执⾏,document.readState变为complete,window触发 load事件
21、显示⻚⾯(HTML解析过程中会逐步显示⻚⾯)