https://zhuanlan.zhihu.com/p/24913080?utm_source=qq&utm_medium=social&utm_oi=667009035568680960
首先从一个问题入手,当我们在浏览器输入url时,浏览器做了哪些事情。
1.首先Chrome搜索自身的DNS缓存。
2.读取硬盘中的host文件,里面记录着域名到ip地址的映射关系(如果1没有找到)
3.浏览器向宽带运营服务商或域名服务器发起DNS解析请求(如果12都没有找到)
4.拿到ip地址后,浏览器就向该ip地址所在服务器建立TCP连接(三次握手)
5.建立连接后,浏览器向服务器发起http请求(比如访问百度首页,就向服务器发起HTTP中的get请求)
6.服务器收到请求后,根据路径参数,经过后台一些处理后,把处理的结果返回给浏览器(如果是百度首页,就把完整的HTML页面代码返回给浏览器)
7.浏览器拿到完整的HTML页面代码,内核和js引擎就会解析和渲染这个页面,里面的js,css,图片等静态资源也通过一个个HTTP请求进行加载
8.浏览器根据拿到的资源对页面进行渲染,最终把完整页面呈现给用户
9.如果浏览器没有后续请求,就会跟服务器端发起TCP断开(四次挥手)
补充:HTML页面加载和解析流程
- 用户输入网址(假设是个html页面,并且是第一次访问),浏览器向服务器发出请求,服务器返回html文件。
- 浏览器开始载入html代码,发现<head>标签内有一个<link>标签引用外部CSS文件。
- 浏览器又发出CSS文件的请求,服务器返回这个CSS文件。
- 浏览器继续载入html中<body>部分的代码,并且CSS文件已经拿到手了,可以开始渲染页面了。
- 浏览器在代码中发现一个<img>标签引用了一张图片,向服务器发出请求。此时浏览器不会等到图片下载完,而是继续渲染后面的代码。
- 服务器返回图片文件,由于图片占用了一定面积,影响了后面段落的排布,因此浏览器需要回过头来重新渲染这部分代码。
- 浏览器发现了一个包含一行Javascript代码的<script>标签,赶快运行它。
- Javascript脚本执行了这条语句,它命令浏览器隐藏掉代码中的某个<style>(style.display=”none”)。杯具啊,突然就少了这么一个元素,浏览器不得不重新渲染这部分代码。
- 终于等到了</html>的到来,浏览器泪流满面……
- 等等,还没完,用户点了一下界面中的“换肤”按钮,Javascript让浏览器换了一下<link>标签的CSS路径。
- 浏览器召集了在座的各位<div><span><ul><li>们,“大伙儿收拾收拾行李,咱得重新来过……”,浏览器向服务器请求了新的CSS文件,重新渲染页面。
HTTP特性:
- HTTP是无连接无状态的
- HTTP一般构建于TCP/IP协议之上,默认端口号是80
补充:
一.无连接
1.每一个访问都是无连接,服务器挨个处理访问队列里的访问,处理完一个就关闭连接,这事儿就完了,然后处理下一个新的
2.无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接
二.无状态
1.协议对于事务处理没有记忆能力
2.对同一个url请求没有上下文关系
3.每次的请求都是独立的,它的执行情况和结果与前面的请求和之后的请求是无直接关系的,它不会受前面的请求应答情况直接影响,也不会直接影响后面的请求应答情况
4.服务器中没有保存客户端的状态,客户端必须每次带上自己的状态去请求服务器
三.TCP
TCP的传输数据的核心是在于将数据分为若干段并将每段数据按顺序标记。标记后的顺序可以以不同的顺序被另一方接收并集成回完整的数据。计算机对每一段数据的成功接收都会做出相应,确保所有数据的完整性。
HTTP可以分为两个部分: 请求和响应
HTTP请求:
HTTP定义了与服务器交互的四种方式,分别是GET,POST,PUT,DELETE。可以这么认为:一个URL地址对应一个网络上的资源,而HTTP中的get,post,put,delete对应着对这个资源的查询,修改,增添,删除4个操作
HTTP请求由3个部分组成,分别是:状态行,请求头,请求正文。
GET请求:
- 状态行由请求方式、路径和协议构成,各元素间用空格分隔。比如:
- GET、/books/?sex=man&name=Professional、HTTP/1.1
请求头提供一些参数比如:Cookie, 用户代理信息,主机名等等 - 请求正文放一些发送的数据,一般get请求会将参数放在url中,post请求把参数放在请求正文中。请求正文可以传一些json数据或字符串等。
get一般用于信息获取,它不会产生副作用,仅仅是获取资源信息,而post请求表示可能会修改服务器上的资源。
GET请求和POST请求的区别
1.请求参数位置不同,get在url中,而post在请求体中(但这只是一种约定,get请求中出现body也是被允许的)
2.由于url最大字符长度限制,导致get请求中参数数量是有限的
3.在涉及安全的请求比如:登录请求需要提交表单,而get请求一般用来获取静态资源
4.get请求可以被缓存,可以被存为书签,post请求可以被缓存,但不能被存为书签
补充:
https://mp.weixin.qq.com/s?__biz=MzI3NzIzMzg3Mw==&mid=100000054&idx=1&sn=71f6c214f3833d9ca20b9f7dcd9d33e4
在我大万维网世界中,TCP就像汽车,我们用TCP来运输数据,它很可靠,从来不会发生丢件少件的现象。但是如果路上跑的全是看起来一模一样的汽车,那这个世界看起来是一团混乱,送急件的汽车可能被前面满载货物的汽车拦堵在路上,整个交通系统一定会瘫痪。为了避免这种情况发生,交通规则HTTP诞生了。HTTP给汽车运输设定了好几个服务类别,有GET, POST, PUT, DELETE等等,HTTP规定,当执行GET请求的时候,要给汽车贴上GET的标签(设置method为GET),而且要求把传送的数据放在车顶上(url中)以方便记录。如果是POST请求,就要在车上贴上POST的标签,并把货物放在车厢里。当然,你也可以在GET的时候往车厢内偷偷藏点货物,但是这是很不光彩;也可以在POST的时候在车顶上也放一些数据,让人觉得傻乎乎的。HTTP只是个行为准则,而TCP才是GET和POST怎么实现的基本。
但是,我们只看到HTTP对GET和POST参数的传送渠道(url还是requrest body)提出了要求。“标准答案”里关于参数大小的限制又是从哪来的呢?
在我大万维网世界中,还有另一个重要的角色:运输公司。不同的浏览器(发起http请求)和服务器(接受http请求)就是不同的运输公司。 虽然理论上,你可以在车顶上无限的堆货物(url中无限加参数)。但是运输公司可不傻,装货和卸货也是有很大成本的,他们会限制单次运输量来控制风险,数据量太大对浏览器和服务器都是很大负担。业界不成文的规定是,(大多数)浏览器通常都会限制url长度在2K个字节,而(大多数)服务器最多处理64K大小的url。超过的部分,恕不处理。如果你用GET服务,在request body偷偷藏了数据,不同服务器的处理方式也是不同的,有些服务器会帮你卸货,读出数据,有些服务器直接忽略,所以,虽然GET可以带request body,也不能保证一定能被接收到哦。
好了,现在你知道,GET和POST本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。
GET和POST还有一个重大区别,简单的说:
GET产生一个TCP数据包;POST产生两个TCP数据包。
长的说:
对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。
也就是说,GET只需要汽车跑一趟就把货送到了,而POST得跑两趟,第一趟,先去和服务器打个招呼“嗨,我等下要送一批货来,你们打开门迎接我”,然后再回头把货送过去。
因为POST需要两步,时间上消耗的要多一点,看起来GET比POST更有效。因此Yahoo团队有推荐用GET替换POST来优化网站性能。但这是一个坑!跳入需谨慎。为什么?
- GET与POST都有自己的语义,不能随便混用。
- 据研究,在网络环境好的情况下,发一次包的时间和发两次包的时间差别基本可以无视。而在网络环境差的情况下,两次包的TCP在验证数据包完整性上,有非常大的优点。
- 并不是所有浏览器都会在POST中发送两次包,Firefox就只发送一次。
HTTP响应
和HTTP请求相似,也由三部分构成:状态行、响应头、响应正文
响应中包含一个状态码,用来表示服务器对客户端响应的结果
常见状态码:
200 OK 客户端请求成功。
301 Moved Permanently 请求永久重定向。
302 Moved Temporarily 请求临时重定向。
304 Not Modified 文件未修改,可以直接使用缓存的文件。
400 Bad Request 由于客户端请求有语法错误,不能被服务器所理解。
401 Unauthorized 请求未经授权,无法访问。
403 Forbidden 服务器收到请求,但是拒绝提供服务。服务器通常会在响应正文中给出不提供服务的原因。
404 Not Found 请求的资源不存在,比如输入了错误的URL。
500 Internal Server Error 服务器发生不可预期的错误,导致无法完成客户端的请求。
503 Service Unavailable 服务器当前不能够处理客户端的请求,在一段时间之后,服务器可能会恢复正常。
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status
一个完整的流程一般是这样的:
通常,由HTTP客户端发起一个请求,建立一个到服务器指定端口(默认是80端口)的TCP连接。HTTP服务器则在那个端口监听客户端发送过来的请求。一旦收到请求,服务器发送一个状态行,比如"HTTP/1.1 200 OK",和响应的消息,消息的消息体可能是请求的文件、错误消息、或其他一些信息。
HTTP头信息
以请求百度首页为例
HTTP请求头
以百度首页为例
- Accept: 指定客户端能接受的内容类型,如常见的text/html等,最后返回的百度首页也是个HTML文件
- Accept-Encoding: 表示浏览器有能力解码的编码类型
- Cache-Control: 指定请求和响应遵循的缓存机制(这里表示不需要缓存)
- Connection: 表示是否需要持久连接
- Cookie: 用于会话追踪
- Host: 请求的服务器网址
- User-Agent: 用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户端使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。
另外一些常见请求头
- Content-Length: 请求的内容长度
- Referer: 先前访问的网页地址,当前请求网页紧随其后,说明你是先前是从哪个网址点击访问到该页面的,如果没有则不填。
- Content-Type: 内容类型,get请求无该字段,post请求中常见的有application/x-www-form-urlencoded为普通表单提交,还有文件上传为multipart/form-data
HTTP响应头
还是以百度举例
前一个是自定义字段,HTTP 请求头中的字段是可以自定义的。https://blog.csdn.net/qq_42695697/article/details/84553669
Connection, Content-Encoding, Content-Type 和请求头的内容差不多,不再赘述。
- Date: 原始服务器消息发出的时间
- Last-Modified: 请求资源的最后修改时间
- Expires: 响应过期的日期和时间,如果下次访问在时间允许的范围内,可以不用重新请求,直接访问缓存。
- Set-Cookie: 设置Http Cookie,下次浏览器再次访问的时候会带上这个 Cookie 值。
- Server:服务器软件名称,常见的有 Apache 和 Nginx。
其它
会话追踪
- 会话:客户端向服务器端发起请求到服务端响应客户端请求的全过程。
- 会话跟踪:会话追踪指的是服务器对用户响应的监视。
为什么需要会话跟踪:
浏览器与服务器之间的通信是通过 HTTP 协议进行通信的,而 HTTP 协议是”无状态”的协议,它不能保存客户的信息,即一次响应完成之后连接就断开了,下一次的请求需要重新连接,这样就需要判断是否是同一个用户,所以才有会话跟踪技术来实现这种要求。
比如你在访问淘宝登录之后会持续追踪你的会话,记录你的购物车记录等等。
会话跟踪常用方法:
会话:客户端向服务器端发起请求到服务端响应客户端请求的全过程。
会话跟踪:会话追踪指的是服务器对用户响应的监视。
为什么需要会话跟踪:
浏览器与服务器之间的通信是通过 HTTP 协议进行通信的,而 HTTP 协议是”无状态”的协议,它不能保存客户的信息,即一次响应完成之后连接就断开了,下一次的请求需要重新连接,这样就需要判断是否是同一个用户,所以才有会话跟踪技术来实现这种要求。
比如你在访问淘宝登录之后会持续追踪你的会话,记录你的购物车记录等等。
会话跟踪常用方法:
- URL 重写:URL 重写技术就是在 URL 结尾添加一个附加数据以标识该会话,把会话 ID 通过 URL 的信息传递过去,以便在服务器进行识别不同的用户。
- 隐藏表单域:将会话ID添加到HTML表单元素中提交到服务器,此表单元素并不在客户端显示。
- Cookie:Cookie 是 Web 服务器发送给客户端的一小段信息,客户端请求时可以读取该信息发送给服务器端,进而进行用户的识别,对于客户端的每次请求,服务器都会将 Cookie 发送到客户端,客户端保存下来,以便下次使用。
客户端可以采用两种方式来保存这个 Cookie 对象,一种方式是保存在客户端内存中,称为临时 Cookie,浏览器关闭后这个 Cookie 对象将消失。
另外一种方式是保存在客户机的磁盘上,称为永久 Cookie。以后客户端只要访问该网站,就会将这个 Cookie 再次发送到服务器上,前提是这个 Cookie 在有效期内,这样就实现了对客户的跟踪。
Cookie 是可以被禁止的,当你打开 Chrome,在设置里面关闭 Cookie,那么你将再也无法登录淘宝页面。
- Session:在服务器端会创建一个 session 对象,产生一个 sessionID 来标识这个 session 对象,然后将这个 sessionID 放入到 Cookie 中发送到客户端,下一次访问时,sessionID 会发送到服务器,在服务器端进行识别不同的用户。
每一个用户都有一个不同的 session,各个用户之间是不能共享的,是每个用户所独享的,在 session 中可以存放信息。
Session的实现依赖于Cookie,如果Cookie被禁用,那么session也将失效。
补充:
Cookie、Session、LocalStorage
https://juejin.im/post/5bbc47a15188255c9e02edbd
https://www.cnblogs.com/cencenyue/p/7604651.html
Cookie机制
Session机制
session是一种服务度机制,类似散列表结构来存储用户数据
浏览器第一次向客户端发送请求时,服务器会自动生成一个session和sessionid
sessionid唯一标识这个session
服务器响应时把sessionid发送给浏览器
浏览器第二次向服务器发送请求时就会携带这个sessionid
服务器通过这个id找到对应的session获取用户数据
session和cookie区别
- session保存在服务器,cookie保存在客户端
- session中保存的时对象,cookie保存的是字符串
- session不能区分路径,同一个用户访问一个网站期间,所有的session在任何一个地方都可以访问
- cookie如果设置路径,则在某些地方不能访问
- session需要借助cookie才能正常工作,如果禁用cookie,session则失效
- 客户端会在发送请求的时候,自动将本地存活的cookie封装在信息头发送给服务器
session和cookie应用场景
session上下文机制,针对每一个用户,通过sessionid来区分不同客户。session是以cookie或url重写为基础的,默认使用cookie实现,系统会创造一个名为jsessionid的输出cookie。重要状态走session,不重要走cookie,登陆信息用session,购物车用cookie。
Session是保管在服务器端的,每个用户都会产生一个Session。假如并发访问的用户十分多,会产生十分多的Session,耗费大量的内存。发访问量极高的网站,是不太可能运用Session来追踪客户会话的。Cookie保管在客户端,不占用服务器资源。假如并发阅读的用户十分多,Cookie是很好的选择。
做购物车的时候,有很多数据是要长期保存在客户端的.
有三种简单的办法可以实现:
1.保存在session里,缺点是占用服务器资源
2.保存在cookie里,缺点是不安全.
3.保存在数据库里,缺点是存取数据太慢.
因为购物车一般没什么机密信息,所以适合用cookie来做.
WebStorage
WebStorage的目的是克服由cookie所带来的一些限制,当数据需要被严格控制在客户端时,不需要持续的将数据发回服务器。
WebStorage两个主要目标:
1.提供一种在cookie之外存储会话数据的路径。
2.提供一种存储大量可以跨会话存在的数据的机制。
HTML5的WebStorage提供了两种API:localStorage(本地存储)和sessionStorage(会话存储)。
WebStorage的优点:
- 存储空间更大:cookie为4KB,而WebStorage是5MB;
- 节省网络流量:WebStorage不会传送到服务器,存储在本地的数据可以直接获取,也不会像cookie一样每次请求都会传送到服务器,所以减少了客户端和服务器端的交互,节省了网络流量;
- 对于那种只需要在用户浏览一组页面期间保存而关闭浏览器后就可以丢弃的数据,sessionStorage会非常方便;
- 快速显示:有的数据存储在WebStorage上,再加上浏览器本身的缓存。获取数据时可以从本地获取会比从服务器端获取快得多,所以速度更快;
- 安全性:WebStorage不会随着HTTP header发送到服务器端,所以安全性相对于cookie来说比较高一些,不会担心截获,但是仍然存在伪造问题;
- WebStorage提供了一些方法,数据操作比cookie方便
setItem (key, value) —— 保存数据,以键值对的方式储存信息。
getItem (key) —— 获取数据,将键值传入,即可获取到对应的value值。
removeItem (key) —— 删除单个数据,根据键值移除对应的信息。
clear () —— 删除所有的数据
key (index) —— 获取某个索引的key
持久连接
我们知道 HTTP 协议采用“请求-应答”模式,当使用普通模式,即非 Keep-Alive 模式时,每个请求/应答客户和服务器都要新建一个连接,完成之后立即断开连接(HTTP协议为无连接的协议);当使用 Keep-Alive 模式(又称持久连接、连接重用)时,Keep-Alive 功能使客户端到服务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive 功能避免了建立或者重新建立连接。
在 HTTP 1.0 版本中,并没有官方的标准来规定 Keep-Alive 如何工作,因此实际上它是被附加到 HTTP 1.0协议上,如果客户端浏览器支持 Keep-Alive ,那么就在HTTP请求头中添加一个字段 Connection: Keep-Alive,当服务器收到附带有 Connection: Keep-Alive 的请求时,它也会在响应头中添加一个同样的字段来使用 Keep-Alive 。这样一来,客户端和服务器之间的HTTP连接就会被保持,不会断开(超过 Keep-Alive 规定的时间,意外断电等情况除外),当客户端发送另外一个请求时,就使用这条已经建立的连接。
在 HTTP 1.1 版本中,默认情况下所有连接都被保持,如果加入 "Connection: close" 才关闭。目前大部分浏览器都使用 HTTP 1.1 协议,也就是说默认都会发起 Keep-Alive 的连接请求了,所以是否能完成一个完整的 Keep-Alive 连接就看服务器设置情况。
由于 HTTP 1.0 没有官方的 Keep-Alive 规范,并且也已经基本被淘汰。
HTTP Keep-Alive 简单说就是保持当前的TCP连接,避免了重新建立连接。HTTP 是一个无状态无连接的协议,那么这是不是与 Keep-Alive 冲突?
- Keep-Alive 与无连接的特性冲突,而对于无状态的特性两者并无矛盾,HTTP 无状态无连接是在 1.0 版本中就规定的,而 Keep-Alive 则是在 1.1 版本中才被添加入规范。
- 无连接的意思是限制每个连接只有一个请求的意思,在服务器处理完客户的请求,并收到客户的反应,即断开。通过这种方式可以节省传输时间。
- Keep-Alive 确实破坏了这一特性,而无状态协议则意味着每个请求都是独立的,互不干扰的,互相没有记忆的。所以才需要有会话跟踪这种机制来识别用户。
缓存机制
HTTP 条件 GET 是 HTTP 协议为了减少不必要的带宽浪费,提出的一种方案:
- HTTP 条件 GET 使用时机:客户端之前已经访问过某网站,并打算再次访问该站点。
- HTTP 条件 GET 使用的方法:客户端向服务器发送一个包询问是否在上一次访问网站的时间后是否更改了页面,如果服务器没有更新,显然不需要把整个网页传给客户端,客户端只要使用本地缓存即可,如果服务器对照客户端给出的时间已经更新了客户端请求的网页,则发送这个更新了的网页给用户。
强缓存和协商缓存
https://jayzangwill.github.io/blog/2019/02/07/cache/
https://segmentfault.com/a/1190000017962411