计算机网络
HTTP/1.0 和 HTTP/1.1 的区别
HTTP(Hypertext Transfer Protocol)是用于在Web上传输数据的协议。HTTP/1.0 和 HTTP/1.1 是两个版本的 HTTP 协议,下面是它们之间的一些区别:
- 持久连接:HTTP/1.1 引入了持久连接,这意味着在单个 TCP 连接上可以发送多个请求/响应对,从而减少了每个请求的延迟。HTTP/1.0 在每个请求/响应之后关闭 TCP 连接。
- 块传输编码:HTTP/1.1 支持块传输编码,这意味着可以在接收响应时逐步解压缩数据,而不必等待整个响应。这对于处理大型响应或流式数据非常有用。
- 身份验证:HTTP/1.1 提供了更安全的身份验证方法,例如基于令牌的身份验证方案,可以替代 HTTP/1.0 中的基本身份验证。
- 缓存处理:HTTP/1.1 对缓存处理进行了改进,包括新的 Cache-Control 指令,可以更好地控制缓存行为。
- 响应码:HTTP/1.1 引入了更多的响应码,例如"100 Continue",这使得客户端可以更好地控制它们的请求行为。
- 主机头字段:HTTP/1.1 要求在每个请求中都包含主机头字段,这使得服务器可以更好地处理多个虚拟主机。
- 管道化:HTTP/1.1 支持管道化,允许客户端同时发送多个请求,从而提高性能。HTTP/1.0 不支持管道化。
HTTP/1.1 和 HTTP/2.0 的区别
- 二进制协议:
HTTP1.1
的解析是基于文本,而HTTP2
使用二进制,将请求和响应分割为更小的帧,从而实现多路复用。 - 多路复用:在一个连接里,客户端和服务器都可以同时发送多个请求或回应,而且不用按照顺序一一发送,这样避免了
HTTP
队头阻塞,但是TCP
的队头阻塞依旧存在。 - 头部信息压缩:由于
HTTP1.1
每次请求都会带上所有信息,比如Cookie
,这样会很浪费性能,HTTP2
引入头部压缩,一方面将头部信息使用gzip压缩后再发送,另一方面客户端和服务器同时维护一张头部信息表,所有字段都会存入这张表,生成索引,只发送索引就可以。 - 服务器推送:
HTTP2
允许服务器向客户端主动发送资源,只限于静态资源如css
,img
等
队头阻塞
通常我们说队头阻塞,都是说 TCP,但是 HTTP1.1 中也有一个类似 TCP 队头阻塞的问题
TCP 队头阻塞
TCP 是一种可靠传输,这个可靠就是体现在它能够"按序到达",然后再被上层接收,这里的按序到达指的是最终顺序是按序排列的,也就是说每当有一个或几个 Packet 丢失的时候,会等待它到达后合并,然后再向上交付。
当一个流的第一个数据包丢失了,那么即使后面的数据包都到达了,后面的这些数据包也不能被处理,而是要等第一个数据包到了之后才能被上层接收处理
HTTP 队头阻塞
HTTP 管道化要求服务端必须按照请求发送的顺序返回响应
,那如果一个响应返回延迟了,那么其后续的响应都会被延迟,直到队头的响应送达。
如何解决队头阻塞
对于 HTTP1.1 中管道化
导致的请求/响应级别的队头阻塞,可以使用 HTTP2 解决。HTTP2 不使用管道化的方式,而是引入了帧、消息和数据流
等概念,每个请求/响应被称为消息,每个消息都被拆分成若干个帧进行传输,每个帧都分配一个序号。每个帧在传输是属于一个数据流,而一个连接上可以存在多个流,各个帧在流和连接上独立传输,到达之后在组装成消息,这样就避免了请求/响应阻塞。
当然,即使使用 HTTP2,如果 HTTP2 底层使用的是 TCP 协议,仍可能出现 TCP 队头阻塞。
HTTP/3(HTTP-over-QUIC)
HTTP/2 虽然通过多路复用
解决了 HTTP 层的队头阻塞,但仍然存在 TCP 层的队头阻塞。同时,TCP 以及 TCP + TLS 建立连接存在的延迟(握手延迟)
连接双方的有任一个数据包丢失,或任一方的网络中断,整个 TCP 连接就会暂停,丢失的数据包需要被重新传输,从而阻塞该 TCP 连接中的所有请求,反而在网络较差或不稳定情况下,使用多个连接表现更好。
因此提出了 QUIC 协议,一种基于 UDP
的低延时的互联网传输层协议。
QUIC 基于 UDP 的低时延的互联网传输层协议,HTTP-over-QUIC 于2018年11月更名为 HTTP/3。
HTTP/3 的主要目标是改进网络连接的性能和安全性。
降低延迟
在传统的 HTTP/1.1 和 HTTP/2 中,建立连接需要进行三次握手,这会引入一定的延迟。而在 HTTP/3 中,通过使用 QUIC 协议,可以实现零 RTT(Round-Trip Time)建立连接,即在建立连接的过程中不需要进行额外的往返时间。
QUIC 已经通过将传输和加密握手合并为一个,减少了典型连接握手的完整往返行程。
允许客户端在连接的第一次往返中发送应用程序数据,而无需事先完成任何其他握手。
有序交付
UDP 是不可靠传输协议,(不保证交付,不保证顺序,不保证不重复)
QUIC 在每个数据包都设有一个 offset 字段(偏移量),接收端根据 offset 字段就可以对异步到达的数据包进行排序了,保证了有序性。
队头阻塞
QUIC基于UDP, UDP的数据包在接收端没有处理顺序, 即使中间丢失一个包, 也不会阻塞整条连接. 其他的资源会被正常处理.
HTTP 和 HTTPS 的区别
-
安全性:HTTP 传输的数据是明文的,容易被窃取和篡改,而 HTTPS 使用 SSL/TLS 加密传输数据,可以保证数据的机密性和完整性,防止数据被窃取和篡改
-
端口号:HTTP 默认使用端口号 80,而 HTTPS 默认使用端口号 443
-
证书:HTTPS 使用 SSL/TLS 协议对传输数据进行加密,需要使用证书对网站进行身份验证,防止中间人攻击。HTTP 不需要证书进行身份验证
-
速度:由于 HTTPS 使用 SSL/TLS 加密传输数据,会增加传输数据的时间和带宽消耗,因此速度比 HTTP 慢一些
-
缓存:HTTP 可以使用浏览器缓存来提高访问速度,而 HTTPS 在加密传输数据时会禁止浏览器缓存,以保证数据的安全性(只要在请求头设置,还是可以缓存的)
GET 和 POST 有什么区别
主要从三个方面去回答
- 协议层面(语义差别)
- 应用层面(GET 请求体为空)
- 浏览器层面
浏览器
跨域问题
- cors
- jsonp
- postmessage
- websocket
- Node中间件代理(两次跨越)
- Nginx 反向代理
- window.name + iframe
- location.hash + iframe
- document.domain + iframe
浏览器兼容问题
解释一下浏览器中的同源策略
同源策略是浏览器中一种安全机制,用于限制不同源(域名、协议、端口)之间的交互。同源策略的目的是防止恶意网站通过脚本访问其他网站的敏感数据或执行恶意操作。
同源策略实行以下限制:
Cookie
、LocalStorage
和IndexDB
等存储在浏览器中的数据只能在同源网站中共享。JavaScript
脚本只能访问同源网站的DOM
,不能读取或修改不同源网站的DOM
。XMLHttpRequest
和Fetch
等网络请求只能发起同源请求,不能访问不同源的接口。iframe
内嵌的网页只能与父页面同源的网页进行交互。
但是,如果目标网站明确设置了允许跨域访问的响应头(CORS
),那么浏览器将允许跨源请求。
同源策略的作用在于保护用户的隐私和安全,防止恶意网站获取另一个网站的敏感数据,并防止 CSRF
(跨站请求伪造)等网络攻击。但同时也使得不同源的网站之间受限,为了实现跨域数据的交互,需要使用其他的机制,如CORS
、JSONP
、代理等。
浏览器路由
使用 history 进行导航的时候,页面真的进行了一个切换吗?是怎么做到的
当使用 history 进行导航时,页面并没有进行刷新或重新加载。浏览器是通过修改 URL 地址和浏览器历史记录,
模拟了一个页面的切换效果。
具体来说,使用 history 进行导航时,通常会调用 history.pushState/replaceState 方法,这些方法可以向浏览器历史记录中添加或修改一个记录,并且同时修改当前URL地址。然后浏览器会根据新的 URL 地址重新渲染页面,并且在浏览器的历史记录中添加或修改一个记录。
当使用 history 进行导航时,虽然页面并没有进行刷新或重新加载,但是浏览器会触发一些相关的事件,如 popstate 事件,用来处理导航过程中的一些逻辑。开发者可以在这些事件中添加相关的处理逻辑,从而实现前端路由的功能。
vue 如何监听路由的变化呢?
在 Vue 中 可以使用 Vue Router 提供的导航守卫(Navigation Guards)来监听路由的变化。
导航守卫是 Vue Router 提供的一组钩子函数,可以在路由发生变化时被触发。通过使用导航守卫,开发者可以实现一些常见的路由控制逻辑,如路由权限控制、路由拦截、路由跳转前的确认等等。
Vue Router 提供了三种类型的导航守卫:
- 全局守卫:在整个应用程序中,所有的路由变化都会触发这些守卫。(beforeEach、beforeResolve 和 afterEach)
- 路由独享守卫:在某个路由上,只有该路由变化时才会触发这些守卫。可以在路由配置对象中通过 beforeEnter 属性来注册路由独享守卫。
- 组件内守卫:在某个路由对应的组件中,可以通过 Vue 组件生命周期钩子函数来监听路由的变化,实现一些组件内部的路由控制逻辑。
以下是一个使用全局守卫来监听路由变化的示例:
javascript
javascript
复制代码
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const router = new VueRouter({
routes: [
{ path: '/', component: Home },
{ path: '/about', component: About }
]
})
router.beforeEach((to, from, next) => {
console.log('路由变化:', from.path, ' => ', to.path)
next()
})
没有 hash 的路由如何进行监听
如果使用的是 HTML5 History API 来管理路由,而不是 hash 路由,那么可以通过监听 popstate
事件来实现路由变化的监听。
HTML5 History API 可以使用 pushState()
和 replaceState()
方法来操作浏览器的历史记录,并可以修改当前页面的 URL,而不会导致页面的刷新。
当通过 pushState()
或 replaceState()
方法修改浏览器历史记录时,会触发 popstate
事件。我们可以通过监听这个事件来获取路由的变化。
例如,我们可以使用如下代码来监听路由的变化:
javascript
javascript
复制代码
window.addEventListener('popstate', function(event) {
console.log("当前路由:", window.location.pathname);
});
window.onpopstate = function(event) {
console.log("当前路由:", window.location.pathname);
};
在上面的代码中,当用户通过浏览器前进或后退按钮,或者通过 pushState()
或 replaceState()
方法修改浏览器历史记录时,会触发 popstate
事件,并输出当前路由路径到控制台
注意:这种方式只能监听浏览器历史记录中的路由变化,对于通过 AJAX 或其他方式进行的路由变化是无法监听的。如果需要监听所有的路由变化,可以考虑使用一些现有的路由库,如 React Router、Vue Router 等
onpopstate 可以监听到一个 pushstate 的事件吗
onpopstate
事件只能监听到由浏览器触发的历史记录变化,例如点击浏览器的前进或后退按钮,或者调用 history.back()
或 history.forward()
方法。
如果你在 JavaScript 中调用 history.pushState()
或 history.replaceState()
方法来修改浏览器的历史记录,那么不会触发 onpopstate
事件。但是,调用这两个方法会添加新的历史记录,并且可以在历史记录中回退和前进,这些历史记录变化会触发 onpopstate
事件。
因此,如果你想要在调用 pushState()
或 replaceState()
方法后立即获取路由变化,可以在调用这两个方法后手动触发 popstate
事件,例如
javascript
javascript
复制代码
history.pushState({}, '', '/new-path');
window.dispatchEvent(new PopStateEvent('popstate'));
在上面的代码中,我们先调用 pushState()
方法来修改浏览器的历史记录,并修改当前页面的 URL 为 /new-path
。然后,手动触发 popstate
事件,这会立即触发绑定在 window.onpopstate
上的事件处理函数,并获取到新的路由信息