概览
关于这个问题,我看过很多文章,每个人分析的方法与总结的步骤都不相同。我这里按照自己的理解把过程分为了十个部分。因为我主要学习后端,所以最后几步前端的内容略写了。
一、URL解析
二、DNS域名解析
三、建立TCP连接
四、发送HTTP请求
五、访问重定向301/302(非必须)
六、服务器处理请求
七、返回响应结果
八、断开TCP连接
九、浏览器解析HTML
十、浏览器渲染界面
一、URL 解析
什么是URL?
URL(Uniform Resource Locator),统一资源定位符,用于定位互联网上资源,俗称网址。
比如 http://www.w3school.com.cn/html/index.asp,遵守以下的语法规则:
scheme://host.domain:port/path/filename
各部分解释如下:
- scheme - 定义因特网服务的类型。常见的协议有http、https、ftp、file,其中最常见的类型是 http,而https则是进行加密的网络传输。
- host - 定义域主机(http 的默认主机是 www)
- domain - 定义因特网域名,比如 w3school.com.cn
- port - 定义主机上的端口号(http 的默认端口号是 80)
- path - 定义服务器上的路径(如果省略,则文档必须位于网站的根目录中)。
- filename - 定义文档/资源的名称
扩展:HTTPS协议
我不知道把HTTPS放在这个部分是否合适,但是放在这里好像又说的过去。HTTP报文是包裹在TCP报文中发送的,服务器端收到TCP报文时会解包提取出HTTP报文。但是这个过程中存在一定的风险,HTTP报文是明文,如果中间被截取的话会存在一些信息泄露的风险。那么在进入TCP报文之前对HTTP做一次加密就可以解决这个问题了。HTTPS协议的本质就是HTTP + SSL(or TLS)。在HTTP报文进入TCP报文之前,先使用SSL对HTTP报文进行加密。从网络的层级结构看它位于HTTP协议与TCP协议之间。
关于HTTPS详细请看我另一篇博文:https://blog.csdn.net/CrankZ/article/details/81235216
扩展:什么是URL、URI、URN?
- URI(Uniform Resource Identifier)统一资源标识符
- URL(Uniform Resource Locator)统一资源定位符
- URN(Uniform Resource Name)统一资源名称
URL和URN 都属于 URI
二、DNS域名解析
DNS是什么
维基百科定义:域名系统(英文:Domain Name System,缩写:DNS)是互联网的一项服务。它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。
因为,我们更习惯于记住一个网站的已经,比如www.baidu.com,而不是记住它的IP地址。但是计算机最终访问的IP地址,而不是像www.baidu.com等链接。
所以DNS的作用就是你给DNS一个域名,它能帮你找到相应的IP地址。域名->DNS->IP地址
DNS缓存解析流程
- 浏览器缓存
- 系统缓存
- 路由器缓存
- ISP DNS缓存
- 递归查询
2.1浏览器缓存
浏览器会缓存DNS记录一段时间。 有趣的是,操作系统没有告诉浏览器储存DNS记录的时间,这样不同浏览器会储存个自固定的一个时间(2分钟到30分钟不等)。所以这时候浏览器就会检查域名是否在缓存当中。
比如如果要查看 Chrome 当中的缓存, 打开 chrome://net-internals/#dns :
2.2系统缓存
如果浏览器缓存中没有,浏览器会做一个系统调用(windows里是gethostbyname)。这样便可获得系统缓存中的记录进行查询。gethostbyname 函数在试图进行DNS解析之前首先检查域名是否在本地 Hosts 里,Hosts 的位置 不同的操作系统有所不同。
如果hosts文件没有,就会去查系统本地缓存的其他DNS 记录, 要查看系统的 DNS 缓存记录,以 windows 为例就是
ipconfig /displaydns
如果 gethostbyname 没有这个域名的缓存记录,也没有在 Hosts 里找到,它将会向 DNS 服务器发送一条 DNS 查询请求。DNS 服务器是由网络通信栈提供的,通常是本地路由器或者 ISP 的缓存 DNS 服务器,即下面的流程。
2.3路由器缓存
如果在系统缓存里面还是没找到对应的IP,那么接着会发送一个请求到路由器上,然后路由器在自己的路由器缓存上查找记录,路由器一般也存有DNS信息(缓存你上过的网站,所以有时路由器需要进行DNS刷新)
2.4ISP DNS缓存
如果本地路由器还是没有,这个请求就会被发送到ISP(注:Internet Service Provider,互联网服务提供商,就是那些拉网线到你家里的运营商,中国电信中国移动什么的),ISP也会有相应的ISP DNS服务器,一听中国电信就知道这个DNS服务器的规模肯定不会小,所以基本上都能在这里找得到。
ps:会跑到这里进行查询是因为你没有改动过”网络中心”的”ipv4”的DNS地址,万恶的运营上可以改动这个DNS服务器,换句话说他们可以让你的浏览器跳转到他们设定的页面上,这也就是人尽皆知的DNS和HTTP劫持。我们也可以自行修改DNS服务器来防止DNS被ISP污染。
2.5递归查询
如果在ISP DNS服务器还没有查到的话(一般情况下在ISP DNS服务器中都可以找到),你的ISP的DNS服务器会将请求发向根域名服务器进行搜索。根域名服务器就是面向全球的顶级DNS服务器,共有13台逻辑上的服务器,从A到M命名,真正的实体服务器则有几百台,分布于全球各大洲。所以这些服务器有真正完整的DNS数据库。
举个例子:
例如 “y.abc.com” 这个域名在 本地域名服务器上找不到
- 这时候本地域名服务器就会到根域名服务器查找,根域名服务器说这个是一个.com域名。
- 然后本地域名服务器就跑到管理.com域名的服务器上进行进一步查询,顶级域名服务器说是 .abc二级域名。
- 最后本地域名服务器再跑到管理 .abc这个二级域名所在的权限域名服务器,去查询 web这个三级域名的ip 地址。
所以域名结构为:三级域名.二级域名.一级域名。
这里的查询过程是包含递归查询和迭代查询的,客户端主机发送给本地服务器的查询是递归查询,而后面的三个查询是迭代查询。
如果到了根域名服务器还是找不到域名的对应信息,那只能说明一个问题:这个域名本来就不存在,它没有在网上正式注册过。或者卖域名的把它回收掉了(通常是因为欠费)。 这也就是为什么打开一个新页面会有点慢,因为本地没什么缓存,要这样递归地查询下去。
扩展:CDN内容分发
通常来说为了防止单个服务器访问压力过大,一个大型的网站,往往一个域名对应多个IP。
这时候就需要DNS的负载均衡问题。而CDN就可以解决这个问题
扩展:为什么需要DNS解析?
看了DNS的概念,有些同学可能觉着更加迷惑了,不要着急,咱们从DNS解析的过程方面来更好地了解它。要讲DNS的解析过程,首先咱们得先来了解一下计算机之间是怎样进行通信的。
扩展:两台电脑之间如何通信
有两台电脑A和B,A电脑想向B电脑发送一条信息,那该怎么办呢?
其实很简单,就像邮递员(假设为电脑A)要给某栋大楼内的某个房间的客户(假设为电脑B)送邮件一样,邮递员要想把邮件送到客户手上,那他必须知道客户的大楼名称(或者说地址)以及客户在这栋大楼内的房间号。在互联网的世界中也是一样,电脑A想向电脑B发送一条信息,电脑A就得知道电脑B的MAC地址和IP地址。
通过域名来获取IP地址的方法就是通过DNS解析,那MAC地址是什么呢?又怎么获取呢?
扩展:IP地址
IP地址有两种
- IPv4
- IPv6
IPv4地址由32位二进制数组成,为便于使用,常以XXX.XXX.XXX.XXX形式表现,每组XXX代表小于或等于255的10进制数。例如IP地址是208.80.152.2。
IPv4地址是唯一的。目前IPv4技术可能使用的IP地址最多可有4,294,967,296个(即232)。骤看可能觉得很难会用尽,但由于早期编码和分配上的问题,使很多区域的编码实际上被空出或不能使用。加上互联网的普及,连接网络的各种设备都消耗大量IPv4地址资源。
导致IPv4的42亿个地址的分配最终于2011年2月3日用尽。
不过相应的科研组织已研究出128位的IPv6,其IP地址数量最高可达3.402823669 × 1038个,届时每个人家居中的每件电器,每件对象,甚至地球上每一粒沙子都可以拥有自己的IP地址。
详细请看:https://en.wikipedia.org/wiki/IP_address
扩展:MAC地址
以太网规定,连入网络的所有设备,都必须具有“网卡”接口。数据包必须是从一块网卡,传送到另一块网卡。网卡的地址,就是数据包的发送地址和接收地址,这叫做MAC地址。
就是说要想上网就得有块叫做“网卡”的东西,电脑的网卡很好理解,大家经常接触;而像路由器,交换机,手机,平板等联网的设备都有“网卡”这个东西。而两台设备(也可以理解为电脑)之间的通信就相当于两块网卡之间的通信,而这个网卡就是MAC地址,MAC地址就相当于“送邮件”例子中的客户房间号(啰嗦了一下,怕新手看不懂)。
而每块网卡出厂的时候,都有一个全世界独一无二的MAC地址,长度是48个二进制位,通常用12个十六进制数表示。
前6个十六进制数是厂商编号,后6个是该厂商的网卡流水号。有了MAC地址,就可以定位网卡和数据包的路径了。
至于IP地址就不用再补充了吧,既然学计算机了,肯定知道IP地址。IP地址就相当于“送邮件”例子中的大楼名称(或者说地址)。
总结:A电脑想向B电脑发送一条信息,首先A电脑要知道B电脑的MAC地址和IP地址,这其中IP地址一般是已知的,而MAC地址是未知的。这时候就需要通过ARP协议来确定B电脑的MAC地址,只要拿到了电脑B的IP地址和MAC地址,两台电脑就可以通信了。
扩展:关于ARP
简单讲DNS是通过域名找IP,域名->DNS->IP
ARP就是通过IP找MAC,IP->ARP->MAC
关于ARP详细请看:
http://www.ruanyifeng.com/blog/2012/05/internet_protocol_suite_part_i.html
https://en.wikipedia.org/wiki/Address_Resolution_Protocol
https://cizixs.com/2017/07/31/arp-protocol/
三、建立TCP连接
概述
3.1TCP三次握手
3.2TLS/SSL握手(非必须)
TCP 报文段
先查看一下 TCP 头部的信息,如下图:
只介绍几个这里要用到的。序列号、确认号,标识:SYN,ACK,FIN。
- 序列号(sequence number):TCP 是面向字节流的,是 TCP 收发两端发送数据时所需,表示当然 TCP 段的第一个数据字节在整个数据流中的位置。也可以表示当前发送了多少数据。当前 seq - INS(初始 seq)
- 确认号(acknowledgement number):发送端发送 TCP 数据包到另一端后,接收端通过确认号来通知发送端接收成功了多少数据。即表示发送端成功发送了多少数据。后面简称为 ackn。
- SYN:同步标识,通常用来建立连接。在“三次握手”的前两次出现。TCP 协议规定,SYN = 1 时,当前 TCP 段不能携带其他有效数据。
- ACK:确认标识,接收端确认接收到数据。TCP 协议规定,只有 ACK = 1 时有效,即确认号信息才会包含在 TCP 段内,反正为 0。
- FIN:结束标识。表示双方数据发送完成,跟 SYN 类似,属于行为标识。也是 FIN = 1 时,TCP 段内不能包含其他主体数据。
通过标识符就可以推断出处于 TCP 连接的所处位置。比如 SYN = 1,ACK = 0,一定就是握手第一阶段,SYN = 1,ACK = 1,就是握手第二阶段,只剩 ACK,就是第三阶段。同样 FIN 就是断开阶段。
3.1TCP三次握手
上面报文的发送和接受过程在 TCP 连接的三次握手过程中会发生很多次:
- Client首先发送一个连接试探,ACK=0 表示确认号无效,SYN = 1 表示这是一个连接请求或连接接受报文,同时表示这个数据报不能携带数据,seq = x 表示Client自己的初始序号(seq = 0 就代表这是第0号包),这时候Client进入syn_sent状态,表示客户端等待服务器的回复
- Server监听到连接请求报文后,如同意建立连接,则向Client发送确认。TCP报文首部中的SYN 和 ACK都置1 ,ack = x + 1表示期望收到对方下一个报文段的第一个数据字节序号是x+1,同时表明x为止的所有数据都已正确收到(ack=1其实是ack=0+1,也就是期望客户端的第1个包),seq = y 表示Server 自己的初始序号(seq=0就代表这是服务器这边发出的第0号包)。这时服务器进入syn_rcvd,表示服务器已经收到Client的连接请求,等待client的确认。
- Client收到确认后还需再次发送确认,同时携带要发送给Server的数据。ACK 置1 表示确认号ack= y + 1 有效(代表期望收到服务器的第1个包),Client自己的序号seq= x + 1(表示这就是我的第1个包,相对于第0个包来说的),一旦收到Client的确认之后,这个TCP连接就进入Established状态,就可以发起http请求了。
扩展:为什么需要三次握手,而不是两次或四次?
既然总结了TCP的三次握手,那为什么非要三次呢?怎么觉得两次就可以完成了。那TCP为什么非要进行三次连接呢?在谢希仁的《计算机网络》中是这样说的:
为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。
在书中同时举了一个例子,如下:
已失效的连接请求报文段”的产生在这样一种情况下:
因为:A发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达B。
所以:因为已经过了有效时间,所以这是一个已失效的报文段。
然而:B收到此失效的连接请求报文段后,就误认为是A再次发出的一个新的连接请求。于是就向A发出确认报文段,同意建立连接。假设采用“两次握手”,那么只要B发出确认,就已经进行了两次连接,所以新的连接就建立了。
但是:但是由于现在A并没有发出建立连接的请求(因为那个请求是以前发的,现在A甚至都可能关机了),所以不会理睬B的确认,也不会向B发送数据。但已经进行了“两次握手”,所以B以为新的运输连接已经建立,并一直等待A发来数据。
结果:B的连接已经建立,一直在等待A的消息,但A根本不在。这样就造成了资源的浪费。
而采用“三次握手”的办法可以防止上述现象发生。例如在刚才的情况下,假如采用“三次握手”的话,A就不会向B的确认发出确认,B由于收不到确认,就不会建立连接。
这就很明白了,防止了服务器端的一直等待而浪费资源。
引用知乎上的别人引用的一个回答,从另外一个角度阐释:
在Google Groups的TopLanguage中看到一帖讨论TCP“三次握手”觉得很有意思。贴主提出“TCP建立连接为什么是三次握手?”的问题,在众多回复中,有一条回复写道:“这个问题的本质是, 信道不可靠, 但是通信双发需要就某个问题达成一致. 而要解决这个问题, 无论你在消息中包含什么信息, 三次通信是理论上的最小值. 所以三次握手不是TCP本身的要求, 而是为了满足"在不可靠信道上可靠地传输信息"这一需求所导致的. 请注意这里的本质需求,信道不可靠, 数据传输要可靠. 三次达到了, 那后面你想接着握手也好, 发数据也好, 跟进行可靠信息传输的需求就没关系了. 因此,如果信道是可靠的, 即无论什么时候发出消息, 对方一定能收到, 或者你不关心是否要保证对方收到你的消息, 那就能像UDP那样直接发送消息就可以了.”。这可视为对“三次握手”目的的另一种解答思路。
举个例子
拿寄快递举个例子
三次握手的情况
- 你:你发微信给快递小哥,“快递小哥在吗?我要寄快递,可以来我家取快递吗?”
- 快递小哥:收到,你在家吗?在家我就去
- 你:在家,你来吧
结果:OK,然后快递小哥来拿快递
为什么要三次,我平时聊微信都是两次就开始聊了?
你:快递小哥在吗?来拿快递
快递小哥:好的,这就去
这两次连接不就建立了?没啥问题啊?为啥非要三次呢?
因为有异常情况
两次握手
1.你:快递小哥在吗?来我家拿快递
但是这时候,由于某种原因(比如网络延迟),消息没有及时到达,第二天消息才送达
2.快递小哥(第二天):收到了,我这就去
结果:连接建立成功,但是你并不在家,然后快递小哥一直在等你,没办法拿到你要寄的快递,造成了资源的浪费。
为了避免这种意外情况,所以要采用“三次握手”。
三次握手
你:快递小哥在吗?来我家拿快递
快递小哥(第二天):收到,你在家吗?在家我就去
你(第二天):没有回应
结果:快递小哥没有收到你的确认,所以连接建立失败,避免了资源的浪费。
为什么不是四次或者以上?
三次可以,为什么还多加几次???不怕资源浪费?家里有矿?
关于三次握手详细请看我另一篇博文:https://blog.csdn.net/CrankZ/article/details/81263761
3.2TLS/SSL握手(非必须)
只有在HTTPS的时候才会有这个流程
如果是HTTPS的,那么就会在TCP三次握手之后,再多一层 TLS 握手,具体握手的流程如下:
TLS/SSL握手流程
- Hello – 握手开始于客户端发送Hello消息。包含服务端为了通过SSL连接到客户端的所有信息,包括客户端支持的各种密码套件和最大SSL版本。服务器也返回一个Hello消息,包含客户端需要的类似信息,包括到底使用哪一个加密算法和SSL版本。
- 证书交换 – 现在连接建立起来了,服务器必须证明他的身份。这个由SSL证书实现,像护照一样。SSL证书包含各种数据,包含所有者名称,相关属性(域名),证书上的公钥,数字签名和关于证书有效期的信息。客户端检查它是不是被CA验证过的。注意服务器被允许需求一个证书去证明客户端的身份,但是这个只发生在敏感应用。
- 密钥交换 – 先使用RSA非对称公钥加密算法(客户端生成一个对称密钥,然后用SSL证书里带的服务器公钥将改对称密钥加密。随后发送到服务端,服务端用服务器私钥解密,到此,握手阶段完成。)或者DH交换算法在客户端与服务端双方确定一将要使用的密钥,这个密钥是双方都同意的一个简单,对称的密钥,这个过程是基于非对称加密方式和服务器的公钥/私钥的。
- 加密通信 – 在服务器和客户端加密实际信息是用到对称加密算法,用哪个算法在Hello阶段已经确定。对称加密算法用对于加密和解密都很简单的密钥,这个密钥是基于第三步在客户端与服务端已经商议好的。与需要公钥/私钥的非对称加密算法相反。
HTTPS相比于HTTP,虽然提供了安全保证,但是势必会带来一些时间上的损耗,如握手和加密等过程,是否使用HTTPS需要根据具体情况在安全和性能方面做出权衡。
HTTPS在传输数据之前需要客户端与服务器进行一个握手(TLS/SSL握手),在握手过程中将确立双方加密传输数据的密码信息。TLS/SSL使用了非对称加密,对称加密以及hash等。
详细请看:http://www.ruanyifeng.com/blog/2014/02/ssl_tls.html
https://imququ.com/post/optimize-tls-handshake.html
扩展:TCP与UDP区别
TCP是面向连接的协议,UDP是无连接协议
TCP 发送数据前使用三次握手建立连接,UDP 发送数据前不需要建立连接。
TCP可靠,UDP不可靠
TCP 丢包会自动重传,UDP 不会(任何必需的可靠性必须由应用层来提供)。 TCP 可靠性由三个机制保证:1. 序号(TCP 报文的序号)2. 确认(ACK 机制)3. 重传(超时或者冗余的 ACK)
TCP有序,UDP无序
消息在传输过程中可能会乱序,后发送的消息可能会先到达,TCP 会对其进行重新排序,UDP 不会。
TCP有流量控制(拥塞控制),UDP没有
TCP 协议的流量控制是基于滑窗协议实现的。 拥塞控制和流量控制不同,流量控制是点对点的通信量抑制,抑制发送端发送速率,使得接收端来得及接收。
TCP传输慢,UDP传输快
因为 TCP 需要建立连接、保证可靠性和有序性,所以比较耗时。 这就是为什么视频流、广播电视、在线多媒体游戏等选择使用 UDP。
总结:
| TCP | UDP |
连接性 | 面向连接 | 无连接 |
可靠性 | 可靠 | 不可靠 |
有序性 | 有序 | 无序 |
拥塞控制 | 有 | 无 |
传输速度 | 慢 | 快 |
更详细请看:https://blog.csdn.net/zhang6223284/article/details/81414149
四、发送HTTP请求
请求报文
先上图
请求报文组成部分
- 报文首部(GET /index HTTP/1)
- 方法
- URL
- HTTP 版本
- 空行(CR+LF)
- 报文主体
请求头
下面是用Chrome访问百度,截取的请求报文头部信息
表格来源:https://zh.wikipedia.org/wiki/HTTP%E5%A4%B4%E5%AD%97%E6%AE%B5
请求头字段 | 说明 | 示例 |
Accept | 能够接受的回应内容类型(Content-Types)。 | Accept: text/plain |
Accept-Charset | 能够接受的字符集 | Accept-Charset: utf-8 |
Accept-Encoding | 能够接受的编码方式列表。 | Accept-Encoding: gzip, deflate |
Accept-Language | 能够接受的回应内容的自然语言列表。 | Accept-Language: en-US |
Accept-Datetime | 能够接受的按照时间来表示的版本 | Accept-Datetime: Thu, 31 May 2007 20:35:00 GMT |
Authorization | 用于超文本传输协议的认证的认证信息 | Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
Cache-Control | 用来指定在这次的请求/响应链中的所有缓存机制 都必须 遵守的指令 | Cache-Control: no-cache |
Connection | 该浏览器想要优先使用的连接类型 | Connection: keep-alive Connection: Upgrade |
Cookie | 之前由服务器通过 Set- Cookie (下文详述)发送的一个 超文本传输协议Cookie | Cookie: $Version=1; Skin=new; |
Content-Length | 以 八位字节数组 (8位的字节)表示的请求体的长度 | Content-Length: 348 |
Content-MD5 | 请求体的内容的二进制 MD5 散列值,以 Base64 编码的结果 | Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ== |
Content-Type | 请求体的 多媒体类型 (用于POST和PUT请求中) | Content-Type: application/x-www-form-urlencoded |
Date | 发送该消息的日期和时间(按照 RFC 7231 中定义的"超文本传输协议日期"格式来发送) | Date: Tue, 15 Nov 1994 08:12:31 GMT |
Expect | 表明客户端要求服务器做出特定的行为 | Expect: 100-continue |
From | 发起此请求的用户的邮件地址 | From: user@example.com |
Host | 服务器的域名(用于虚拟主机 ),以及服务器所监听的传输控制协议端口号。如果所请求的端口是对应的服务的标准端口,则端口号可被省略。 自超文件传输协议版本1.1(HTTP/1.1)开始便是必需字段。 | Host: en.wikipedia.org:80 Host: en.wikipedia.org |
If-Match | 仅当客户端提供的实体与服务器上对应的实体相匹配时,才进行对应的操作。主要作用时,用作像 PUT 这样的方法中,仅当从用户上次更新某个资源以来,该资源未被修改的情况下,才更新该资源。 | If-Match: "737060cd8c284d8af7ad3082f209582d" |
If-Modified-Since | 允许在对应的内容未被修改的情况下返回304未修改( 304 Not Modified ) | If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT |
If-None-Match | 允许在对应的内容未被修改的情况下返回304未修改( 304 Not Modified ),参考 超文本传输协议 的实体标记 | If-None-Match: "737060cd8c284d8af7ad3082f209582d" |
If-Range | 如果该实体未被修改过,则向我发送我所缺少的那一个或多个部分;否则,发送整个新的实体 | If-Range: "737060cd8c284d8af7ad3082f209582d" |
If-Unmodified-Since | 仅当该实体自某个特定时间已来未被修改的情况下,才发送回应。 | If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT |
Max-Forwards | 限制该消息可被代理及网关转发的次数。 | Max-Forwards: 10 |
Origin | 发起一个针对 跨来源资源共享 的请求(要求服务器在回应中加入一个‘访问控制-允许来源’('Access-Control-Allow-Origin')字段)。 | Origin: http://www.example-social-network.com |
Pragma | 与具体的实现相关,这些字段可能在请求/回应链中的任何时候产生多种效果。 | Pragma: no-cache |
Proxy-Authorization | 用来向代理进行认证的认证信息。 | Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
Range | 仅请求某个实体的一部分。字节偏移以0开始。 | Range: bytes=500-999 |
Referer [sic] | 表示浏览器所访问的前一个页面,正是那个页面上的某个链接将浏览器带到了当前所请求的这个页面。 | Referer: http://en.wikipedia.org/wiki/Main_Page |
TE | 浏览器预期接受的传输编码方式:可使用回应协议头 Transfer-Encoding 字段中的值; | TE: trailers, deflate |
User-Agent | 浏览器的浏览器身份标识字符串 | User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/21.0 |
Upgrade | 要求服务器升级到另一个协议。 | Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11 |
Via | 向服务器告知,这个请求是由哪些代理发出的。 | Via: 1.0 fred, 1.1 example.com (Apache/1.1) |
Warning | 一个一般性的警告,告知,在实体内容体中可能存在错误。 | Warning: 199 Miscellaneous warning |
常见的非标准请求字段
请求头字段 | 说明 | 示例 |
X-Requested-With | 主要用于标识 Ajax 及可扩展标记语言 请求。大部分的JavaScript框架会发送这个字段,且将其值设置为 XMLHttpRequest | X-Requested-With: XMLHttpRequest |
DNT | 请求某个网页应用程序停止跟踪某个用户。在火狐浏览器中,相当于X-Do-Not-Track协议头字段(自 Firefox/4.0 Beta 11 版开始支持)。Safari 和 Internet Explorer 9 也支持这个字段。2011年3月7日,草案提交IETF。[13] 万维网协会 的跟踪保护工作组正在就此制作一项规范。[14] | DNT: 1 (DNT启用) DNT: 0 (DNT被禁用) |
X-Forwarded-For | 一个事实标准 ,用于标识某个通过超文本传输协议代理或负载均衡连接到某个网页服务器的客户端的原始互联网地址 | X-Forwarded-For: client1, proxy1, proxy2 X-Forwarded-For: 129.78.138.66, 129.78.64.103 |
X-Forwarded-Host | 一个事实标准 ,用于识别客户端原本发出的 Host 请求头部[17]。 | X-Forwarded-Host: en.wikipedia.org:80 X-Forwarded-Host: en.wikipedia.org |
X-Forwarded-Proto | 一个事实标准,用于标识某个超文本传输协议请求最初所使用的协议。[19] | X-Forwarded-Proto: https |
Front-End-Https | 被微软的服务器和负载均衡器所使用的非标准头部字段。 | Front-End-Https: on |
X-Http-Method-Override | 请求某个网页应用程序使用该协议头字段中指定的方法(一般是PUT或DELETE)来覆盖掉在请求中所指定的方法(一般是POST)。当某个浏览器或防火墙阻止直接发送PUT 或DELETE 方法时(注意,这可能是因为软件中的某个漏洞,因而需要修复,也可能是因为某个配置选项就是如此要求的,因而不应当设法绕过),可使用这种方式。 | X-HTTP-Method-Override: DELETE |
X-ATT-DeviceId | 使服务器更容易解读AT&T设备User-Agent字段中常见的设备型号、固件信息。 | X-Att-Deviceid: GT-P7320/P7320XXLPG |
X-Wap-Profile | 链接到互联网上的一个XML文件,其完整、仔细地描述了正在连接的设备。右侧以为AT&T Samsung Galaxy S2提供的XML文件为例。 | x-wap-profile:http://wap.samsungmobile.com/uaprof/SGH-I777.xml |
Proxy-Connection | 该字段源于早期超文本传输协议版本实现中的错误。与标准的连接(Connection)字段的功能完全相同。 | Proxy-Connection: keep-alive |
X-Csrf-Token | 用于防止 跨站请求伪造。 辅助用的头部有 X-CSRFToken[26] 或 X-XSRF-TOKEN[27] | X-Csrf-Token: i8XNjC4b8KVok4uw5RftR38Wgp2BFwql |
HTTP请求方法
来源:https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol
根据HTTP标准,HTTP请求可以使用多种请求方法。
HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法。
HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法。
HTTP请求方法 | 含义 | 请求报文主体 | 响应报文主体 | 安全 | 幂等性 | 可缓存 |
GET | 用于获取资源,不会对原文件有影响。没有请求实体 | Optional | Yes | Yes | Yes | Yes |
HEAD | 类似于GET请求,用于获取头,返回的响应中没有具体的内容 | No | No | Yes | Yes | Yes |
POST | 可提交数据(例如提交表单或者上传文件)。 数据被包含在请求体中。 POST请求可能会导致新的资源的建立和/或已有资源的修改。 | Yes | Yes | No | No | Yes |
PUT | 传输文件 | Yes | Yes | No | Yes | No |
DELETE | 删除文件 | No | Yes | No | Yes | No |
CONNECT | HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。 | Yes | Yes | No | No | No |
OPTIONS | 查看服务器支持的方法。 | Optional | Yes | Yes | Yes | No |
TRACE | 追踪路径,主要用于测试或诊断。 | No | Yes | Yes | Yes | No |
PATCH | 用于将局部修改应用到资源。 | Yes | Yes | No | No | No |
扩展:GET和POST有什么区别?
来源:http://www.w3school.com.cn/tags/html_ref_httpmethods.asp
| GET | POST |
后退按钮/刷新 | 无害 | 数据会被重新提交(浏览器应该告知用户数据会被重新提交)。 |
书签 | 可收藏为书签 | 不可收藏为书签 |
缓存 | 能被缓存 | 不能缓存 |
编码类型 | application/x-www-form-urlencoded | application/x-www-form-urlencoded 或 multipart/form-data。为二进制数据使用多重编码。 |
历史 | 参数保留在浏览器历史中。 | 参数不会保存在浏览器历史中。 |
对数据长度的限制 | 是的。当发送数据时,GET 方法向 URL 添加数据;URL 的长度是受限制的(URL 的最大长度是 2048 个字符)。 | 无限制。 |
对数据类型的限制 | 只允许 ASCII 字符。 | 没有限制。也允许二进制数据。 |
安全性 | 与 POST 相比,GET 的安全性较差,因为所发送的数据是 URL 的一部分。 在发送密码或其他敏感信息时绝不要使用 GET ! | POST 比 GET 更安全,因为参数不会被保存在浏览器历史或 web 服务器日志中。 |
可见性 | 数据在 URL 中对所有人都是可见的。 | 数据不会显示在 URL 中。 |
更详细请看https://www.zhihu.com/question/28586791
HTTP版本
超文本传输协议已经演化出了很多版本,它们中的大部分都是向下兼容的。在 RFC 2145 中描述了HTTP版本号的用法。客户端在请求的开始告诉服务器它采用的协议版本号,而后者则在响应中采用相同或者更早的协议版本。
HTTP/0.9
已过时。只接受GET一种请求方法,没有在通讯中指定版本号,且不支持请求头。由于该版本不支持POST方法,因此客户端无法向服务器传递太多信息。
HTTP/1.0
这是第一个在通讯中指定版本号的HTTP协议版本,至今仍被广泛采用,特别是在代理服务器中。
HTTP/1.1
持久连接被默认采用,并能很好地配合代理服务器工作。还支持以管道方式在同时发送多个请求,以便降低线路负载,提高传输速度。
HTTP/1.1相较于HTTP/1.0协议的区别主要体现在:
- 缓存处理
- 带宽优化及网络连接的使用
- 错误通知的管理
- 消息在网络中的发送
- 互联网地址的维护
- 安全性及完整性
HTTP/2
HTTP/2标准于2015年5月以RFC 7540正式发表。HTTP/2的标准化工作由Chrome、Opera、Firefox、Internet Explorer 11、Safari、Amazon Silk及Edge等浏览器提供支持。
HTTP2.0与HTTP1.1的区别
- HTTP/2采用二进制格式而非文本格式
- HTTP/2是完全多路复用的,而非有序并阻塞的——只需一个连接即可实现并行
- 使用报头压缩,HTTP/2降低了开销
- HTTP/2让服务器可以将响应主动“推送”到客户端缓存中
关于HTTP各个版本之间的区别,请看我另一篇博文:https://blog.csdn.net/CrankZ/article/details/81239654
Content-Type?
Content-Type表明信息类型,用于定义网络文件的类型和网页的编码,只要是在网上传播的HTTP信息,都带有Content-Type头,决定浏览器将以什么形式、什么编码读取这个文件。默认值为" text/plain"。它包含了主要类型(primary type)和次要类型(subtype)两个部分,两者之间用"/"分割。主要类型有9种,分别是application、audio、example、image、message、model、multipart、text、video。每一种主要类型下面又有许多种次要类型,常见的有:
- text/plain:纯文本,文件扩展名.txt
- text/html:HTML文本,文件扩展名.htm和.html
- image/jpeg:jpeg格式的图片,文件扩展名.jpg
- image/gif:GIF格式的图片,文件扩展名.gif
- audio/x-wave:WAVE格式的音频,文件扩展名.wav
- audio/mpeg:MP3格式的音频,文件扩展名.mp3
- video/mpeg:MPEG格式的视频,文件扩展名.mpg
- application/zip:PK-ZIP格式的压缩文件,文件扩展名.zip
五、访问重定向301/302(非必须)
注意:这一步不是必须的,通常会出现在我们把网址前面的” www.”去掉之后
我们日常访问网站的时候,通常为了方便会把网址的前” www.”省去,而直接输入网址
比如www.baidu.com我们会直接输入baidu.com,当然,这样访问肯定是没问题的。但是对于搜索引擎来说www.baidu.com与baidu.com却是两个不同的网站。
比如 www.baidu.com -> baidu.com
我们直接访问baidu.com的话,打开Chrome控制台
可以很明显的看出,虽然我们输入的是没有3w的 baidu.com但是服务器自动重定向为了带3w 的www.baidu.com
为什么搜索引擎会把带www与不带www的网站区别对待呢?
因为www.baidu.com是三级域名
baidu.com是二级域名(在这里一级域名是.com)
而百度的三级域名有很多,比如
百度新闻news.baidu.com
百度地图map.baidu.com
明显的,百度新闻与百度地图不是同一个网站。
也就是说在搜索引擎眼里www与这里的news或map没有区别,都是三级域名,既然是三级域名,也就会把它当作不同的网站
为什么要重定向?
为什么服务器一定要重定向而不是直接发会用户想看的网页内容呢?
其中一个原因跟搜索引擎排名有关。对于搜索引擎来说 www.baidu .com和baidu.com是不同的站点。
结果就是虽然用户访问的内容是相同的,但是搜索引擎却认为访问量是分开的,这就会导致这个网站在搜索引擎的排名下降。
不过搜索引擎知道301永久重定向是什么意思,我们加上这个重定向,浏览器把访问带www的和不带www的地址归到同一个网站排名下。
还有一个原因是会增加缓存的难度。当一个页面有好几个名字时,它可能会在缓存里出现好几次。
301和302的区别
通过上面的例子可以看到访问baidu.com的时候浏览器状态码是302。
我们再来访问一下google.com
可以看到Google的状态码是301
301和302状态码都表示重定向,就是说浏览器在拿到服务器返回的这个状态码后会自动跳转到一个新的URL地址,这个地址可以从响应的Location首部中获取(用户看到的效果就是他输入的地址A瞬间变成了另一个地址B)——这是它们的共同点。
- 301:表示旧地址A的资源已经被永久地移除了(这个资源不可访问了),搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址;
- 302:表示旧地址A的资源还在(仍然可以访问),这个重定向只是临时地从旧地址A跳转到地址B,搜索引擎会抓取新的内容而保存旧的网址。 SEO302好于301
六、服务器处理请求
服务器端收到请求后的由web服务器(准确说应该是http服务器)处理请求,如Tomcat、Ngnix、IIS等。web服务器解析用户请求,知道了需要调度哪些资源文件,再通过相应的这些资源文件处理用户请求和参数,并调用数据库信息,最后将结果通过web服务器返回给浏览器客户端。
扩展:负载均衡
通常为了减少服务器的压力,用户的访问请求首先会经过一个负载均衡系统,然后由这个系统通过一些调度算法,分配给不同的服务器。
常见的负载均衡系统有Nginx、SpringCloud的里面的Ribbon
扩展:什么是反向代理?
想要理解什么是反向代理,要先理解什么是正向代理
正向代理
我们学生交作业,只要交给课代表,然后由课代表把作业交给老师。
这里就是正向代理,多个用户(学生)通过代理(课代表)把任务(作业)交给服务器(老师)
正向代理,代理的是客户端
反向代理
加入我们打电话给114,114后台肯定有很多接话员,但我们拨号的时候不需要考虑这么多,直接打114就行了,具体的114会分配给你一个不忙的接话员。作为用户,我们感受不到任何差别。这就是反向代理
反向代理,代理的是服务器
小结
正向代理代理客户端,反向代理代理服务器
关于反向代理的请看另一篇博文:https://blog.csdn.net/CrankZ/article/details/80800245
七、返回响应结果
响应报文
报文组成
下面是用Chrome访问百度的Response Headers
响应头
来源:https://zh.wikipedia.org/wiki/HTTP%E5%A4%B4%E5%AD%97%E6%AE%B5
响应头字段 | 说明 | 例子 |
Access-Control-Allow-Origin | 指定哪些网站可参与到跨来源资源共享过程中 | Access-Control-Allow-Origin: * |
Accept-Patch | 指定服务器支持的文件格式类型。 | Accept-Patch: text/example;charset=utf-8 |
Accept-Ranges | 这个服务器支持哪些种类的部分内容范围 | Accept-Ranges: bytes |
Age | 这个对象在代理缓存中存在的时间,以秒为单位 | Age: 12 |
Allow | 对于特定资源有效的动作。针对HTTP/405这一错误代码而使用 | Allow: GET, HEAD |
Cache-Control | 向从服务器直到客户端在内的所有缓存机制告知,它们是否可以缓存这个对象。其单位为秒 | Cache-Control: max-age=3600 |
Connection | 针对该连接所预期的选项 | Connection: close |
Content-Disposition[29] | 一个可以让客户端下载文件并建议文件名的头部。文件名需要用双引号包裹。 | Content-Disposition: attachment; filename="fname.ext" |
Content-Encoding | 在数据上使用的编码类型。参考 超文本传输协议压缩 。 | Content-Encoding: gzip |
Content-Language | 内容所使用的语言 | Content-Language: da |
Content-Length | 回应消息体的长度,以 字节 (8位为一字节)为单位 | Content-Length: 348 |
Content-Location | 所返回的数据的一个候选位置 | Content-Location: /index.htm |
Content-MD5 | 回应内容的二进制 MD5 散列,以 Base64 方式编码 | Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ== |
Content-Range | 这条部分消息是属于某条完整消息的哪个部分 | Content-Range: bytes 21010-47021/47022 |
Content-Type | 当前内容的MIME类型 | Content-Type: text/html; charset=utf-8 |
Date | 此条消息被发送时的日期和时间 | Date: Tue, 15 Nov 1994 08:12:31 GMT |
ETag | 对于某个资源的某个特定版本的一个标识符,通常是一个 消息散列 | ETag: "737060cd8c284d8af7ad3082f209582d" |
Expires | 指定一个日期/时间,超过该时间则认为此回应已经过期 | Expires: Thu, 01 Dec 1994 16:00:00 GMT |
Last-Modified | 所请求的对象的最后修改日期 | Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT |
Link | 用来表达与另一个资源之间的类型关系 | Link: </feed>; rel="alternate" |
Location | 用来 进行重定向,或者在创建了某个新资源时使用。 | Location: http://www.w3.org/pub/WWW/People.html |
P3P | 用于支持设置P3P策略,标准格式为“P3P:CP="your_compact_policy"”。 | P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info." |
Pragma | 与具体的实现相关,这些字段可能在请求/回应链中的任何时候产生多种效果。 | Pragma: no-cache |
Proxy-Authenticate | 要求在访问代理时提供身份认证信息。 | Proxy-Authenticate: Basic |
Public-Key-Pins | 用于缓解中间人攻击,声明网站认证使用的传输层安全协议证书的散列值 | Public-Key-Pins: max-age=2592000; pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g="; |
Refresh | 用于设定可定时的重定向跳转。右边例子设定了5秒后跳转至“http://www.w3.org/pub/WWW/People.html”。 | Refresh: 5; url=http://www.w3.org/pub/WWW/People.html |
Retry-After | 如果某个实体临时不可用,则,此协议头用来告知客户端日后重试。其值可以是一个特定的时间段(以秒为单位)或一个超文本传输协议日期。 |
|
Server | 服务器的名字 | Server: Apache/2.4.1 (Unix) |
Set-Cookie | HTTP cookie | Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1 |
Status | 通用网关接口 协议头字段,用来说明当前这个超文本传输协议回应的 状态 。 | Status: 200 OK |
Strict-Transport-Security | HTTP 严格传输安全这一头部告知客户端缓存这一强制 HTTPS 策略的时间,以及这一策略是否适用于其子域名。 | Strict-Transport-Security: max-age=16070400; includeSubDomains |
Trailer | 这个头部数值指示了在这一系列头部信息由由分块传输编码编码。 | Trailer: Max-Forwards |
Transfer-Encoding | 用来将实体安全地传输给用户的编码形式。当前定义的方法包括:分块(chunked)、compress、deflate、gzip和identity。 | Transfer-Encoding: chunked |
Upgrade | 要求客户端升级到另一个协议。 | Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11 |
Vary | 告知下游的代理服务器,应当如何对未来的请求协议头进行匹配,以决定是否可使用已缓存的回应内容而不是重新从原始服务器请求新的内容。 | Vary: * |
Via | 告知代理服务器的客户端,当前回应是通过什么途径发送的。 | Via: 1.0 fred, 1.1 example.com (Apache/1.1) |
Warning | 一般性的警告,告知在实体内容体中可能存在错误。 | Warning: 199 Miscellaneous warning |
WWW-Authenticate | 表明在请求获取这个实体时应当使用的认证模式。 | WWW-Authenticate: Basic |
X-Frame-Options | 点击劫持保护: deny:该页面不允许在 frame 中展示,即使是同域名内。 sameorigin:该页面允许同域名内在 frame 中展示。 allow-from uri:该页面允许在指定uri的 frame 中展示。 allowall:允许任意位置的frame显示,非标准值。 | X-Frame-Options: deny |
常见的非标准回应字段
字段名 | 说明 | 示例 |
X-XSS-Protection | 跨站脚本攻击 (XSS)过滤器 | X-XSS-Protection: 1; mode=block |
Content-Security-Policy, X-Content-Security-Policy, X-WebKit-CSP | 内容安全策略定义。 | X-WebKit-CSP: default-src 'self' |
X-Content-Type-Options | 唯一允许的数值为"nosniff",防止 Internet Explorer 对文件进行MIME类型嗅探。这也对 Google Chrome 下载扩展时适用。 | X-Content-Type-Options: nosniff |
X-Powered-By | 表明用于支持当前网页应用程序的技术(例如:PHP)(版本号细节通常放置在 X-Runtime 或 X-Version 中) | X-Powered-By: PHP/5.4.0 |
X-UA-Compatible | 推荐指定的渲染引擎(通常是向后兼容模式)来显示内容。也用于激活 Internet Explorer中的 Chrome Frame。 | X-UA-Compatible: IE=EmulateIE7 X-UA-Compatible: IE=edge |
X-Content-Duration | 指出音视频的长度,单位为秒。只受Gecko内核浏览器支持。 | X-Content-Duration: 42.666 |
HTTP状态码分类
HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用。HTTP状态码共分为5种类型:
表格来源:http://www.runoob.com/http/http-status-codes.html
分类 | 分类描述 |
1xx | 信息,服务器收到请求,需要请求者继续执行操作 |
2xx | 成功,操作被成功接收并处理 |
3xx | 重定向,需要进一步的操作以完成请求 |
4xx | 客户端错误,请求包含语法错误或无法完成请求 |
5xx | 服务器错误,服务器在处理请求的过程中发生了错误 |
HTTP状态码列表
表格来源:http://www.runoob.com/http/http-status-codes.html
状态码 | 状态码英文名称 | 中文描述 |
100 | Continue | 继续。客户端应继续其请求 |
101 | Switching Protocols | 切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议 |
200 | OK | 请求成功。一般用于GET与POST请求 |
201 | Created | 已创建。成功请求并创建了新的资源 |
202 | Accepted | 已接受。已经接受请求,但未处理完成 |
203 | Non-Authoritative Information | 非授权信息。请求成功。但返回的meta信息不在原始的服务器,而是一个副本 |
204 | No Content | 无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档 |
205 | Reset Content | 重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域 |
206 | Partial Content | 部分内容。服务器成功处理了部分GET请求 |
300 | Multiple Choices | 多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择 |
301 | Moved Permanently | 永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替 |
302 | Found | 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI |
303 | See Other | 查看其它地址。与301类似。使用GET和POST请求查看 |
304 | Not Modified | 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源 |
305 | Use Proxy | 使用代理。所请求的资源必须通过代理访问 |
306 | Unused | 已经被废弃的HTTP状态码 |
307 | Temporary Redirect | 临时重定向。与302类似。使用GET请求重定向 |
400 | Bad Request | 客户端请求的语法错误,服务器无法理解 |
401 | Unauthorized | 请求要求用户的身份认证 |
402 | Payment Required | 保留,将来使用 |
403 | Forbidden | 服务器理解请求客户端的请求,但是拒绝执行此请求 |
404 | Not Found | 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面 |
405 | Method Not Allowed | 客户端请求中的方法被禁止 |
406 | Not Acceptable | 服务器无法根据客户端请求的内容特性完成请求 |
407 | Proxy Authentication Required | 请求要求代理的身份认证,与401类似,但请求者应当使用代理进行授权 |
408 | Request Time-out | 服务器等待客户端发送的请求时间过长,超时 |
409 | Conflict | 服务器完成客户端的PUT请求是可能返回此代码,服务器处理请求时发生了冲突 |
410 | Gone | 客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置 |
411 | Length Required | 服务器无法处理客户端发送的不带Content-Length的请求信息 |
412 | Precondition Failed | 客户端请求信息的先决条件错误 |
413 | Request Entity Too Large | 由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个Retry-After的响应信息 |
414 | Request-URI Too Large | 请求的URI过长(URI通常为网址),服务器无法处理 |
415 | Unsupported Media Type | 服务器无法处理请求附带的媒体格式 |
416 | Requested range not satisfiable | 客户端请求的范围无效 |
417 | Expectation Failed | 服务器无法满足Expect的请求头信息 |
500 | Internal Server Error | 服务器内部错误,无法完成请求 |
501 | Not Implemented | 服务器不支持请求的功能,无法完成请求 |
502 | Bad Gateway | 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应 |
503 | Service Unavailable | 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中 |
504 | Gateway Time-out | 充当网关或代理的服务器,未及时从远端服务器获取请求 |
505 | HTTP Version not supported | 服务器不支持请求的HTTP协议的版本,无法完成处理 |
八、断开TCP连接
当资源通过TCP通道传输过来的时候,浏览器使用完之后就要断开通道了。
这时候就是四次挥手
第一次挥手
因此当主动方发送断开连接的请求(即FIN报文)给被动方时,仅仅代表主动方不会再发送数据报文了,但主动方仍可以接收数据报文。
第二次挥手
被动方此时有可能还有相应的数据报文需要发送,因此需要先发送ACK报文,告知主动方“我知道你想断开连接的请求了”。这样主动方就不会因为没有收到应答而重复发送断开连接的请求。
第三次挥手
被动方在处理完数据报文后,便发送给主动方FIN报文;这样可以保证数据通信正常可靠地完成。发送完FIN报文后,被动方进入LAST_ACK阶段(超时等待)。
第四挥手
主动方发送ACK报文进行连接中断的确认,被动方接收后,连接就正式中断了。
为什么断开要四次
对比 TCP 建立连接的时候,区别大概就是第二步拆成了两步。“三次握手”的时候确认 ACK 和同步 SYN 是一块返回的,断开连接则是分开发送,先发送 ACK 确认,再发送 FIN。这里主要是因为 B 端是被动断开的一方,A 发送完数据了,发送 FIN 表示我已经完事了,但是 B 不一定,也能还有数据会发送给 A。所以 B 会先 ACK 确认,然后当它真的没有数据要发送了,才会执行 FIN。
这种情况主要是由于 TCP 全双工传输的特性决定的。什么是全双工?也就是说连接是双向的,所以连接的取消也是两者都取消才算真的取消。所以 TCP 的数据传输也是这样,两端同时可以向对方发送数据,所以当 A 要断开连接的时候,B 接收到 FIN 表示没有数据会发来了,但是B可能还有数据需要发送,为了数据不丢失,即采用先确定后断开的方式。
举个例子
要取消连接
假如说挥手只有三次:
- A:我要结束连接。
- B:等等啊,我还有数据要传给你
- A:没办法,我只有三次握手,告辞
结果:
在第二步,B有可能还有数据要传给A,但是A直接就结束了,造成了数据的丢失。
四次
1.A:我要结束连接
2.B:好的,我知道了。我还有点数据要传给你
(B对A传数据·····)
3.B:数据传完了,你可以结束了,我也要结束
4.A:OK,大家都结束了,拜拜
结果:两者连接都结束了,连接真的结束了。
关于三次握手与四次挥手详细看我另一篇博文:https://blog.csdn.net/CrankZ/article/details/81263761
Tips:浏览器解析并渲染的内容也很多,因为我主要学习后端,这里就不详细写了
九、浏览器解析HTML
准确地说,浏览器需要加载解析的不仅仅是HTML,还包括CSS、JS。以及还要加载图片、视频等其他媒体资源。
浏览器通过解析HTML,生成DOM树,解析CSS,生成CSS规则树,然后通过DOM树和CSS规则树生成渲染树。渲染树与DOM树不同,渲染树中并没有head、display为none等不必显示的节点。
要注意的是,浏览器的解析过程并非是串连进行的,比如在解析CSS的同时,可以继续加载解析HTML,但在解析执行JS脚本时,会停止解析后续HTML,这就会出现阻塞问题,关于JS阻塞相关问题,这里不过多阐述,后面会单独开篇讲解。
十、浏览器渲染界面
浏览器在收到HTML,CSS,JS文件后,它是如何把页面呈现到屏幕上的?下图对应的就是WebKit渲染的过程。
浏览器是一个边解析边渲染的过程。首先浏览器解析HTML文件构建DOM树,然后解析CSS文件构建渲染树,等到渲染树构建完成后,浏览器开始布局渲染树并将其绘制到屏幕上。这个过程比较复杂,涉及到两个概念: reflow(回流)和repain(重绘)。DOM节点中的各个元素都是以盒模型的形式存在,这些都需要浏览器去计算其位置和大小等,这个过程称为relow;当盒模型的位置,大小以及其他属性,如颜色,字体,等确定下来之后,浏览器便开始绘制内容,这个过程称为repaint。页面在首次加载时必然会经历reflow和repaint。reflow和repaint过程是非常消耗性能的,尤其是在移动设备上,它会破坏用户体验,有时会造成页面卡顿。所以我们应该尽可能少的减少reflow和repaint。
参考
https://www.zhihu.com/question/19649178
https://www.xuecaijie.com/it/157.html
http://zining.me/2017/07/13/how-it-works-when-enter-a-url
https://www.yuque.com/serifx/fex/dwb1ee
https://www.jianshu.com/p/c1dfc6caa520
https://www.jianshu.com/p/8a40f99da882
https://www.linux178.com/web/httprequest.html
https://kebingzao.com/2018/07/01/what-happens-when-you-navigate-to-a-url/
https://jaminzhang.github.io/network/The-Difference-Between-TCP-And-UDP-Protocol/