307 Temporary Redirect:临时重定向,与303有着相同的含义,307会遵照浏览器标准不会从POST变成GET;(不同浏览器可能会出现不同的情况);
301与302的区别:前者是永久移动,后者是临时移动(之后可能还会更改URL)
302与303的区别:后者明确表示客户端应当采用GET方式获取资源
4xx (4种)
400 Bad Request:表示请求报文中存在语法错误;
401 Unauthorized:未经许可,需要通过HTTP认证;
403 Forbidden:服务器拒绝该次访问(访问权限出现问题)
404 Not Found:表示服务器上无法找到请求的资源,除此之外,也可以在服务器拒绝请求但不想给拒绝原因时使用;
5xx (2种)
500 Inter Server Error:表示服务器在执行请求时发生了错误,也有可能是web应用存在的bug或某些临时的错误时;
503 Server Unavailable:表示服务器暂时处于超负载或正在进行停机维护,无法处理请求;
详细版
-
在浏览器地址栏输入URL
-
浏览器查看缓存,如果请求资源在缓存中并且新鲜,跳转到转码步骤
-
如果资源未缓存,发起新请求
-
如果已缓存,检验是否足够新鲜,足够新鲜直接提供给客户端,否则与服务器进行验证。
-
检验新鲜通常有两个HTTP头进行控制Expires和Cache-Control:
-
HTTP1.0提供Expires,值为一个绝对时间表示缓存新鲜日期
-
HTTP1.1增加了Cache-Control: max-age=,值为以秒为单位的最大新鲜时间
-
浏览器解析URL获取协议,主机,端口,path
-
浏览器组装一个HTTP(GET)请求报文
-
浏览器获取主机ip地址,过程如下:
-
浏览器缓存
-
本机缓存
-
hosts文件
-
路由器缓存
-
ISP DNS缓存
-
DNS递归查询(可能存在负载均衡导致每次IP不一样)
-
打开一个socket与目标IP地址,端口建立TCP链接,三次握手如下:
-
客户端发送一个TCP的SYN=1,Seq=X的包到服务器端口
-
服务器发回SYN=1, ACK=X+1, Seq=Y的响应包
-
客户端发送ACK=Y+1, Seq=Z
-
TCP链接建立后发送HTTP请求
-
服务器接受请求并解析,将请求转发到服务程序,如虚拟主机使用HTTP Host头部判断请求的服务程序
-
服务器检查HTTP请求头是否包含缓存验证信息如果验证缓存新鲜,返回304等对应状态码
-
处理程序读取完整请求并准备HTTP响应,可能需要查询数据库等操作
-
服务器将响应报文通过TCP连接发送回浏览器
-
浏览器接收HTTP响应,然后根据情况选择关闭TCP连接或者保留重用,关闭TCP连接的四次握手如下:
-
主动方发送Fin=1, Ack=Z, Seq= X报文
-
被动方发送ACK=X+1, Seq=Z报文
-
被动方发送Fin=1, ACK=X, Seq=Y报文
-
主动方发送ACK=Y, Seq=X报文
-
浏览器检查响应状态吗:是否为1XX,3XX, 4XX, 5XX,这些情况处理与2XX不同
-
如果资源可缓存,进行缓存
-
对响应进行解码(例如gzip压缩)
-
根据资源类型决定如何处理(假设资源为HTML文档)
-
解析HTML文档,构件DOM树,下载资源,构造CSSOM树,执行js脚本,这些操作没有严格的先后顺序,以下分别解释
-
构建DOM树:
-
Tokenizing:根据HTML规范将字符流解析为标记
-
Lexing:词法分析将标记转换为对象并定义属性和规则
-
DOM construction:根据HTML标记关系将对象组成DOM树
-
解析过程中遇到图片、样式表、js文件,启动下载
-
构建CSSOM树:
-
Tokenizing:字符流转换为标记流
-
Node:根据标记创建节点
-
CSSOM:节点创建CSSOM树
-
根据DOM树和CSSOM树构建渲染树 :
-
从DOM树的根节点遍历所有可见节点,不可见节点包括:1) script,meta这样本身不可见的标签。2)被css隐藏的节点,如display: none
-
对每一个可见节点,找到恰当的CSSOM规则并应用
-
发布可视节点的内容和计算样式
-
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事件
-
显示页面(HTML解析过程中会逐步显示页面)
补充
三次握手
第一次握手:客户端向服务端发送SYN包,等待服务端响应,并进入SYN-SEND状态
第二次握手:服务端收到SYN包,并确定SYN=ACK+1,然后响应一个SYN包和ACK包。客户端进入SYN-RECV状态。
第三次握手:客户端收到服务端SYN+ACK包。向服务器发送确认包ACK。发送完毕进入ESTABLISHED状态。
四次挥手
第一次挥手:主动关闭连接一方,发送FIN包。此时发送FIN包之前发送的数据如果没有发送到。会进行重试发送。
第二次挥手:被动关闭一方收到FIN包。响应一个ACK包。
第三次挥手:被动关闭方发送一个FIN包。告诉被动关闭方。数据发送完毕。
第四次挥手:主动关闭方收到FIN包。发送一个ACK包给被动关闭方,至此四次挥手结束,断开连接。
P.S
ACK:确认位,只有ACK=1的时候ack才起作用,正常通信时ACK=1,第一次发起请求时,因为没有需要确认接收的数据所以ACK为0。
SYN:同步位,用于在建立连接时同步序号,刚开始建立连接时并没有历史接收的数据,所以ack也就没办法设置。SYN的作用就是,当接收端接收到SYN=1的报文时就会将ack设置位接收到的seq+1的值。SYN会在前两次握手时都为1,是因为通信的双方的ack都需要设置一个初始值;
FIN:终止位,用来在数据传输完毕后释放连接。
为什么是三次握手,四次挥手?
三次握手用于防止“已失效的连接请求报文段”,报文段没有丢失,而是在某个节点长时间滞留。
四次挥手:由于连接是全双工的。所以每个方向都必须单独进行关闭
因为在握手的时候服务端在listen状态,收到建立连接的syn报文后,将ack和syn放在一个报文里发送给对方,而关闭连接时,收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送。
浏览器缓存,也称Http缓存,分为强缓存和协商缓存。强缓存的优先级大于协商缓存。
1.强缓存
强缓存是利用 http 头中的 Expires 和 Cache-Control 两个字段来控制的。强缓存中,当请求再次发出时,浏览器会根据其中的 Expires 和 Cache-control 判断目标资源是否“命中”强缓存,若命中则直接从缓存中获取资源,不会再与服务端发生通信。
Expires 是时间戳(过期时间),浏览器就会先对比本地时间和 Expires 的时间戳,如果本地时间小于 Expires 设定的过期时间,那么就直接去缓存中取这个资源。
Cache-Control 利用 max-age (时间段/相对时间),如果访问间隔小于 Cache-Control 设定的时间段,那么就直接去缓存中取这个资源。
两者可以同时启用,Cache-Control 相对于 expires 优先级更高。
2.协商缓存
协商缓存通过 Last-Modified 和 Etag 实现,具体机制如下:浏览器向服务器去询问缓存的相关信息,如果服务端提示缓存资源未改动(Not Modified),资源会被重定向到浏览器缓存,这种情况下网络请求对应的状态码是 304。
Last-Modified 是一个时间戳(更新时间),首次请求时随着 Response Headers 返回 Last-Modified(请求资源在服务器上一次修改时间),再次请求时,Request Header 会带上 If-Modified-Since 的时间戳字段,它的值正是上一次 response 返回给它的 last-modified 值。
如果发生了变化,就会返回一个完整的响应内容,并在 Response Headers 中添加新的 Last-Modified 值;否则,返回如上图的 304 响应,Response Headers 不会再添加 Last-Modified 字段。
Etag是一个唯一标识字符串,每次文件修改后服务器端就会生成一个新的 Etag,这个标识字符串可以是基于文件内容编码的,只要文件内容不同,它们对应的 Etag 就是不同的。再次请求资源时,Request Header 会带上 If-Modified-Since,询问 Etag 是否变动
Etag 比 Last-Modified 优先级更高。
补充
Expires 缺点:
返回的到期时间是服务器端的时间,如果客户端的时间与服务器的时间相差很大,容易产生误差。
Last-Modified 缺点:
修改文件,但文件的内容未改变。服务器端并不清楚我们是否真正改变了文件,它仍然通过最后编辑时间进行判断。因此这个资源在再次被请求时,会被当做新资源,进而引发一次完整的响应。
当我们修改文件的速度过快时(比如花了 100ms 完成了改动),由于 If-Modified-Since 只能检查到以秒为最小计量单位的时间差,它感知不到这个改动的。
Etag 缺点:
Etag 的生成过程需要服务器额外付出开销,会影响服务端的性能。
TCP/IP四层协议体系结构
1.应用层(域名系统DNS、文件传输协议FTP、简单邮件传送协议SMTP、超文本传输协议HTTP、简单网络管理协议SNMP、远程登录协议Telnet)
2.运输层(TCP、UDP)
3.网际层(IP、ICMP、ARP、RARP)
4.网络接口层
五层体系结构
1.应用层
2.运输层
3.网络层
4.数据链路层
5.物理层
OSI七层协议模型
1.应用层(Application)(TELNET,HTTP,FTP,NFS,SMTP)
2.表示层(Presentation)(加密,ASCII)
3.会话层(Session)(RPC,SQL)
4.传输层(Transport)(TCP,UDP,SPX)
5.网络层(Network)(IP,IPX)
6.数据链路层(Data Link)(ATM,FDDI)
7.物理层(Physical)(Rj45,802.3)
HTTP请求报文主要包括请求行、请求头部以及请求的数据(实体)三部分。
请求行由方法字段(GET、POST、PUT、DELETE)、URL字段和HTTP协议版本字段组成。
请求头部
Connection标头:连接管理
Host标头:指定请求资源的主机
Range标头:请求实体的字节范围
User-Agent标头:包含发出请求的用户信息
Accept标头:首选的媒体类型
Accept-Language标头:首选的自然语言
HTTP响应报文分为状态行、首部行、实体三部分。
状态行包括三个字段:协议版本、状态码与原因短语。
响应首部
Date标头:消息产生的时间
Age标头:(从最初创建开始)响应持续时间
Server标头: 向客户端标明服务器程序名称和版本
ETag标头:不透明验证者
Location标头:URL备用的位置
Content-Length标头:实体的长度
Content-Type标头:实体的媒体类型
本质区别:GET 产生一个 TCP 数据包;POST 产生两个 TCP 数据包。
GET 方式的请求,浏览器会把 http header 和 data 一并发送出去,服务器响应 200(返回数据);而对于 POST,浏览器先发送 header,服务器响应 100(continue),浏览器再发送 data,服务器响应 200(返回数据)。
-
GET 在浏览器回退时是无害的,而 POST 会再次提交请求。
-
GET 产生的 URL 地址可以被 Bookmark,而 POST 不可以。
-
GET 请求会被浏览器主动 cache,而 POST 不会,除非手动设置。
-
GET 请求只能进行 URL 编码,而 POST 支持多种编码方式。
-
GET 请求参数会被完整保留在浏览器历史记录里,而 POST 中的参数不会被保留。
-
GET 请求在 URL 中传送的参数是有长度限制的,而 POST 么有。对参数的数据类型,